Stream - Version 3.5.0

Version Description

  • July 8, 2020 =

  • Fix: Stream records now show the correct timestamp instead of dates like -0001/11/30 #1091, props @kidunot89.

  • Fix: Searching Stream records is now more performant as we throttle the amount of search requests #1081, props @oscarssanchez.

  • Tweak: Inline PHP documentation updates and WordPress coding standard fixes, props @kidunot89.

Download this release

Release Info

Developer kasparsd
Plugin Icon 128x128 Stream
Version 3.5.0
Comparing to
See all releases

Code changes from version 3.4.3 to 3.5.0

Files changed (72) hide show
  1. alerts/class-alert-type-ifttt.php +2 -2
  2. alerts/js/alert-type-highlight.js +6 -6
  3. alerts/js/alert-type-highlight.min.js +1 -1
  4. classes/class-admin.php +109 -50
  5. classes/class-alert-trigger.php +2 -2
  6. classes/class-alert-type.php +4 -4
  7. classes/class-alert.php +16 -8
  8. classes/class-alerts-list.php +3 -3
  9. classes/class-alerts.php +10 -10
  10. classes/class-author.php +44 -22
  11. classes/class-cli.php +14 -9
  12. classes/class-connector.php +32 -22
  13. classes/class-connectors.php +42 -17
  14. classes/class-date-interval.php +20 -9
  15. classes/class-db-driver-wpdb.php +16 -7
  16. classes/class-db-driver.php +14 -4
  17. classes/class-db.php +30 -21
  18. classes/class-export.php +15 -4
  19. classes/class-exporter.php +9 -0
  20. classes/class-filter-input.php +59 -11
  21. classes/class-form-generator.php +9 -0
  22. classes/class-install.php +26 -13
  23. classes/class-list-table.php +178 -33
  24. classes/class-live-update.php +23 -14
  25. classes/class-log.php +11 -3
  26. classes/class-network.php +60 -29
  27. classes/class-plugin.php +43 -20
  28. classes/class-preview-list-table.php +8 -0
  29. classes/class-query.php +16 -7
  30. classes/class-record.php +120 -7
  31. classes/class-settings.php +38 -27
  32. classes/class-uninstall.php +40 -24
  33. connectors/class-connector-acf.php +46 -37
  34. connectors/class-connector-bbpress.php +31 -13
  35. connectors/class-connector-blogs.php +40 -31
  36. connectors/class-connector-buddypress.php +315 -47
  37. connectors/class-connector-comments.php +42 -33
  38. connectors/class-connector-edd.php +175 -24
  39. connectors/class-connector-editor.php +23 -9
  40. connectors/class-connector-gravityforms.php +203 -73
  41. connectors/class-connector-installer.php +80 -26
  42. connectors/class-connector-jetpack.php +129 -37
  43. connectors/class-connector-media.php +36 -16
  44. connectors/class-connector-menus.php +31 -19
  45. connectors/class-connector-mercator.php +20 -12
  46. connectors/class-connector-posts.php +39 -30
  47. connectors/class-connector-settings.php +78 -53
  48. connectors/class-connector-taxonomies.php +39 -20
  49. connectors/class-connector-user-switching.php +20 -7
  50. connectors/class-connector-users.php +41 -30
  51. connectors/class-connector-widgets.php +113 -94
  52. connectors/class-connector-woocommerce.php +112 -58
  53. connectors/class-connector-wordpress-seo.php +210 -125
  54. contributing.md +1 -1
  55. exporters/class-exporter-csv.php +9 -0
  56. exporters/class-exporter-json.php +9 -0
  57. includes/db-updates.php +13 -7
  58. includes/feeds/atom.php +7 -1
  59. includes/feeds/json.php +8 -2
  60. includes/feeds/rss-2.0.php +7 -1
  61. includes/functions.php +16 -15
  62. includes/lib/Carbon.php +7 -7
  63. readme.md +1 -0
  64. readme.txt +19 -9
  65. stream.php +3 -1
  66. ui/js/admin.js +1 -0
  67. ui/js/admin.min.js +1 -1
  68. ui/js/alerts.min.js +1 -1
  69. ui/js/exclude.min.js +1 -1
  70. ui/js/global.min.js +1 -1
  71. ui/js/live-updates.min.js +1 -1
  72. ui/js/settings.min.js +1 -1
alerts/class-alert-type-ifttt.php CHANGED
@@ -208,7 +208,7 @@ class Alert_Type_IFTTT extends Alert_Type {
208
  $record_data = wp_parse_args(
209
  $recordarr,
210
  array(
211
- // translators: Placeholder refers to the Event Name of the Alert (e.g. "Update a post")
212
  'summary' => sprintf( __( 'The event %s was triggered' ), $alert->alert_meta['event_name'] ),
213
  'user_id' => get_current_user_id(),
214
  'created' => current_time( 'Y-m-d H:i:s' ),
@@ -242,7 +242,7 @@ class Alert_Type_IFTTT extends Alert_Type {
242
  * @return string
243
  */
244
  $date_format = apply_filters( 'wp_stream_alert_ifttt_date_format', 'Y-m-d H:i:s', $alert, $recordarr );
245
- $date = date( $date_format, strtotime( $created ) );
246
 
247
  $url = 'https://maker.ifttt.com/trigger/' . $alert->alert_meta['event_name'] . '/with/key/' . $alert->alert_meta['maker_key'];
248
 
208
  $record_data = wp_parse_args(
209
  $recordarr,
210
  array(
211
+ /* translators: %s: the Event Name of the Alert (e.g. "Update a post") */
212
  'summary' => sprintf( __( 'The event %s was triggered' ), $alert->alert_meta['event_name'] ),
213
  'user_id' => get_current_user_id(),
214
  'created' => current_time( 'Y-m-d H:i:s' ),
242
  * @return string
243
  */
244
  $date_format = apply_filters( 'wp_stream_alert_ifttt_date_format', 'Y-m-d H:i:s', $alert, $recordarr );
245
+ $date = gmdate( $date_format, strtotime( $created ) );
246
 
247
  $url = 'https://maker.ifttt.com/trigger/' . $alert->alert_meta['event_name'] . '/with/key/' . $alert->alert_meta['maker_key'];
248
 
alerts/js/alert-type-highlight.js CHANGED
@@ -25,10 +25,10 @@ var streamAlertTypeHighlight = ( function( $ ) {
25
  var actionLink = $( this );
26
 
27
  /**
28
- * Ajax call to remove the highlight.
29
- *
30
- * @returns void.
31
- */
32
  actionLink.click(
33
  function( e ) {
34
  var recordId, data;
@@ -51,8 +51,8 @@ var streamAlertTypeHighlight = ( function( $ ) {
51
  );
52
 
53
  /**
54
- * Fires when Ajax complete.
55
- */
56
  function ajaxDone() {
57
  var row = actionLink.parents( '.alert-highlight' ),
58
  odd = $( '.striped > tbody > :nth-child( odd )' );
25
  var actionLink = $( this );
26
 
27
  /**
28
+ * Ajax call to remove the highlight.
29
+ *
30
+ * @return void.
31
+ */
32
  actionLink.click(
33
  function( e ) {
34
  var recordId, data;
51
  );
52
 
53
  /**
54
+ * Fires when Ajax complete.
55
+ */
56
  function ajaxDone() {
57
  var row = actionLink.parents( '.alert-highlight' ),
58
  odd = $( '.striped > tbody > :nth-child( odd )' );
alerts/js/alert-type-highlight.min.js CHANGED
@@ -1 +1 @@
1
- var streamAlertTypeHighlight=function(t){var e={ajaxUrl:"",removeAction:"",security:""};return"undefined"!=typeof _streamAlertTypeHighlightExports&&t.extend(e,_streamAlertTypeHighlightExports),e.init=function(){t(document).ready(function(){t('.alert-highlight .action-link[href="#"]').each(function(){var r=t(this);r.click(function(i){function n(){var e=r.parents(".alert-highlight"),i=t(".striped > tbody > :nth-child( odd )");e.is(i)?e.animate({backgroundColor:"#f9f9f9"},300,function(){e.removeClass("alert-highlight")}):e.animate({backgroundColor:""},300,function(){e.removeClass("alert-highlight")}),r.remove()}var a,o;i.preventDefault(),a=(a=r.parents(".alert-highlight").attr("class").match(/record\-id\-[\w-]*\b/))[0].replace("record-id-",""),o={action:e.removeAction,security:e.security,recordId:a},t.post(e.ajaxUrl,o,function(t){!0===t.success&&n()})})})})},e}(jQuery);
1
+ var streamAlertTypeHighlight=function(n){var a={ajaxUrl:"",removeAction:"",security:""};return"undefined"!=typeof _streamAlertTypeHighlightExports&&n.extend(a,_streamAlertTypeHighlightExports),a.init=function(){n(document).ready(function(){n('.alert-highlight .action-link[href="#"]').each(function(){var i=n(this);i.click(function(t){var e,r;t.preventDefault(),e=(e=i.parents(".alert-highlight").attr("class").match(/record\-id\-[\w-]*\b/))[0].replace("record-id-",""),r={action:a.removeAction,security:a.security,recordId:e},n.post(a.ajaxUrl,r,function(t){!0===t.success&&function(){var t=i.parents(".alert-highlight"),e=n(".striped > tbody > :nth-child( odd )");t.is(e)?t.animate({backgroundColor:"#f9f9f9"},300,function(){t.removeClass("alert-highlight")}):t.animate({backgroundColor:""},300,function(){t.removeClass("alert-highlight")});i.remove()}()})})})})},a}(jQuery);
classes/class-admin.php CHANGED
@@ -1,4 +1,9 @@
1
  <?php
 
 
 
 
 
2
 
3
  namespace WP_Stream;
4
 
@@ -8,10 +13,13 @@ use DateInterval;
8
  use \WP_CLI;
9
  use \WP_Roles;
10
 
 
 
 
11
  class Admin {
12
 
13
  /**
14
- * Hold Plugin class
15
  *
16
  * @var Plugin
17
  */
@@ -118,7 +126,7 @@ class Admin {
118
  /**
119
  * Class constructor.
120
  *
121
- * @param Plugin $plugin The main Plugin class.
122
  */
123
  public function __construct( $plugin ) {
124
  $this->plugin = $plugin;
@@ -183,7 +191,11 @@ class Admin {
183
  )
184
  );
185
 
186
- // Uninstall Streams and Deactivate plugin.
 
 
 
 
187
  $uninstall = $this->plugin->db->driver->purge_storage( $this->plugin );
188
 
189
  // Auto purge setup.
@@ -242,7 +254,7 @@ class Admin {
242
  */
243
  public function notice( $message, $is_error = true ) {
244
  if ( defined( 'WP_CLI' ) && WP_CLI ) {
245
- $message = strip_tags( $message );
246
 
247
  if ( $is_error ) {
248
  WP_CLI::warning( $message );
@@ -380,7 +392,7 @@ class Admin {
380
  *
381
  * @action admin_enqueue_scripts
382
  *
383
- * @param string $hook
384
  *
385
  * @return void
386
  */
@@ -393,9 +405,21 @@ class Admin {
393
  $file_tmpl = 'ui/lib/timeago/locales/jquery.timeago.%s.js';
394
 
395
  if ( file_exists( $this->plugin->locations['dir'] . sprintf( $file_tmpl, $locale ) ) ) {
396
- wp_register_script( 'wp-stream-timeago-locale', $this->plugin->locations['url'] . sprintf( $file_tmpl, $locale ), array( 'wp-stream-timeago' ), '1' );
 
 
 
 
 
 
397
  } else {
398
- wp_register_script( 'wp-stream-timeago-locale', $this->plugin->locations['url'] . sprintf( $file_tmpl, 'en' ), array( 'wp-stream-timeago' ), '1' );
 
 
 
 
 
 
399
  }
400
 
401
  $min = wp_stream_min_suffix();
@@ -417,7 +441,8 @@ class Admin {
417
  'jquery',
418
  'wp-stream-select2',
419
  ),
420
- $this->plugin->get_version()
 
421
  );
422
  wp_enqueue_script(
423
  'wp-stream-admin-exclude',
@@ -426,7 +451,8 @@ class Admin {
426
  'jquery',
427
  'wp-stream-select2',
428
  ),
429
- $this->plugin->get_version()
 
430
  );
431
  wp_enqueue_script(
432
  'wp-stream-live-updates',
@@ -435,7 +461,8 @@ class Admin {
435
  'jquery',
436
  'heartbeat',
437
  ),
438
- $this->plugin->get_version()
 
439
  );
440
 
441
  wp_localize_script(
@@ -452,19 +479,19 @@ class Admin {
452
  )
453
  );
454
 
 
 
455
  wp_localize_script(
456
  'wp-stream-live-updates',
457
  'wp_stream_live_updates',
458
  array(
459
  'current_screen' => $hook,
460
- 'current_page' => isset( $_GET['paged'] ) ? esc_js( $_GET['paged'] ) : '1', // WPCS: CSRF ok.
461
- // input var okay, CSRF okay
462
- 'current_order' => isset( $_GET['order'] ) ? esc_js( $_GET['order'] ) : 'desc', // WPCS: CSRF ok.
463
- // input var okay, CSRF okay
464
- 'current_query' => wp_stream_json_encode( $_GET ), // WPCS: CSRF ok.
465
- // input var okay, CSRF okay
466
- 'current_query_count' => count( $_GET ), // WPCS: CSRF ok.
467
- // input var okay, CSRF okay
468
  )
469
  );
470
  }
@@ -483,14 +510,21 @@ class Admin {
483
  */
484
  $bulk_actions_threshold = apply_filters( 'wp_stream_bulk_actions_threshold', 100 );
485
 
486
- wp_enqueue_script( 'wp-stream-global', $this->plugin->locations['url'] . 'ui/js/global.' . $min . 'js', array( 'jquery' ), $this->plugin->get_version() );
 
 
 
 
 
 
 
487
  wp_localize_script(
488
  'wp-stream-global',
489
  'wp_stream_global',
490
  array(
491
  'bulk_actions' => array(
492
  'i18n' => array(
493
- // translators: Placeholder refers to a number of items (e.g. "1,742")
494
  'confirm_action' => sprintf( esc_html__( 'Are you sure you want to perform bulk actions on over %s items? This process could take a while to complete.', 'stream' ), number_format( absint( $bulk_actions_threshold ) ) ),
495
  ),
496
  'threshold' => absint( $bulk_actions_threshold ),
@@ -521,7 +555,7 @@ class Admin {
521
  /**
522
  * Add a specific body class to all Stream admin screens
523
  *
524
- * @param string $classes CSS classes to output to body
525
  *
526
  * @filter admin_body_class
527
  *
@@ -533,8 +567,8 @@ class Admin {
533
  if ( $this->is_stream_screen() ) {
534
  $stream_classes[] = $this->admin_body_class;
535
 
536
- if ( isset( $_GET['page'] ) ) { // CSRF okay
537
- $stream_classes[] = sanitize_key( $_GET['page'] ); // input var okay, CSRF okay
538
  }
539
  }
540
 
@@ -561,7 +595,7 @@ class Admin {
561
  wp_register_style( 'wp-stream-datepicker', $this->plugin->locations['url'] . 'ui/css/datepicker.' . $min . 'css', array(), $this->plugin->get_version() );
562
  wp_register_style( 'wp-stream-icons', $this->plugin->locations['url'] . 'ui/stream-icons/style.css', array(), $this->plugin->get_version() );
563
 
564
- // Make sure we're working off a clean version
565
  if ( ! file_exists( ABSPATH . WPINC . '/version.php' ) ) {
566
  return;
567
  }
@@ -646,7 +680,7 @@ class Admin {
646
  return true;
647
  }
648
 
649
- wp_redirect(
650
  add_query_arg(
651
  array(
652
  'page' => is_network_admin() ? $this->network->network_settings_page_slug : $this->settings_page_slug,
@@ -659,6 +693,11 @@ class Admin {
659
  exit;
660
  }
661
 
 
 
 
 
 
662
  private function erase_stream_records() {
663
  global $wpdb;
664
 
@@ -677,16 +716,26 @@ class Admin {
677
  );
678
  }
679
 
 
 
 
 
 
680
  public function purge_schedule_setup() {
681
  if ( ! wp_next_scheduled( 'wp_stream_auto_purge' ) ) {
682
  wp_schedule_event( time(), 'twicedaily', 'wp_stream_auto_purge' );
683
  }
684
  }
685
 
 
 
 
 
 
686
  public function purge_scheduled_action() {
687
  global $wpdb;
688
 
689
- // Don't purge when in Network Admin unless Stream is network activated
690
  if (
691
  is_multisite()
692
  &&
@@ -715,7 +764,7 @@ class Admin {
715
 
716
  $where = $wpdb->prepare( ' AND `stream`.`created` < %s', $date->format( 'Y-m-d H:i:s' ) );
717
 
718
- // Multisite but NOT network activated, only purge the current blog
719
  if ( is_multisite() && ! $this->plugin->is_network_activated() ) {
720
  $where .= $wpdb->prepare( ' AND `blog_id` = %d', get_current_blog_id() );
721
  }
@@ -730,11 +779,13 @@ class Admin {
730
  }
731
 
732
  /**
733
- * @param array $links
734
- * @param string $file
735
  *
736
  * @filter plugin_action_links
737
  *
 
 
 
738
  * @return array
739
  */
740
  public function plugin_action_links( $links, $file ) {
@@ -742,7 +793,7 @@ class Admin {
742
  return $links;
743
  }
744
 
745
- // Also don't show links in Network Admin if Stream isn't network enabled
746
  if ( is_network_admin() && is_multisite() && ! $this->plugin->is_network_activated() ) {
747
  return $links;
748
  }
@@ -868,7 +919,7 @@ class Admin {
868
  /**
869
  * Check if a particular role has access
870
  *
871
- * @param string $role
872
  *
873
  * @return bool
874
  */
@@ -883,10 +934,10 @@ class Admin {
883
  /**
884
  * Filter user caps to dynamically grant our view cap based on allowed roles
885
  *
886
- * @param $allcaps
887
- * @param $caps
888
- * @param $args
889
- * @param $user
890
  *
891
  * @filter user_has_cap
892
  *
@@ -933,9 +984,9 @@ class Admin {
933
  *
934
  * @filter role_has_cap
935
  *
936
- * @param $allcaps
937
- * @param $cap
938
- * @param $role
939
  *
940
  * @return array
941
  */
@@ -950,6 +1001,8 @@ class Admin {
950
  }
951
 
952
  /**
 
 
953
  * @action wp_ajax_wp_stream_filters
954
  */
955
  public function ajax_filters() {
@@ -985,19 +1038,25 @@ class Admin {
985
  $users = array_slice( $users, 0, $this->preload_users_max );
986
  }
987
 
988
- // Get gravatar / roles for final result set
989
  $results = $this->get_users_record_meta( $users );
990
 
991
  break;
992
  }
993
 
994
  if ( isset( $results ) ) {
995
- echo wp_stream_json_encode( $results ); // xss ok
996
  }
997
 
998
  die();
999
  }
1000
 
 
 
 
 
 
 
1001
  public function get_users_record_meta( $authors ) {
1002
  $authors_records = array();
1003
 
@@ -1019,9 +1078,9 @@ class Admin {
1019
  /**
1020
  * Get user meta in a way that is also safe for VIP
1021
  *
1022
- * @param int $user_id
1023
- * @param string $meta_key
1024
- * @param bool $single (optional)
1025
  *
1026
  * @return mixed
1027
  */
@@ -1036,10 +1095,10 @@ class Admin {
1036
  /**
1037
  * Update user meta in a way that is also safe for VIP
1038
  *
1039
- * @param int $user_id
1040
- * @param string $meta_key
1041
- * @param mixed $meta_value
1042
- * @param mixed $prev_value (optional)
1043
  *
1044
  * @return int|bool
1045
  */
@@ -1054,9 +1113,9 @@ class Admin {
1054
  /**
1055
  * Delete user meta in a way that is also safe for VIP
1056
  *
1057
- * @param int $user_id
1058
- * @param string $meta_key
1059
- * @param mixed $meta_value (optional)
1060
  *
1061
  * @return bool
1062
  */
1
  <?php
2
+ /**
3
+ * Centralized manager for WordPress backend functionality.
4
+ *
5
+ * @package WP_Stream
6
+ */
7
 
8
  namespace WP_Stream;
9
 
13
  use \WP_CLI;
14
  use \WP_Roles;
15
 
16
+ /**
17
+ * Class - Admin
18
+ */
19
  class Admin {
20
 
21
  /**
22
+ * Holds Instance of plugin object
23
  *
24
  * @var Plugin
25
  */
126
  /**
127
  * Class constructor.
128
  *
129
+ * @param Plugin $plugin Instance of plugin object.
130
  */
131
  public function __construct( $plugin ) {
132
  $this->plugin = $plugin;
191
  )
192
  );
193
 
194
+ /**
195
+ * Uninstall Streams and Deactivate plugin.
196
+ *
197
+ * @todo Confirm if variable assignment is necessary.
198
+ */
199
  $uninstall = $this->plugin->db->driver->purge_storage( $this->plugin );
200
 
201
  // Auto purge setup.
254
  */
255
  public function notice( $message, $is_error = true ) {
256
  if ( defined( 'WP_CLI' ) && WP_CLI ) {
257
+ $message = wp_strip_all_tags( $message );
258
 
259
  if ( $is_error ) {
260
  WP_CLI::warning( $message );
392
  *
393
  * @action admin_enqueue_scripts
394
  *
395
+ * @param string $hook Current hook.
396
  *
397
  * @return void
398
  */
405
  $file_tmpl = 'ui/lib/timeago/locales/jquery.timeago.%s.js';
406
 
407
  if ( file_exists( $this->plugin->locations['dir'] . sprintf( $file_tmpl, $locale ) ) ) {
408
+ wp_register_script(
409
+ 'wp-stream-timeago-locale',
410
+ $this->plugin->locations['url'] . sprintf( $file_tmpl, $locale ),
411
+ array( 'wp-stream-timeago' ),
412
+ '1',
413
+ false
414
+ );
415
  } else {
416
+ wp_register_script(
417
+ 'wp-stream-timeago-locale',
418
+ $this->plugin->locations['url'] . sprintf( $file_tmpl, 'en' ),
419
+ array( 'wp-stream-timeago' ),
420
+ '1',
421
+ false
422
+ );
423
  }
424
 
425
  $min = wp_stream_min_suffix();
441
  'jquery',
442
  'wp-stream-select2',
443
  ),
444
+ $this->plugin->get_version(),
445
+ false
446
  );
447
  wp_enqueue_script(
448
  'wp-stream-admin-exclude',
451
  'jquery',
452
  'wp-stream-select2',
453
  ),
454
+ $this->plugin->get_version(),
455
+ false
456
  );
457
  wp_enqueue_script(
458
  'wp-stream-live-updates',
461
  'jquery',
462
  'heartbeat',
463
  ),
464
+ $this->plugin->get_version(),
465
+ false
466
  );
467
 
468
  wp_localize_script(
479
  )
480
  );
481
 
482
+ $order_types = array( 'asc', 'desc' );
483
+
484
  wp_localize_script(
485
  'wp-stream-live-updates',
486
  'wp_stream_live_updates',
487
  array(
488
  'current_screen' => $hook,
489
+ 'current_page' => isset( $_GET['paged'] ) ? absint( wp_unslash( $_GET['paged'] ) ) : '1', // phpcs:ignore WordPress.Security.NonceVerification.Recommended
490
+ 'current_order' => isset( $_GET['order'] ) && in_array( strtolower( $_GET['order'] ), $order_types, true ) // phpcs:ignore WordPress.Security.NonceVerification.Recommended
491
+ ? esc_js( $_GET['order'] ) // phpcs:ignore WordPress.Security.NonceVerification.Recommended
492
+ : 'desc',
493
+ 'current_query' => wp_stream_json_encode( $_GET ), // phpcs:ignore WordPress.Security.NonceVerification.Recommended
494
+ 'current_query_count' => count( $_GET ), // phpcs:ignore WordPress.Security.NonceVerification.Recommended
 
 
495
  )
496
  );
497
  }
510
  */
511
  $bulk_actions_threshold = apply_filters( 'wp_stream_bulk_actions_threshold', 100 );
512
 
513
+ wp_enqueue_script(
514
+ 'wp-stream-global',
515
+ $this->plugin->locations['url'] . 'ui/js/global.' . $min . 'js',
516
+ array( 'jquery' ),
517
+ $this->plugin->get_version(),
518
+ false
519
+ );
520
+
521
  wp_localize_script(
522
  'wp-stream-global',
523
  'wp_stream_global',
524
  array(
525
  'bulk_actions' => array(
526
  'i18n' => array(
527
+ /* translators: %s: a number of items (e.g. "1,742") */
528
  'confirm_action' => sprintf( esc_html__( 'Are you sure you want to perform bulk actions on over %s items? This process could take a while to complete.', 'stream' ), number_format( absint( $bulk_actions_threshold ) ) ),
529
  ),
530
  'threshold' => absint( $bulk_actions_threshold ),
555
  /**
556
  * Add a specific body class to all Stream admin screens
557
  *
558
+ * @param string $classes CSS classes to output to body.
559
  *
560
  * @filter admin_body_class
561
  *
567
  if ( $this->is_stream_screen() ) {
568
  $stream_classes[] = $this->admin_body_class;
569
 
570
+ if ( isset( $_GET['page'] ) ) { // // phpcs:ignore WordPress.Security.NonceVerification.Recommended
571
+ $stream_classes[] = sanitize_key( $_GET['page'] ); // phpcs:ignore WordPress.Security.NonceVerification.Recommended
572
  }
573
  }
574
 
595
  wp_register_style( 'wp-stream-datepicker', $this->plugin->locations['url'] . 'ui/css/datepicker.' . $min . 'css', array(), $this->plugin->get_version() );
596
  wp_register_style( 'wp-stream-icons', $this->plugin->locations['url'] . 'ui/stream-icons/style.css', array(), $this->plugin->get_version() );
597
 
598
+ // Make sure we're working off a clean version.
599
  if ( ! file_exists( ABSPATH . WPINC . '/version.php' ) ) {
600
  return;
601
  }
680
  return true;
681
  }
682
 
683
+ wp_safe_redirect(
684
  add_query_arg(
685
  array(
686
  'page' => is_network_admin() ? $this->network->network_settings_page_slug : $this->settings_page_slug,
693
  exit;
694
  }
695
 
696
+ /**
697
+ * Clears stream records from the database.
698
+ *
699
+ * @return void
700
+ */
701
  private function erase_stream_records() {
702
  global $wpdb;
703
 
716
  );
717
  }
718
 
719
+ /**
720
+ * Schedules a purge of records.
721
+ *
722
+ * @return void
723
+ */
724
  public function purge_schedule_setup() {
725
  if ( ! wp_next_scheduled( 'wp_stream_auto_purge' ) ) {
726
  wp_schedule_event( time(), 'twicedaily', 'wp_stream_auto_purge' );
727
  }
728
  }
729
 
730
+ /**
731
+ * Executes a scheduled purge
732
+ *
733
+ * @return void
734
+ */
735
  public function purge_scheduled_action() {
736
  global $wpdb;
737
 
738
+ // Don't purge when in Network Admin unless Stream is network activated.
739
  if (
740
  is_multisite()
741
  &&
764
 
765
  $where = $wpdb->prepare( ' AND `stream`.`created` < %s', $date->format( 'Y-m-d H:i:s' ) );
766
 
767
+ // Multisite but NOT network activated, only purge the current blog.
768
  if ( is_multisite() && ! $this->plugin->is_network_activated() ) {
769
  $where .= $wpdb->prepare( ' AND `blog_id` = %d', get_current_blog_id() );
770
  }
779
  }
780
 
781
  /**
782
+ * Returns the admin action links.
 
783
  *
784
  * @filter plugin_action_links
785
  *
786
+ * @param array $links Action links.
787
+ * @param string $file Plugin file.
788
+ *
789
  * @return array
790
  */
791
  public function plugin_action_links( $links, $file ) {
793
  return $links;
794
  }
795
 
796
+ // Also don't show links in Network Admin if Stream isn't network enabled.
797
  if ( is_network_admin() && is_multisite() && ! $this->plugin->is_network_activated() ) {
798
  return $links;
799
  }
919
  /**
920
  * Check if a particular role has access
921
  *
922
+ * @param string $role User role.
923
  *
924
  * @return bool
925
  */
934
  /**
935
  * Filter user caps to dynamically grant our view cap based on allowed roles
936
  *
937
+ * @param array $allcaps All capabilities.
938
+ * @param array $caps Required caps.
939
+ * @param array $args Unused.
940
+ * @param WP_User $user User.
941
  *
942
  * @filter user_has_cap
943
  *
984
  *
985
  * @filter role_has_cap
986
  *
987
+ * @param array $allcaps All capabilities.
988
+ * @param string $cap Require cap.
989
+ * @param string $role User role.
990
  *
991
  * @return array
992
  */
1001
  }
1002
 
1003
  /**
1004
+ * Ajax callback for return a user list.
1005
+ *
1006
  * @action wp_ajax_wp_stream_filters
1007
  */
1008
  public function ajax_filters() {
1038
  $users = array_slice( $users, 0, $this->preload_users_max );
1039
  }
1040
 
1041
+ // Get gravatar / roles for final result set.
1042
  $results = $this->get_users_record_meta( $users );
1043
 
1044
  break;
1045
  }
1046
 
1047
  if ( isset( $results ) ) {
1048
+ echo wp_stream_json_encode( $results ); // xss ok.
1049
  }
1050
 
1051
  die();
1052
  }
1053
 
1054
+ /**
1055
+ * Return relevant user meta data.
1056
+ *
1057
+ * @param array $authors Author data.
1058
+ * @return array
1059
+ */
1060
  public function get_users_record_meta( $authors ) {
1061
  $authors_records = array();
1062
 
1078
  /**
1079
  * Get user meta in a way that is also safe for VIP
1080
  *
1081
+ * @param int $user_id User ID.
1082
+ * @param string $meta_key Meta key.
1083
+ * @param bool $single Return first found meta value connected to the meta key (optional).
1084
  *
1085
  * @return mixed
1086
  */
1095
  /**
1096
  * Update user meta in a way that is also safe for VIP
1097
  *
1098
+ * @param int $user_id User ID.
1099
+ * @param string $meta_key Meta key.
1100
+ * @param mixed $meta_value Meta value.
1101
+ * @param mixed $prev_value Previous meta value being overwritten (optional).
1102
  *
1103
  * @return int|bool
1104
  */
1113
  /**
1114
  * Delete user meta in a way that is also safe for VIP
1115
  *
1116
+ * @param int $user_id User ID.
1117
+ * @param string $meta_key Meta key.
1118
+ * @param mixed $meta_value Meta value (optional).
1119
  *
1120
  * @return bool
1121
  */
classes/class-alert-trigger.php CHANGED
@@ -15,7 +15,7 @@ namespace WP_Stream;
15
  abstract class Alert_Trigger {
16
 
17
  /**
18
- * Hold the Plugin class
19
  *
20
  * @var Plugin
21
  */
@@ -31,7 +31,7 @@ abstract class Alert_Trigger {
31
  /**
32
  * Class constructor
33
  *
34
- * @param Plugin $plugin Plugin class.
35
  */
36
  public function __construct( $plugin ) {
37
  $this->plugin = $plugin;
15
  abstract class Alert_Trigger {
16
 
17
  /**
18
+ * Holds instance of plugin object
19
  *
20
  * @var Plugin
21
  */
31
  /**
32
  * Class constructor
33
  *
34
+ * @param Plugin $plugin Instance of plugin object.
35
  */
36
  public function __construct( $plugin ) {
37
  $this->plugin = $plugin;
classes/class-alert-type.php CHANGED
@@ -17,7 +17,7 @@ namespace WP_Stream;
17
  abstract class Alert_Type {
18
 
19
  /**
20
- * Hold the Plugin class
21
  *
22
  * @var Plugin
23
  */
@@ -54,7 +54,7 @@ abstract class Alert_Type {
54
  * @param Alert $alert Alert currently being worked on.
55
  */
56
  public function display_fields( $alert ) {
57
- // Implementation optional, but recommended
58
  }
59
 
60
  /**
@@ -63,7 +63,7 @@ abstract class Alert_Type {
63
  * @param Alert $alert Alert currently being worked on.
64
  */
65
  public function save_fields( $alert ) {
66
- // Implementation optional, but recommended
67
  }
68
 
69
  /**
@@ -72,7 +72,7 @@ abstract class Alert_Type {
72
  * @return bool
73
  */
74
  public function is_dependency_satisfied() {
75
- // Implementation optional, but recommended
76
  return true;
77
  }
78
  }
17
  abstract class Alert_Type {
18
 
19
  /**
20
+ * Holds instance of plugin object
21
  *
22
  * @var Plugin
23
  */
54
  * @param Alert $alert Alert currently being worked on.
55
  */
56
  public function display_fields( $alert ) {
57
+ // Implementation optional, but recommended.
58
  }
59
 
60
  /**
63
  * @param Alert $alert Alert currently being worked on.
64
  */
65
  public function save_fields( $alert ) {
66
+ // Implementation optional, but recommended.
67
  }
68
 
69
  /**
72
  * @return bool
73
  */
74
  public function is_dependency_satisfied() {
75
+ // Implementation optional, but recommended.
76
  return true;
77
  }
78
  }
classes/class-alert.php CHANGED
@@ -1,6 +1,6 @@
1
  <?php
2
  /**
3
- * Single Alert handler.
4
  *
5
  * @package WP_Stream
6
  */
@@ -57,7 +57,7 @@ class Alert {
57
  public $alert_meta;
58
 
59
  /**
60
- * Hold Plugin class
61
  *
62
  * @var Plugin
63
  */
@@ -67,7 +67,7 @@ class Alert {
67
  * Class constructor
68
  *
69
  * @param object $item Alert data.
70
- * @param Plugin $plugin Plugin class.
71
  * @return void
72
  */
73
  public function __construct( $item, $plugin ) {
@@ -83,8 +83,9 @@ class Alert {
83
  }
84
 
85
  /**
86
- * Save state of the Alert to database
87
  *
 
88
  * @return int The Post ID of the alert.
89
  */
90
  public function save() {
@@ -99,15 +100,18 @@ class Alert {
99
  'post_type' => Alerts::POST_TYPE,
100
  );
101
 
 
102
  if ( empty( $args['ID'] ) ) {
103
  unset( $args['ID'] );
104
  }
105
 
 
106
  $post_id = wp_insert_post( $args );
107
  if ( empty( $args['ID'] ) ) {
108
  $this->ID = $post_id;
109
  }
110
 
 
111
  $meta = array(
112
  'alert_type' => $this->alert_type,
113
  'alert_meta' => $this->alert_meta,
@@ -123,6 +127,8 @@ class Alert {
123
  /**
124
  * Process settings form data
125
  *
 
 
126
  * @param array $data Processed post object data.
127
  * @return array New post object data.
128
  */
@@ -201,7 +207,7 @@ class Alert {
201
  }
202
 
203
  /**
204
- * Retrive current alert type object
205
  *
206
  * @return Alert_Type
207
  */
@@ -230,7 +236,6 @@ class Alert {
230
  *
231
  * @param int $record_id Record ID.
232
  * @param int $recordarr Record Data.
233
- * @return void
234
  */
235
  public function send_alert( $record_id, $recordarr ) {
236
  $this->get_alert_type_obj()->alert( $record_id, $recordarr, $this );
@@ -319,8 +324,11 @@ class Alert {
319
  return false;
320
  }
321
 
322
- // Grab an Alert post ID.
323
- // @todo determine which Alert post takes priority.
 
 
 
324
  if ( is_array( $values ) ) {
325
  $post_id = $values[0];
326
  } else {
1
  <?php
2
  /**
3
+ * Manages a single alert, acting as a model.
4
  *
5
  * @package WP_Stream
6
  */
57
  public $alert_meta;
58
 
59
  /**
60
+ * Holds instance of plugin object
61
  *
62
  * @var Plugin
63
  */
67
  * Class constructor
68
  *
69
  * @param object $item Alert data.
70
+ * @param Plugin $plugin Instance of plugin object.
71
  * @return void
72
  */
73
  public function __construct( $item, $plugin ) {
83
  }
84
 
85
  /**
86
+ * Saves alert state.
87
  *
88
+ * @todo Clean up/Remove unnecessary conditional statements.
89
  * @return int The Post ID of the alert.
90
  */
91
  public function save() {
100
  'post_type' => Alerts::POST_TYPE,
101
  );
102
 
103
+ // Remove empty "ID" field, if new post.
104
  if ( empty( $args['ID'] ) ) {
105
  unset( $args['ID'] );
106
  }
107
 
108
+ // Create or update alert and assign the ID.
109
  $post_id = wp_insert_post( $args );
110
  if ( empty( $args['ID'] ) ) {
111
  $this->ID = $post_id;
112
  }
113
 
114
+ // Save alert type and meta.
115
  $meta = array(
116
  'alert_type' => $this->alert_type,
117
  'alert_meta' => $this->alert_meta,
127
  /**
128
  * Process settings form data
129
  *
130
+ * @todo Confirm if the function is necessary, it's currently unreference
131
+ * anywhere else in the plugin.
132
  * @param array $data Processed post object data.
133
  * @return array New post object data.
134
  */
207
  }
208
 
209
  /**
210
+ * Retreive current alert type object
211
  *
212
  * @return Alert_Type
213
  */
236
  *
237
  * @param int $record_id Record ID.
238
  * @param int $recordarr Record Data.
 
239
  */
240
  public function send_alert( $record_id, $recordarr ) {
241
  $this->get_alert_type_obj()->alert( $record_id, $recordarr, $this );
324
  return false;
325
  }
326
 
327
+ /**
328
+ * Grab an Alert post ID.
329
+ *
330
+ * @todo Determine which Alert post takes priority.
331
+ */
332
  if ( is_array( $values ) ) {
333
  $post_id = $values[0];
334
  } else {
classes/class-alerts-list.php CHANGED
@@ -14,7 +14,7 @@ namespace WP_Stream;
14
  */
15
  class Alerts_List {
16
  /**
17
- * Hold the Plugin class
18
  *
19
  * @var Plugin
20
  */
@@ -23,7 +23,7 @@ class Alerts_List {
23
  /**
24
  * Class constructor.
25
  *
26
- * @param Plugin $plugin The main Plugin class.
27
  */
28
  public function __construct( $plugin ) {
29
  $this->plugin = $plugin;
@@ -356,7 +356,7 @@ class Alerts_List {
356
  wp_register_style(
357
  'wp-stream-alerts-list-css',
358
  $this->plugin->locations['url'] . 'ui/css/alerts-list.' . $min . 'css',
359
- [],
360
  $this->plugin->get_version()
361
  );
362
 
14
  */
15
  class Alerts_List {
16
  /**
17
+ * Holds instance of plugin object
18
  *
19
  * @var Plugin
20
  */
23
  /**
24
  * Class constructor.
25
  *
26
+ * @param Plugin $plugin Instance of plugin object.
27
  */
28
  public function __construct( $plugin ) {
29
  $this->plugin = $plugin;
356
  wp_register_style(
357
  'wp-stream-alerts-list-css',
358
  $this->plugin->locations['url'] . 'ui/css/alerts-list.' . $min . 'css',
359
+ array(),
360
  $this->plugin->get_version()
361
  );
362
 
classes/class-alerts.php CHANGED
@@ -25,7 +25,7 @@ class Alerts {
25
  const ALERTS_TRIGGERED_META_KEY = 'wp_stream_alerts_triggered';
26
 
27
  /**
28
- * Hold Plugin class
29
  *
30
  * @var Plugin
31
  */
@@ -55,7 +55,7 @@ class Alerts {
55
  /**
56
  * Class constructor.
57
  *
58
- * @param Plugin $plugin The main Plugin class.
59
  */
60
  public function __construct( $plugin ) {
61
  $this->plugin = $plugin;
@@ -381,7 +381,7 @@ class Alerts {
381
  'public' => false,
382
  'show_in_admin_all_list' => true,
383
  'show_in_admin_status_list' => true,
384
- // translators: Placeholder refers to a number of items (e.g. "42")
385
  'label_count' => _n_noop( 'Enabled <span class="count">(%s)</span>', 'Enabled <span class="count">(%s)</span>', 'stream' ),
386
  );
387
 
@@ -393,7 +393,7 @@ class Alerts {
393
  'internal' => false,
394
  'show_in_admin_all_list' => true,
395
  'show_in_admin_status_list' => true,
396
- // translators: Placeholder refers to a number of items (e.g. "42")
397
  'label_count' => _n_noop( 'Disabled <span class="count">(%s)</span>', 'Disabled <span class="count">(%s)</span>', 'stream' ),
398
  );
399
 
@@ -493,7 +493,7 @@ class Alerts {
493
  // Set correct URL for the menu item.
494
  if ( $page === $value[2] ) {
495
  // This hack is not kosher, see the docblock for an explanation.
496
- $submenu[ $parent ][ $key ][2] = $new_url; // override okay
497
  break;
498
  }
499
  }
@@ -755,7 +755,7 @@ class Alerts {
755
  $alert_type = wp_stream_filter_input( INPUT_POST, 'wp_stream_alert_type' );
756
  $alert_status = wp_stream_filter_input( INPUT_POST, 'wp_stream_alert_status' );
757
 
758
- // Insert the post into the database
759
  $item = (object) array(
760
  'alert_type' => $alert_type,
761
  'alert_meta' => array(
@@ -796,7 +796,7 @@ class Alerts {
796
  }
797
 
798
  /**
799
- *
800
  */
801
  public function get_new_alert_triggers_notifications() {
802
  ob_start();
@@ -826,8 +826,8 @@ class Alerts {
826
  *
827
  * @filter wp_stream_action_links_{connector}
828
  *
829
- * @param array $links Previous links registered
830
- * @param Record $record Stream record
831
  *
832
  * @return array Action links
833
  */
@@ -839,7 +839,7 @@ class Alerts {
839
  $connector_posts = new \WP_Stream\Connector_Posts();
840
  $post_type_name = $connector_posts->get_post_type_name( get_post_type( $post->ID ) );
841
 
842
- // translators: Placeholder refers to the post type singular name (e.g. "Post")
843
  $links[ sprintf( esc_html_x( 'Edit %s', 'Post type singular name', 'stream' ), $post_type_name ) ] = admin_url( 'edit.php?post_type=wp_stream_alerts#post-' . $post->ID );
844
  unset( $links[ esc_html__( 'View', 'stream' ) ] );
845
  }
25
  const ALERTS_TRIGGERED_META_KEY = 'wp_stream_alerts_triggered';
26
 
27
  /**
28
+ * Holds Instance of plugin object
29
  *
30
  * @var Plugin
31
  */
55
  /**
56
  * Class constructor.
57
  *
58
+ * @param Plugin $plugin Instance of plugin object.
59
  */
60
  public function __construct( $plugin ) {
61
  $this->plugin = $plugin;
381
  'public' => false,
382
  'show_in_admin_all_list' => true,
383
  'show_in_admin_status_list' => true,
384
+ /* translators: %s: a number of items (e.g. "42") */
385
  'label_count' => _n_noop( 'Enabled <span class="count">(%s)</span>', 'Enabled <span class="count">(%s)</span>', 'stream' ),
386
  );
387
 
393
  'internal' => false,
394
  'show_in_admin_all_list' => true,
395
  'show_in_admin_status_list' => true,
396
+ /* translators: %s: a number of items (e.g. "42") */
397
  'label_count' => _n_noop( 'Disabled <span class="count">(%s)</span>', 'Disabled <span class="count">(%s)</span>', 'stream' ),
398
  );
399
 
493
  // Set correct URL for the menu item.
494
  if ( $page === $value[2] ) {
495
  // This hack is not kosher, see the docblock for an explanation.
496
+ $submenu[ $parent ][ $key ][2] = $new_url; // phpcs:ignore WordPress.WP.GlobalVariablesOverride.Prohibited
497
  break;
498
  }
499
  }
755
  $alert_type = wp_stream_filter_input( INPUT_POST, 'wp_stream_alert_type' );
756
  $alert_status = wp_stream_filter_input( INPUT_POST, 'wp_stream_alert_status' );
757
 
758
+ // Insert the post into the database.
759
  $item = (object) array(
760
  'alert_type' => $alert_type,
761
  'alert_meta' => array(
796
  }
797
 
798
  /**
799
+ * Return HTML string of the Alert page controls.
800
  */
801
  public function get_new_alert_triggers_notifications() {
802
  ob_start();
826
  *
827
  * @filter wp_stream_action_links_{connector}
828
  *
829
+ * @param array $links Previous links registered.
830
+ * @param Record $record Stream record.
831
  *
832
  * @return array Action links
833
  */
839
  $connector_posts = new \WP_Stream\Connector_Posts();
840
  $post_type_name = $connector_posts->get_post_type_name( get_post_type( $post->ID ) );
841
 
842
+ /* translators: %s: the post type singular name (e.g. "Post") */
843
  $links[ sprintf( esc_html_x( 'Edit %s', 'Post type singular name', 'stream' ), $post_type_name ) ] = admin_url( 'edit.php?post_type=wp_stream_alerts#post-' . $post->ID );
844
  unset( $links[ esc_html__( 'View', 'stream' ) ] );
845
  }
classes/class-author.php CHANGED
@@ -1,18 +1,33 @@
1
  <?php
 
 
 
 
 
 
2
  namespace WP_Stream;
3
 
 
 
 
4
  class Author {
5
  /**
 
 
6
  * @var int
7
  */
8
  public $id;
9
 
10
  /**
 
 
11
  * @var array
12
  */
13
  public $meta = array();
14
 
15
  /**
 
 
16
  * @var \WP_User
17
  */
18
  protected $user;
@@ -35,31 +50,38 @@ class Author {
35
  /**
36
  * Get various user meta data
37
  *
38
- * @param string $name
 
 
39
  *
40
- * @throws \Exception
41
  *
42
  * @return string
43
  */
44
  public function __get( $name ) {
45
- if ( 'display_name' === $name ) {
46
- return $this->get_display_name();
47
- } elseif ( 'avatar_img' === $name ) {
48
- return $this->get_avatar_img();
49
- } elseif ( 'avatar_src' === $name ) {
50
- return $this->get_avatar_src();
51
- } elseif ( 'role' === $name ) {
52
- return $this->get_role();
53
- } elseif ( 'agent' === $name ) {
54
- return $this->get_agent();
55
- } elseif ( ! empty( $this->user ) && 0 !== $this->user->ID ) {
56
- return $this->user->$name;
57
- } else {
58
- throw new \Exception( "Unrecognized magic '$name'" );
 
 
 
59
  }
60
  }
61
 
62
  /**
 
 
63
  * @return string
64
  */
65
  public function __toString() {
@@ -76,7 +98,7 @@ class Author {
76
  if ( isset( $this->meta['system_user_name'] ) ) {
77
  return esc_html( $this->meta['system_user_name'] );
78
  } elseif ( 'wp_cli' === $this->get_current_agent() ) {
79
- return 'WP-CLI'; // No translation needed
80
  }
81
  return esc_html__( 'N/A', 'stream' );
82
  } else {
@@ -107,7 +129,7 @@ class Author {
107
  if ( ! empty( $this->meta['agent'] ) ) {
108
  $agent = $this->meta['agent'];
109
  } elseif ( ! empty( $this->meta['is_wp_cli'] ) ) {
110
- $agent = 'wp_cli'; // legacy
111
  }
112
 
113
  return $agent;
@@ -118,7 +140,7 @@ class Author {
118
  *
119
  * This function will not return an avatar if "Show Avatars" is unchecked in Settings > Discussion.
120
  *
121
- * @param int $size (optional) Size of Gravatar to return (in pixels), max is 512, default is 80
122
  *
123
  * @return string|bool An img HTML element, or false if avatars are disabled
124
  */
@@ -146,7 +168,7 @@ class Author {
146
  /**
147
  * Return the URL of a Gravatar image.
148
  *
149
- * @param int $size (optional) Size of Gravatar to return (in pixels), max is 512, default is 80
150
  *
151
  * @return string|bool Gravatar image URL, or false on failure
152
  */
@@ -263,7 +285,7 @@ class Author {
263
  /**
264
  * Get the agent label
265
  *
266
- * @param string $agent
267
  *
268
  * @return string
269
  */
@@ -279,7 +301,7 @@ class Author {
279
  /**
280
  * Filter agent labels
281
  *
282
- * @param string $agent
283
  *
284
  * @return string
285
  */
1
  <?php
2
+ /**
3
+ * Manages a single user, acting as a model.
4
+ *
5
+ * @package WP_Stream
6
+ */
7
+
8
  namespace WP_Stream;
9
 
10
+ /**
11
+ * Class - Author
12
+ */
13
  class Author {
14
  /**
15
+ * Holds User ID.
16
+ *
17
  * @var int
18
  */
19
  public $id;
20
 
21
  /**
22
+ * Holds User meta data.
23
+ *
24
  * @var array
25
  */
26
  public $meta = array();
27
 
28
  /**
29
+ * Holds WP user object connected to "$this" instance.
30
+ *
31
  * @var \WP_User
32
  */
33
  protected $user;
50
  /**
51
  * Get various user meta data
52
  *
53
+ * @todo Make sure this is being covered in the unit tests.
54
+ *
55
+ * @param string $name User meta key.
56
  *
57
+ * @throws \Exception Meta not found | User not found.
58
  *
59
  * @return string
60
  */
61
  public function __get( $name ) {
62
+ switch ( $name ) {
63
+ case 'display_name':
64
+ case 'avatar_img':
65
+ case 'avatar_src':
66
+ case 'role':
67
+ case 'agent':
68
+ $getter = "get_{$name}";
69
+ return $this->$getter();
70
+ default:
71
+ if ( ! empty( $this->user ) && 0 !== $this->user->ID ) {
72
+ if ( is_null( $this->user->$name ) ) {
73
+ throw new \Exception( "Unrecognized magic '$name'" );
74
+ }
75
+ return $this->user->$name;
76
+ }
77
+
78
+ throw new \Exception( 'User not found.' );
79
  }
80
  }
81
 
82
  /**
83
+ * Returns string representation of this object
84
+ *
85
  * @return string
86
  */
87
  public function __toString() {
98
  if ( isset( $this->meta['system_user_name'] ) ) {
99
  return esc_html( $this->meta['system_user_name'] );
100
  } elseif ( 'wp_cli' === $this->get_current_agent() ) {
101
+ return 'WP-CLI'; // No translation needed.
102
  }
103
  return esc_html__( 'N/A', 'stream' );
104
  } else {
129
  if ( ! empty( $this->meta['agent'] ) ) {
130
  $agent = $this->meta['agent'];
131
  } elseif ( ! empty( $this->meta['is_wp_cli'] ) ) {
132
+ $agent = 'wp_cli'; // legacy.
133
  }
134
 
135
  return $agent;
140
  *
141
  * This function will not return an avatar if "Show Avatars" is unchecked in Settings > Discussion.
142
  *
143
+ * @param int $size (optional) Size of Gravatar to return (in pixels), max is 512, default is 80.
144
  *
145
  * @return string|bool An img HTML element, or false if avatars are disabled
146
  */
168
  /**
169
  * Return the URL of a Gravatar image.
170
  *
171
+ * @param int $size (optional) Size of Gravatar to return (in pixels), max is 512, default is 80.
172
  *
173
  * @return string|bool Gravatar image URL, or false on failure
174
  */
285
  /**
286
  * Get the agent label
287
  *
288
+ * @param string $agent Key representing agent.
289
  *
290
  * @return string
291
  */
301
  /**
302
  * Filter agent labels
303
  *
304
+ * @param string $agent Key representing agent.
305
  *
306
  * @return string
307
  */
classes/class-cli.php CHANGED
@@ -3,10 +3,14 @@
3
  * Stream command for WP-CLI
4
  *
5
  * @see https://github.com/wp-cli/wp-cli
 
6
  */
7
 
8
  namespace WP_Stream;
9
 
 
 
 
10
  class CLI extends \WP_CLI_Command {
11
 
12
  /**
@@ -88,6 +92,9 @@ class CLI extends \WP_CLI_Command {
88
  * @see WP_Stream_Query
89
  * @see https://github.com/wp-stream/stream/wiki/WP-CLI-Command
90
  * @see https://github.com/wp-stream/stream/wiki/Query-Reference
 
 
 
91
  */
92
  public function query( $args, $assoc_args ) {
93
  unset( $args );
@@ -121,11 +128,11 @@ class CLI extends \WP_CLI_Command {
121
 
122
  $records = wp_stream_get_instance()->db->query( $query_args );
123
 
124
- // Make structure Formatter compatible
125
  foreach ( (array) $records as $key => $record ) {
126
  $formatted_records[ $key ] = array();
127
 
128
- // Catch any fields missing in records
129
  foreach ( $fields as $field ) {
130
  if ( ! array_key_exists( $field, $record ) ) {
131
  $record->$field = null;
@@ -152,9 +159,9 @@ class CLI extends \WP_CLI_Command {
152
 
153
  if ( 'json_pretty' === $assoc_args['format'] ) {
154
  if ( version_compare( PHP_VERSION, '5.4', '<' ) ) {
155
- \WP_CLI::line( wp_stream_json_encode( $formatted_records ) ); // xss ok
156
  } else {
157
- \WP_CLI::line( wp_stream_json_encode( $formatted_records, JSON_PRETTY_PRINT ) ); // xss ok
158
  }
159
  }
160
 
@@ -176,8 +183,8 @@ class CLI extends \WP_CLI_Command {
176
  /**
177
  * Convert any field to a flat array.
178
  *
179
- * @param string $name The output array element name
180
- * @param mixed $object Any value to be converted to an array
181
  *
182
  * @return array The flat array
183
  */
@@ -200,9 +207,7 @@ class CLI extends \WP_CLI_Command {
200
  /**
201
  * Convert an array of flat records to CSV
202
  *
203
- * @param array $array The input array of records
204
- *
205
- * @return string The CSV output
206
  */
207
  private function csv_format( $array ) {
208
  $output = fopen( 'php://output', 'w' ); // @codingStandardsIgnoreLine Clever output for WP CLI using php://output
3
  * Stream command for WP-CLI
4
  *
5
  * @see https://github.com/wp-cli/wp-cli
6
+ * @package WP_Stream
7
  */
8
 
9
  namespace WP_Stream;
10
 
11
+ /**
12
+ * Class - CLI
13
+ */
14
  class CLI extends \WP_CLI_Command {
15
 
16
  /**
92
  * @see WP_Stream_Query
93
  * @see https://github.com/wp-stream/stream/wiki/WP-CLI-Command
94
  * @see https://github.com/wp-stream/stream/wiki/Query-Reference
95
+ *
96
+ * @param array $args Unused.
97
+ * @param array $assoc_args Fields to return data for.
98
  */
99
  public function query( $args, $assoc_args ) {
100
  unset( $args );
128
 
129
  $records = wp_stream_get_instance()->db->query( $query_args );
130
 
131
+ // Make structure Formatter compatible.
132
  foreach ( (array) $records as $key => $record ) {
133
  $formatted_records[ $key ] = array();
134
 
135
+ // Catch any fields missing in records.
136
  foreach ( $fields as $field ) {
137
  if ( ! array_key_exists( $field, $record ) ) {
138
  $record->$field = null;
159
 
160
  if ( 'json_pretty' === $assoc_args['format'] ) {
161
  if ( version_compare( PHP_VERSION, '5.4', '<' ) ) {
162
+ \WP_CLI::line( wp_stream_json_encode( $formatted_records ) ); // xss ok.
163
  } else {
164
+ \WP_CLI::line( wp_stream_json_encode( $formatted_records, JSON_PRETTY_PRINT ) ); // xss ok.
165
  }
166
  }
167
 
183
  /**
184
  * Convert any field to a flat array.
185
  *
186
+ * @param string $name The output array element name.
187
+ * @param mixed $object Any value to be converted to an array.
188
  *
189
  * @return array The flat array
190
  */
207
  /**
208
  * Convert an array of flat records to CSV
209
  *
210
+ * @param array $array The input array of records.
 
 
211
  */
212
  private function csv_format( $array ) {
213
  $output = fopen( 'php://output', 'w' ); // @codingStandardsIgnoreLine Clever output for WP CLI using php://output
classes/class-connector.php CHANGED
@@ -1,6 +1,16 @@
1
  <?php
 
 
 
 
 
 
 
2
  namespace WP_Stream;
3
 
 
 
 
4
  abstract class Connector {
5
  /**
6
  * Connector slug
@@ -63,7 +73,7 @@ abstract class Connector {
63
  $action = current_filter();
64
  $callback = array( $this, 'callback_' . preg_replace( '/[^a-z0-9_\-]/', '_', $action ) );
65
 
66
- // For the sake of testing, trigger an action with the name of the callback
67
  if ( defined( 'WP_STREAM_TESTS' ) && WP_STREAM_TESTS ) {
68
  /**
69
  * Action fires during testing to test the current callback
@@ -73,7 +83,7 @@ abstract class Connector {
73
  do_action( 'wp_stream_test_' . $callback[1] );
74
  }
75
 
76
- // Call the real function
77
  if ( is_callable( $callback ) ) {
78
  return call_user_func_array( $callback, func_get_args() );
79
  }
@@ -82,8 +92,8 @@ abstract class Connector {
82
  /**
83
  * Add action links to Stream drop row in admin list screen
84
  *
85
- * @param array $links Previous links registered
86
- * @param object $record Stream record
87
  *
88
  * @filter wp_stream_action_links_{connector}
89
  *
@@ -97,12 +107,12 @@ abstract class Connector {
97
  /**
98
  * Log handler
99
  *
100
- * @param string $message sprintf-ready error message string
101
- * @param array $args sprintf (and extra) arguments to use
102
- * @param int $object_id Target object id
103
- * @param string $context Context of the event
104
- * @param string $action Action of the event
105
- * @param int $user_id User responsible for the event
106
  *
107
  * @return bool
108
  */
@@ -132,7 +142,7 @@ abstract class Connector {
132
  /**
133
  * Save log data till shutdown, so other callbacks would be able to override
134
  *
135
- * @param string $handle Special slug to be shared with other actions
136
  * @note param mixed $arg1 Extra arguments to sent to log()
137
  * @note param param mixed $arg2, etc..
138
  */
@@ -158,9 +168,9 @@ abstract class Connector {
158
  /**
159
  * Compare two values and return changed keys if they are arrays
160
  *
161
- * @param mixed $old_value Value before change
162
- * @param mixed $new_value Value after change
163
- * @param bool|int $deep Get array children changes keys as well, not just parents
164
  *
165
  * @return array
166
  */
@@ -181,21 +191,21 @@ abstract class Connector {
181
  $old_value,
182
  $new_value,
183
  function( $value1, $value2 ) {
184
- // Compare potentially complex nested arrays
185
  return wp_json_encode( $value1 ) !== wp_json_encode( $value2 );
186
  }
187
  );
188
 
189
  $result = array_keys( $diff );
190
 
191
- // find unexisting keys in old or new value
192
  $common_keys = array_keys( array_intersect_key( $old_value, $new_value ) );
193
  $unique_keys_old = array_values( array_diff( array_keys( $old_value ), $common_keys ) );
194
  $unique_keys_new = array_values( array_diff( array_keys( $new_value ), $common_keys ) );
195
 
196
  $result = array_merge( $result, $unique_keys_old, $unique_keys_new );
197
 
198
- // remove numeric indexes
199
  $result = array_filter(
200
  $result,
201
  function( $value ) {
@@ -209,17 +219,17 @@ abstract class Connector {
209
  $result = array_values( array_unique( $result ) );
210
 
211
  if ( false === $deep ) {
212
- return $result; // Return an numerical based array with changed TOP PARENT keys only
213
  }
214
 
215
  $result = array_fill_keys( $result, null );
216
 
217
  foreach ( $result as $key => $val ) {
218
  if ( in_array( $key, $unique_keys_old, true ) ) {
219
- $result[ $key ] = false; // Removed
220
  } elseif ( in_array( $key, $unique_keys_new, true ) ) {
221
- $result[ $key ] = true; // Added
222
- } elseif ( $deep ) { // Changed, find what changed, only if we're allowed to explore a new level
223
  if ( is_array( $old_value[ $key ] ) && is_array( $new_value[ $key ] ) ) {
224
  $inner = array();
225
  $parent = $key;
@@ -228,7 +238,7 @@ abstract class Connector {
228
  foreach ( $changed as $child => $change ) {
229
  $inner[ $parent . '::' . $child ] = $change;
230
  }
231
- $result[ $key ] = 0; // Changed parent which has a changed children
232
  $result = array_merge( $result, $inner );
233
  }
234
  }
1
  <?php
2
+ /**
3
+ * Abstract class serving as the parent for all logger classes AKA "Connectors".
4
+ * Common functionality for registering log events are defined here.
5
+ *
6
+ * @package WP_Stream;
7
+ */
8
+
9
  namespace WP_Stream;
10
 
11
+ /**
12
+ * Class - Connector
13
+ */
14
  abstract class Connector {
15
  /**
16
  * Connector slug
73
  $action = current_filter();
74
  $callback = array( $this, 'callback_' . preg_replace( '/[^a-z0-9_\-]/', '_', $action ) );
75
 
76
+ // For the sake of testing, trigger an action with the name of the callback.
77
  if ( defined( 'WP_STREAM_TESTS' ) && WP_STREAM_TESTS ) {
78
  /**
79
  * Action fires during testing to test the current callback
83
  do_action( 'wp_stream_test_' . $callback[1] );
84
  }
85
 
86
+ // Call the real function.
87
  if ( is_callable( $callback ) ) {
88
  return call_user_func_array( $callback, func_get_args() );
89
  }
92
  /**
93
  * Add action links to Stream drop row in admin list screen
94
  *
95
+ * @param array $links Previous links registered.
96
+ * @param object $record Stream record.
97
  *
98
  * @filter wp_stream_action_links_{connector}
99
  *
107
  /**
108
  * Log handler
109
  *
110
+ * @param string $message sprintf-ready error message string.
111
+ * @param array $args sprintf (and extra) arguments to use.
112
+ * @param int $object_id Target object id.
113
+ * @param string $context Context of the event.
114
+ * @param string $action Action of the event.
115
+ * @param int $user_id User responsible for the event.
116
  *
117
  * @return bool
118
  */
142
  /**
143
  * Save log data till shutdown, so other callbacks would be able to override
144
  *
145
+ * @param string $handle Special slug to be shared with other actions.
146
  * @note param mixed $arg1 Extra arguments to sent to log()
147
  * @note param param mixed $arg2, etc..
148
  */
168
  /**
169
  * Compare two values and return changed keys if they are arrays
170
  *
171
+ * @param mixed $old_value Value before change.
172
+ * @param mixed $new_value Value after change.
173
+ * @param bool|int $deep Get array children changes keys as well, not just parents.
174
  *
175
  * @return array
176
  */
191
  $old_value,
192
  $new_value,
193
  function( $value1, $value2 ) {
194
+ // Compare potentially complex nested arrays.
195
  return wp_json_encode( $value1 ) !== wp_json_encode( $value2 );
196
  }
197
  );
198
 
199
  $result = array_keys( $diff );
200
 
201
+ // Find unexisting keys in old or new value.
202
  $common_keys = array_keys( array_intersect_key( $old_value, $new_value ) );
203
  $unique_keys_old = array_values( array_diff( array_keys( $old_value ), $common_keys ) );
204
  $unique_keys_new = array_values( array_diff( array_keys( $new_value ), $common_keys ) );
205
 
206
  $result = array_merge( $result, $unique_keys_old, $unique_keys_new );
207
 
208
+ // Remove numeric indexes.
209
  $result = array_filter(
210
  $result,
211
  function( $value ) {
219
  $result = array_values( array_unique( $result ) );
220
 
221
  if ( false === $deep ) {
222
+ return $result; // Return an numerical based array with changed TOP PARENT keys only.
223
  }
224
 
225
  $result = array_fill_keys( $result, null );
226
 
227
  foreach ( $result as $key => $val ) {
228
  if ( in_array( $key, $unique_keys_old, true ) ) {
229
+ $result[ $key ] = false; // Removed.
230
  } elseif ( in_array( $key, $unique_keys_new, true ) ) {
231
+ $result[ $key ] = true; // Added.
232
+ } elseif ( $deep ) { // Changed, find what changed, only if we're allowed to explore a new level.
233
  if ( is_array( $old_value[ $key ] ) && is_array( $new_value[ $key ] ) ) {
234
  $inner = array();
235
  $parent = $key;
238
  foreach ( $changed as $child => $change ) {
239
  $inner[ $parent . '::' . $child ] = $change;
240
  }
241
+ $result[ $key ] = 0; // Changed parent which has a changed children.
242
  $result = array_merge( $result, $inner );
243
  }
244
  }
classes/class-connectors.php CHANGED
@@ -1,16 +1,26 @@
1
  <?php
 
 
 
 
 
 
 
2
  namespace WP_Stream;
3
 
 
 
 
4
  class Connectors {
5
  /**
6
- * Hold Plugin class
7
  *
8
  * @var Plugin
9
  */
10
  public $plugin;
11
 
12
  /**
13
- * Connectors registered
14
  *
15
  * @var array
16
  */
@@ -25,6 +35,7 @@ class Connectors {
25
 
26
  /**
27
  * Action taxonomy terms
 
28
  * Holds slug to localized label association
29
  *
30
  * @var array
@@ -45,7 +56,7 @@ class Connectors {
45
  /**
46
  * Class constructor.
47
  *
48
- * @param Plugin $plugin The main Plugin class.
49
  */
50
  public function __construct( $plugin ) {
51
  $this->plugin = $plugin;
@@ -57,7 +68,9 @@ class Connectors {
57
  */
58
  public function load_connectors() {
59
  $connectors = array(
60
- // Core
 
 
61
  'blogs',
62
  'comments',
63
  'editor',
@@ -70,7 +83,9 @@ class Connectors {
70
  'users',
71
  'widgets',
72
 
73
- // Extras
 
 
74
  'acf',
75
  'bbpress',
76
  'buddypress',
@@ -85,28 +100,36 @@ class Connectors {
85
 
86
  $classes = array();
87
  foreach ( $connectors as $connector ) {
 
88
  include_once $this->plugin->locations['dir'] . '/connectors/class-connector-' . $connector . '.php';
 
 
89
  $class_name = sprintf( '\WP_Stream\Connector_%s', str_replace( '-', '_', $connector ) );
 
 
90
  if ( ! class_exists( $class_name ) ) {
91
  continue;
92
  }
 
 
93
  $class = new $class_name( $this->plugin->log );
94
 
95
- // Check if the Connector extends WP_Stream\Connector
96
  if ( ! is_subclass_of( $class, 'WP_Stream\Connector' ) ) {
97
  continue;
98
  }
99
 
100
- // Check if the Connector is allowed to be registered in the WP Admin
101
  if ( is_admin() && ! $class->register_admin ) {
102
  continue;
103
  }
104
 
105
- // Check if the Connector is allowed to be registered in the WP Frontend
106
  if ( ! is_admin() && ! $class->register_frontend ) {
107
  continue;
108
  }
109
 
 
110
  if ( $class->is_dependency_satisfied() ) {
111
  $classes[ $class->name ] = $class;
112
  }
@@ -130,39 +153,41 @@ class Connectors {
130
  $this->term_labels['stream_connector'][ $connector->name ] = $connector->get_label();
131
  }
132
 
133
- // Get excluded connectors
134
  $excluded_connectors = array();
135
 
136
  foreach ( $this->connectors as $connector ) {
 
 
137
  if ( ! method_exists( $connector, 'get_label' ) ) {
138
- // translators: Placeholder refers to a Connector class name, intended to provide help to developers (e.g. "Connector_BuddyPress")
139
  $this->plugin->admin->notice( sprintf( __( '%s class wasn\'t loaded because it doesn\'t implement the get_label method.', 'stream' ), $connector->name, 'Connector' ), true );
140
  continue;
141
  }
142
  if ( ! method_exists( $connector, 'register' ) ) {
143
- // translators: Placeholder refers to a Connector class name, intended to provide help to developers (e.g. "Connector_BuddyPress")
144
  $this->plugin->admin->notice( sprintf( __( '%s class wasn\'t loaded because it doesn\'t implement the register method.', 'stream' ), $connector->name, 'Connector' ), true );
145
  continue;
146
  }
147
  if ( ! method_exists( $connector, 'get_context_labels' ) ) {
148
- // translators: Placeholder refers to a Connector class name, intended to provide help to developers (e.g. "Connector_BuddyPress")
149
  $this->plugin->admin->notice( sprintf( __( '%s class wasn\'t loaded because it doesn\'t implement the get_context_labels method.', 'stream' ), $connector->name, 'Connector' ), true );
150
  continue;
151
  }
152
  if ( ! method_exists( $connector, 'get_action_labels' ) ) {
153
- // translators: Placeholder refers to a Connector class name, intended to provide help to developers (e.g. "Connector_BuddyPress")
154
  $this->plugin->admin->notice( sprintf( __( '%s class wasn\'t loaded because it doesn\'t implement the get_action_labels method.', 'stream' ), $connector->name, 'Connector' ), true );
155
  continue;
156
  }
157
 
158
  // Check if the connectors extends the Connector class, if not skip it.
159
  if ( ! is_subclass_of( $connector, '\WP_Stream\Connector' ) ) {
160
- // translators: Placeholder refers to a Connector class name, intended to provide help to developers (e.g. "Connector_BuddyPress")
161
  $this->plugin->admin->notice( sprintf( __( '%1$s class wasn\'t loaded because it doesn\'t extends the %2$s class.', 'stream' ), $connector->name, 'Connector' ), true );
162
  continue;
163
  }
164
 
165
- // Store connector label
166
  if ( ! in_array( $connector->name, $this->term_labels['stream_connector'], true ) ) {
167
  $this->term_labels['stream_connector'][ $connector->name ] = $connector->get_label();
168
  }
@@ -185,10 +210,10 @@ class Connectors {
185
 
186
  $connector->register();
187
 
188
- // Link context labels to their connector
189
  $this->contexts[ $connector->name ] = $connector->get_context_labels();
190
 
191
- // Add new terms to our label lookup array
192
  $this->term_labels['stream_action'] = array_merge(
193
  $this->term_labels['stream_action'],
194
  $connector->get_action_labels()
1
  <?php
2
+ /**
3
+ * Validates and loads core connectors, integrated connectors, and
4
+ * connectors registered using the "wp_stream_connectors" hook.
5
+ *
6
+ * @package WP_Stream
7
+ */
8
+
9
  namespace WP_Stream;
10
 
11
+ /**
12
+ * Class - Connectors
13
+ */
14
  class Connectors {
15
  /**
16
+ * Holds instance of plugin object
17
  *
18
  * @var Plugin
19
  */
20
  public $plugin;
21
 
22
  /**
23
+ * Registered connectors.
24
  *
25
  * @var array
26
  */
35
 
36
  /**
37
  * Action taxonomy terms
38
+ *
39
  * Holds slug to localized label association
40
  *
41
  * @var array
56
  /**
57
  * Class constructor.
58
  *
59
+ * @param Plugin $plugin Instance of plugin object.
60
  */
61
  public function __construct( $plugin ) {
62
  $this->plugin = $plugin;
68
  */
69
  public function load_connectors() {
70
  $connectors = array(
71
+ /**
72
+ * Core Connectors
73
+ */
74
  'blogs',
75
  'comments',
76
  'editor',
83
  'users',
84
  'widgets',
85
 
86
+ /**
87
+ * Integrated Connectors
88
+ */
89
  'acf',
90
  'bbpress',
91
  'buddypress',
100
 
101
  $classes = array();
102
  foreach ( $connectors as $connector ) {
103
+ // Load connector class file.
104
  include_once $this->plugin->locations['dir'] . '/connectors/class-connector-' . $connector . '.php';
105
+
106
+ // Set fully qualified class name.
107
  $class_name = sprintf( '\WP_Stream\Connector_%s', str_replace( '-', '_', $connector ) );
108
+
109
+ // Bail if no class loaded.
110
  if ( ! class_exists( $class_name ) ) {
111
  continue;
112
  }
113
+
114
+ // Initialize connector.
115
  $class = new $class_name( $this->plugin->log );
116
 
117
+ // Check if the connector class extends WP_Stream\Connector.
118
  if ( ! is_subclass_of( $class, 'WP_Stream\Connector' ) ) {
119
  continue;
120
  }
121
 
122
+ // Check if the connector events are allowed to be registered in the WP Admin.
123
  if ( is_admin() && ! $class->register_admin ) {
124
  continue;
125
  }
126
 
127
+ // Check if the connector events are allowed to be registered in the WP Frontend.
128
  if ( ! is_admin() && ! $class->register_frontend ) {
129
  continue;
130
  }
131
 
132
+ // Run any final validations the connector may have before used.
133
  if ( $class->is_dependency_satisfied() ) {
134
  $classes[ $class->name ] = $class;
135
  }
153
  $this->term_labels['stream_connector'][ $connector->name ] = $connector->get_label();
154
  }
155
 
156
+ // Get excluded connectors.
157
  $excluded_connectors = array();
158
 
159
  foreach ( $this->connectors as $connector ) {
160
+
161
+ // Register error for invalid any connector class.
162
  if ( ! method_exists( $connector, 'get_label' ) ) {
163
+ /* translators: %s: connector class name, intended to provide help to developers (e.g. "Connector_BuddyPress") */
164
  $this->plugin->admin->notice( sprintf( __( '%s class wasn\'t loaded because it doesn\'t implement the get_label method.', 'stream' ), $connector->name, 'Connector' ), true );
165
  continue;
166
  }
167
  if ( ! method_exists( $connector, 'register' ) ) {
168
+ /* translators: %s: connector class name, intended to provide help to developers (e.g. "Connector_BuddyPress") */
169
  $this->plugin->admin->notice( sprintf( __( '%s class wasn\'t loaded because it doesn\'t implement the register method.', 'stream' ), $connector->name, 'Connector' ), true );
170
  continue;
171
  }
172
  if ( ! method_exists( $connector, 'get_context_labels' ) ) {
173
+ /* translators: %s: connector class name, intended to provide help to developers (e.g. "Connector_BuddyPress") */
174
  $this->plugin->admin->notice( sprintf( __( '%s class wasn\'t loaded because it doesn\'t implement the get_context_labels method.', 'stream' ), $connector->name, 'Connector' ), true );
175
  continue;
176
  }
177
  if ( ! method_exists( $connector, 'get_action_labels' ) ) {
178
+ /* translators: %s: connector class name, intended to provide help to developers (e.g. "Connector_BuddyPress") */
179
  $this->plugin->admin->notice( sprintf( __( '%s class wasn\'t loaded because it doesn\'t implement the get_action_labels method.', 'stream' ), $connector->name, 'Connector' ), true );
180
  continue;
181
  }
182
 
183
  // Check if the connectors extends the Connector class, if not skip it.
184
  if ( ! is_subclass_of( $connector, '\WP_Stream\Connector' ) ) {
185
+ /* translators: %s: connector class name, intended to provide help to developers (e.g. "Connector_BuddyPress") */
186
  $this->plugin->admin->notice( sprintf( __( '%1$s class wasn\'t loaded because it doesn\'t extends the %2$s class.', 'stream' ), $connector->name, 'Connector' ), true );
187
  continue;
188
  }
189
 
190
+ // Store connector label.
191
  if ( ! in_array( $connector->name, $this->term_labels['stream_connector'], true ) ) {
192
  $this->term_labels['stream_connector'][ $connector->name ] = $connector->get_label();
193
  }
210
 
211
  $connector->register();
212
 
213
+ // Link context labels to their connector.
214
  $this->contexts[ $connector->name ] = $connector->get_context_labels();
215
 
216
+ // Add new terms to our label lookup array.
217
  $this->term_labels['stream_action'] = array_merge(
218
  $this->term_labels['stream_action'],
219
  $connector->get_action_labels()
classes/class-date-interval.php CHANGED
@@ -1,13 +1,21 @@
1
  <?php
 
 
 
 
 
 
2
  namespace WP_Stream;
3
 
4
- // Load Carbon to Handle dates much easier
5
  if ( ! class_exists( 'Carbon\Carbon' ) ) {
6
  require_once wp_stream_get_instance()->locations['inc_dir'] . 'lib/Carbon.php';
7
  }
8
-
9
  use Carbon\Carbon;
10
 
 
 
 
11
  class Date_Interval {
12
  /**
13
  * Contains an array of all available intervals
@@ -20,11 +28,14 @@ class Date_Interval {
20
  * Class constructor
21
  */
22
  public function __construct() {
23
- // Get all default intervals
24
  $this->intervals = $this->get_predefined_intervals();
25
  }
26
 
27
  /**
 
 
 
28
  * @return mixed
29
  */
30
  public function get_predefined_intervals() {
@@ -55,19 +66,19 @@ class Date_Interval {
55
  'end' => Carbon::today( $timezone )->startOfDay()->subSecond(),
56
  ),
57
  'last-7-days' => array(
58
- // translators: Placeholder refers to a number of days (e.g. "7")
59
  'label' => sprintf( esc_html__( 'Last %d Days', 'stream' ), 7 ),
60
  'start' => Carbon::today( $timezone )->subDays( 7 ),
61
  'end' => Carbon::today( $timezone ),
62
  ),
63
  'last-14-days' => array(
64
- // translators: Placeholder refers to a number of days (e.g. "7")
65
  'label' => sprintf( esc_html__( 'Last %d Days', 'stream' ), 14 ),
66
  'start' => Carbon::today( $timezone )->subDays( 14 ),
67
  'end' => Carbon::today( $timezone ),
68
  ),
69
  'last-30-days' => array(
70
- // translators: Placeholder refers to a number of days (e.g. "7")
71
  'label' => sprintf( esc_html__( 'Last %d Days', 'stream' ), 30 ),
72
  'start' => Carbon::today( $timezone )->subDays( 30 ),
73
  'end' => Carbon::today( $timezone ),
@@ -83,19 +94,19 @@ class Date_Interval {
83
  'end' => Carbon::today( $timezone )->startOfMonth()->subSecond(),
84
  ),
85
  'last-3-months' => array(
86
- // translators: Placeholder refers to a number of months (e.g. "3")
87
  'label' => sprintf( esc_html__( 'Last %d Months', 'stream' ), 3 ),
88
  'start' => Carbon::today( $timezone )->subMonths( 3 ),
89
  'end' => Carbon::today( $timezone ),
90
  ),
91
  'last-6-months' => array(
92
- // translators: Placeholder refers to a number of months (e.g. "3")
93
  'label' => sprintf( esc_html__( 'Last %d Months', 'stream' ), 6 ),
94
  'start' => Carbon::today( $timezone )->subMonths( 6 ),
95
  'end' => Carbon::today( $timezone ),
96
  ),
97
  'last-12-months' => array(
98
- // translators: Placeholder refers to a number of months (e.g. "3")
99
  'label' => sprintf( esc_html__( 'Last %d Months', 'stream' ), 12 ),
100
  'start' => Carbon::today( $timezone )->subMonths( 12 ),
101
  'end' => Carbon::today( $timezone ),
1
  <?php
2
+ /**
3
+ * Calculate date intervals for a specific timezone.
4
+ *
5
+ * @package WP_Stream
6
+ */
7
+
8
  namespace WP_Stream;
9
 
10
+ // Load Carbon to Handle dates much easier.
11
  if ( ! class_exists( 'Carbon\Carbon' ) ) {
12
  require_once wp_stream_get_instance()->locations['inc_dir'] . 'lib/Carbon.php';
13
  }
 
14
  use Carbon\Carbon;
15
 
16
+ /**
17
+ * Class - Date_Interval
18
+ */
19
  class Date_Interval {
20
  /**
21
  * Contains an array of all available intervals
28
  * Class constructor
29
  */
30
  public function __construct() {
31
+ // Get all default intervals.
32
  $this->intervals = $this->get_predefined_intervals();
33
  }
34
 
35
  /**
36
+ * Returns date interval data based upon "Timezone" site setting.
37
+ *
38
+ * @todo add better inline comments
39
  * @return mixed
40
  */
41
  public function get_predefined_intervals() {
66
  'end' => Carbon::today( $timezone )->startOfDay()->subSecond(),
67
  ),
68
  'last-7-days' => array(
69
+ /* translators: %d: number of days (e.g. "7") */
70
  'label' => sprintf( esc_html__( 'Last %d Days', 'stream' ), 7 ),
71
  'start' => Carbon::today( $timezone )->subDays( 7 ),
72
  'end' => Carbon::today( $timezone ),
73
  ),
74
  'last-14-days' => array(
75
+ /* translators: %d: number of days (e.g. "7") */
76
  'label' => sprintf( esc_html__( 'Last %d Days', 'stream' ), 14 ),
77
  'start' => Carbon::today( $timezone )->subDays( 14 ),
78
  'end' => Carbon::today( $timezone ),
79
  ),
80
  'last-30-days' => array(
81
+ /* translators: %d: number of days (e.g. "7") */
82
  'label' => sprintf( esc_html__( 'Last %d Days', 'stream' ), 30 ),
83
  'start' => Carbon::today( $timezone )->subDays( 30 ),
84
  'end' => Carbon::today( $timezone ),
94
  'end' => Carbon::today( $timezone )->startOfMonth()->subSecond(),
95
  ),
96
  'last-3-months' => array(
97
+ /* translators: %d: number of months (e.g. "3") */
98
  'label' => sprintf( esc_html__( 'Last %d Months', 'stream' ), 3 ),
99
  'start' => Carbon::today( $timezone )->subMonths( 3 ),
100
  'end' => Carbon::today( $timezone ),
101
  ),
102
  'last-6-months' => array(
103
+ /* translators: %d: number of months (e.g. "3") */
104
  'label' => sprintf( esc_html__( 'Last %d Months', 'stream' ), 6 ),
105
  'start' => Carbon::today( $timezone )->subMonths( 6 ),
106
  'end' => Carbon::today( $timezone ),
107
  ),
108
  'last-12-months' => array(
109
+ /* translators: %d: number of months (e.g. "3") */
110
  'label' => sprintf( esc_html__( 'Last %d Months', 'stream' ), 12 ),
111
  'start' => Carbon::today( $timezone )->subMonths( 12 ),
112
  'end' => Carbon::today( $timezone ),
classes/class-db-driver-wpdb.php CHANGED
@@ -1,6 +1,15 @@
1
  <?php
 
 
 
 
 
 
2
  namespace WP_Stream;
3
 
 
 
 
4
  class DB_Driver_WPDB implements DB_Driver {
5
  /**
6
  * Holds Query class
@@ -38,7 +47,7 @@ class DB_Driver_WPDB implements DB_Driver {
38
  $wpdb->stream = $this->table;
39
  $wpdb->streammeta = $this->table_meta;
40
 
41
- // Hack for get_metadata
42
  $wpdb->recordmeta = $this->table_meta;
43
  }
44
 
@@ -66,7 +75,7 @@ class DB_Driver_WPDB implements DB_Driver {
66
 
67
  $record_id = $wpdb->insert_id;
68
 
69
- // Insert record meta
70
  foreach ( (array) $meta as $key => $vals ) {
71
  foreach ( (array) $vals as $val ) {
72
  $this->insert_meta( $record_id, $key, $val );
@@ -79,9 +88,9 @@ class DB_Driver_WPDB implements DB_Driver {
79
  /**
80
  * Insert record meta
81
  *
82
- * @param int $record_id
83
- * @param string $key
84
- * @param string $val
85
  *
86
  * @return array
87
  */
@@ -103,7 +112,7 @@ class DB_Driver_WPDB implements DB_Driver {
103
  /**
104
  * Retrieve records
105
  *
106
- * @param array $args
107
  *
108
  * @return array
109
  */
@@ -118,7 +127,7 @@ class DB_Driver_WPDB implements DB_Driver {
118
  * GROUP BY allows query to find just the first occurrence of each value in the column,
119
  * increasing the efficiency of the query.
120
  *
121
- * @param string $column
122
  *
123
  * @return array
124
  */
1
  <?php
2
+ /**
3
+ * Database Driver class for "stream" table responsible for holding records.
4
+ *
5
+ * @package WP_Stream
6
+ */
7
+
8
  namespace WP_Stream;
9
 
10
+ /**
11
+ * Class - DB_Driver_WPDB
12
+ */
13
  class DB_Driver_WPDB implements DB_Driver {
14
  /**
15
  * Holds Query class
47
  $wpdb->stream = $this->table;
48
  $wpdb->streammeta = $this->table_meta;
49
 
50
+ // Hack for get_metadata.
51
  $wpdb->recordmeta = $this->table_meta;
52
  }
53
 
75
 
76
  $record_id = $wpdb->insert_id;
77
 
78
+ // Insert record meta.
79
  foreach ( (array) $meta as $key => $vals ) {
80
  foreach ( (array) $vals as $val ) {
81
  $this->insert_meta( $record_id, $key, $val );
88
  /**
89
  * Insert record meta
90
  *
91
+ * @param int $record_id Record ID.
92
+ * @param string $key Meta Key.
93
+ * @param string $val Meta Data.
94
  *
95
  * @return array
96
  */
112
  /**
113
  * Retrieve records
114
  *
115
+ * @param array $args Query arguments.
116
  *
117
  * @return array
118
  */
127
  * GROUP BY allows query to find just the first occurrence of each value in the column,
128
  * increasing the efficiency of the query.
129
  *
130
+ * @param string $column Column being filtered.
131
  *
132
  * @return array
133
  */
classes/class-db-driver.php CHANGED
@@ -1,11 +1,21 @@
1
  <?php
 
 
 
 
 
 
 
2
  namespace WP_Stream;
3
 
 
 
 
4
  interface DB_Driver {
5
  /**
6
  * Insert a record
7
  *
8
- * @param array $data
9
  *
10
  * @return int
11
  */
@@ -14,7 +24,7 @@ interface DB_Driver {
14
  /**
15
  * Retrieve records
16
  *
17
- * @param array $args
18
  *
19
  * @return array
20
  */
@@ -24,14 +34,14 @@ interface DB_Driver {
24
  * Returns array of existing values for requested column.
25
  * Used to fill search filters with only used items, instead of all items.
26
  *
27
- * @param string $column
28
  *
29
  * @return array
30
  */
31
  public function get_column_values( $column );
32
 
33
  /**
34
- * Public getter to return table names
35
  *
36
  * @return array
37
  */
1
  <?php
2
+ /**
3
+ * Interface for a Database Driver.
4
+ *
5
+ * @todo Review. Heavy refactor maybe needed.
6
+ * @package WP_Stream
7
+ */
8
+
9
  namespace WP_Stream;
10
 
11
+ /**
12
+ * Interface - DB_Driver
13
+ */
14
  interface DB_Driver {
15
  /**
16
  * Insert a record
17
  *
18
+ * @param array $data Data to be insert into the database.
19
  *
20
  * @return int
21
  */
24
  /**
25
  * Retrieve records
26
  *
27
+ * @param array $args Argument to filter the result by.
28
  *
29
  * @return array
30
  */
34
  * Returns array of existing values for requested column.
35
  * Used to fill search filters with only used items, instead of all items.
36
  *
37
+ * @param string $column Column to pull data from.
38
  *
39
  * @return array
40
  */
41
  public function get_column_values( $column );
42
 
43
  /**
44
+ * Public getter to return the names of the tables this driver manages.
45
  *
46
  * @return array
47
  */
classes/class-db.php CHANGED
@@ -1,9 +1,18 @@
1
  <?php
 
 
 
 
 
 
2
  namespace WP_Stream;
3
 
 
 
 
4
  class DB {
5
  /**
6
- * Hold the Driver class
7
  *
8
  * @var DB_Driver
9
  */
@@ -28,7 +37,7 @@ class DB {
28
  /**
29
  * Insert a record
30
  *
31
- * @param array $record
32
  *
33
  * @return int
34
  */
@@ -50,7 +59,7 @@ class DB {
50
  $record,
51
  function( &$value, &$key ) {
52
  if ( ! is_array( $value ) ) {
53
- $value = strip_tags( $value );
54
  }
55
  }
56
  );
@@ -97,12 +106,12 @@ class DB {
97
  * @see assemble_records
98
  * @since 1.0.4
99
  *
100
- * @param string $column
101
  *
102
  * @return array
103
  */
104
  public function existing_records( $column ) {
105
- // Sanitize column
106
  $allowed_columns = array( 'ID', 'site_id', 'blog_id', 'object_id', 'user_id', 'user_role', 'created', 'summary', 'connector', 'context', 'action', 'ip' );
107
  if ( ! in_array( $column, $allowed_columns, true ) ) {
108
  return array();
@@ -131,37 +140,37 @@ class DB {
131
  /**
132
  * Get stream records
133
  *
134
- * @param array Query args
135
  *
136
  * @return array Stream Records
137
  */
138
  public function get_records( $args ) {
139
  $defaults = array(
140
- // Search param
141
  'search' => null,
142
  'search_field' => 'summary',
143
  'record_after' => null, // Deprecated, use date_after instead
144
- // Date-based filters
145
- 'date' => null, // Ex: 2015-07-01
146
- 'date_from' => null, // Ex: 2015-07-01
147
- 'date_to' => null, // Ex: 2015-07-01
148
- 'date_after' => null, // Ex: 2015-07-01T15:19:21+00:00
149
- 'date_before' => null, // Ex: 2015-07-01T15:19:21+00:00
150
- // Record ID filters
151
  'record' => null,
152
  'record__in' => array(),
153
  'record__not_in' => array(),
154
- // Pagination params
155
  'records_per_page' => get_option( 'posts_per_page', 20 ),
156
  'paged' => 1,
157
- // Order
158
  'order' => 'desc',
159
  'orderby' => 'date',
160
- // Fields selection
161
  'fields' => array(),
162
  );
163
 
164
- // Additional property fields
165
  $properties = array(
166
  'user_id' => null,
167
  'user_role' => null,
@@ -181,7 +190,7 @@ class DB {
181
  */
182
  $properties = apply_filters( 'wp_stream_query_properties', $properties );
183
 
184
- // Add property fields to defaults, including their __in/__not_in variations
185
  foreach ( $properties as $property => $default ) {
186
  if ( ! isset( $defaults[ $property ] ) ) {
187
  $defaults[ $property ] = $default;
@@ -209,7 +218,7 @@ class DB {
209
  /**
210
  * Helper function, backwards compatibility
211
  *
212
- * @param array $args Query args
213
  *
214
  * @return array Stream Records
215
  */
@@ -220,7 +229,7 @@ class DB {
220
  /**
221
  * Return the number of records found in last request
222
  *
223
- * return int
224
  */
225
  public function get_found_records_count() {
226
  return $this->found_records_count;
1
  <?php
2
+ /**
3
+ * Manage DB connections using a provided DB driver.
4
+ *
5
+ * @package WP_Stream
6
+ */
7
+
8
  namespace WP_Stream;
9
 
10
+ /**
11
+ * Class - DB
12
+ */
13
  class DB {
14
  /**
15
+ * Holds the driver instance
16
  *
17
  * @var DB_Driver
18
  */
37
  /**
38
  * Insert a record
39
  *
40
+ * @param array $record New record.
41
  *
42
  * @return int
43
  */
59
  $record,
60
  function( &$value, &$key ) {
61
  if ( ! is_array( $value ) ) {
62
+ $value = wp_strip_all_tags( $value );
63
  }
64
  }
65
  );
106
  * @see assemble_records
107
  * @since 1.0.4
108
  *
109
+ * @param string $column Table column to pull data from.
110
  *
111
  * @return array
112
  */
113
  public function existing_records( $column ) {
114
+ // Sanitize column.
115
  $allowed_columns = array( 'ID', 'site_id', 'blog_id', 'object_id', 'user_id', 'user_role', 'created', 'summary', 'connector', 'context', 'action', 'ip' );
116
  if ( ! in_array( $column, $allowed_columns, true ) ) {
117
  return array();
140
  /**
141
  * Get stream records
142
  *
143
+ * @param array $args Arguments to filter result by.
144
  *
145
  * @return array Stream Records
146
  */
147
  public function get_records( $args ) {
148
  $defaults = array(
149
+ // Search param.
150
  'search' => null,
151
  'search_field' => 'summary',
152
  'record_after' => null, // Deprecated, use date_after instead
153
+ // Date-based filters.
154
+ 'date' => null, // Ex: 2015-07-01.
155
+ 'date_from' => null, // Ex: 2015-07-01.
156
+ 'date_to' => null, // Ex: 2015-07-01.
157
+ 'date_after' => null, // Ex: 2015-07-01T15:19:21+00:00.
158
+ 'date_before' => null, // Ex: 2015-07-01T15:19:21+00:00.
159
+ // Record ID filters.
160
  'record' => null,
161
  'record__in' => array(),
162
  'record__not_in' => array(),
163
+ // Pagination params.
164
  'records_per_page' => get_option( 'posts_per_page', 20 ),
165
  'paged' => 1,
166
+ // Order.
167
  'order' => 'desc',
168
  'orderby' => 'date',
169
+ // Fields selection.
170
  'fields' => array(),
171
  );
172
 
173
+ // Additional property fields.
174
  $properties = array(
175
  'user_id' => null,
176
  'user_role' => null,
190
  */
191
  $properties = apply_filters( 'wp_stream_query_properties', $properties );
192
 
193
+ // Add property fields to defaults, including their __in/__not_in variations.
194
  foreach ( $properties as $property => $default ) {
195
  if ( ! isset( $defaults[ $property ] ) ) {
196
  $defaults[ $property ] = $default;
218
  /**
219
  * Helper function, backwards compatibility
220
  *
221
+ * @param array $args Argument to filter result by.
222
  *
223
  * @return array Stream Records
224
  */
229
  /**
230
  * Return the number of records found in last request
231
  *
232
+ * @return int
233
  */
234
  public function get_found_records_count() {
235
  return $this->found_records_count;
classes/class-export.php CHANGED
@@ -1,9 +1,18 @@
1
  <?php
 
 
 
 
 
 
2
  namespace WP_Stream;
3
 
 
 
 
4
  class Export {
5
  /**
6
- * Hold Plugin class
7
  *
8
  * @var Plugin
9
  */
@@ -73,12 +82,14 @@ class Export {
73
  /**
74
  * Add Export options to record actions menu
75
  *
 
 
76
  * @return array
77
  */
78
  public function actions_menu_export_items( $action_menu_items ) {
79
  foreach ( $this->get_exporters() as $exporter ) {
80
  $action = 'export-' . $exporter->slug;
81
- // translators: Placeholder refers to an export format (e.g. "CSV")
82
  $action_menu_items[ $action ] = sprintf( __( 'Export as %s', 'stream' ), $exporter->name );
83
  }
84
 
@@ -99,7 +110,7 @@ class Export {
99
  foreach ( array_keys( $columns ) as $column_name ) {
100
  switch ( $column_name ) {
101
  case 'date':
102
- $created = date( 'Y-m-d H:i:s', strtotime( $record->created ) );
103
  $row_out[ $column_name ] = get_date_from_gmt( $created, 'Y/m/d h:i:s A' );
104
  break;
105
 
@@ -203,7 +214,7 @@ class Export {
203
  */
204
  $this->exporters = apply_filters( 'wp_stream_exporters', $classes );
205
 
206
- // Ensure that all exporters extend Exporter
207
  foreach ( $this->exporters as $key => $exporter ) {
208
  if ( ! $this->is_valid_exporter( $exporter ) ) {
209
  unset( $this->exporters[ $key ] );
1
  <?php
2
+ /**
3
+ * Loads & Manages exporter classes.
4
+ *
5
+ * @package WP_Stream
6
+ */
7
+
8
  namespace WP_Stream;
9
 
10
+ /**
11
+ * Class - Export
12
+ */
13
  class Export {
14
  /**
15
+ * Holds instance of plugin object
16
  *
17
  * @var Plugin
18
  */
82
  /**
83
  * Add Export options to record actions menu
84
  *
85
+ * @param array $action_menu_items Export types.
86
+ *
87
  * @return array
88
  */
89
  public function actions_menu_export_items( $action_menu_items ) {
90
  foreach ( $this->get_exporters() as $exporter ) {
91
  $action = 'export-' . $exporter->slug;
92
+ /* translators: %s: an export format (e.g. "CSV") */
93
  $action_menu_items[ $action ] = sprintf( __( 'Export as %s', 'stream' ), $exporter->name );
94
  }
95
 
110
  foreach ( array_keys( $columns ) as $column_name ) {
111
  switch ( $column_name ) {
112
  case 'date':
113
+ $created = gmdate( 'Y-m-d H:i:s', strtotime( $record->created ) );
114
  $row_out[ $column_name ] = get_date_from_gmt( $created, 'Y/m/d h:i:s A' );
115
  break;
116
 
214
  */
215
  $this->exporters = apply_filters( 'wp_stream_exporters', $classes );
216
 
217
+ // Ensure that all exporters extend Exporter.
218
  foreach ( $this->exporters as $key => $exporter ) {
219
  if ( ! $this->is_valid_exporter( $exporter ) ) {
220
  unset( $this->exporters[ $key ] );
classes/class-exporter.php CHANGED
@@ -1,6 +1,15 @@
1
  <?php
 
 
 
 
 
 
2
  namespace WP_Stream;
3
 
 
 
 
4
  abstract class Exporter {
5
  /**
6
  * Exporter name
1
  <?php
2
+ /**
3
+ * Abstract class for record exporters
4
+ *
5
+ * @package WP_Stream
6
+ */
7
+
8
  namespace WP_Stream;
9
 
10
+ /**
11
+ * Class - Exporter
12
+ */
13
  abstract class Exporter {
14
  /**
15
  * Exporter name
classes/class-filter-input.php CHANGED
@@ -1,10 +1,25 @@
1
  <?php
 
 
 
 
 
 
2
  namespace WP_Stream;
3
 
 
 
 
4
  class Filter_Input {
 
 
 
 
 
 
5
  public static $filter_callbacks = array(
6
  FILTER_DEFAULT => null,
7
- // Validate
8
  FILTER_VALIDATE_BOOLEAN => 'is_bool',
9
  FILTER_VALIDATE_EMAIL => 'is_email',
10
  FILTER_VALIDATE_FLOAT => 'is_float',
@@ -12,7 +27,7 @@ class Filter_Input {
12
  FILTER_VALIDATE_IP => array( __CLASS__, 'is_ip_address' ),
13
  FILTER_VALIDATE_REGEXP => array( __CLASS__, 'is_regex' ),
14
  FILTER_VALIDATE_URL => 'wp_http_validate_url',
15
- // Sanitize
16
  FILTER_SANITIZE_EMAIL => 'sanitize_email',
17
  FILTER_SANITIZE_ENCODED => 'esc_url_raw',
18
  FILTER_SANITIZE_NUMBER_FLOAT => 'floatval',
@@ -20,10 +35,20 @@ class Filter_Input {
20
  FILTER_SANITIZE_SPECIAL_CHARS => 'htmlspecialchars',
21
  FILTER_SANITIZE_STRING => 'sanitize_text_field',
22
  FILTER_SANITIZE_URL => 'esc_url_raw',
23
- // Other
24
  FILTER_UNSAFE_RAW => null,
25
  );
26
 
 
 
 
 
 
 
 
 
 
 
27
  public static function super( $type, $variable_name, $filter = null, $options = array() ) {
28
  $super = null;
29
 
@@ -57,11 +82,20 @@ class Filter_Input {
57
  return $var;
58
  }
59
 
 
 
 
 
 
 
 
 
 
60
  public static function filter( $var, $filter = null, $options = array() ) {
61
- // Default filter is a sanitizer, not validator
62
  $filter_type = 'sanitizer';
63
 
64
- // Only filter value if it is not null
65
  if ( isset( $var ) && $filter && FILTER_DEFAULT !== $filter ) {
66
  if ( ! isset( self::$filter_callbacks[ $filter ] ) ) {
67
  throw new \Exception( esc_html__( 'Filter not supported.', 'stream' ) );
@@ -70,20 +104,22 @@ class Filter_Input {
70
  $filter_callback = self::$filter_callbacks[ $filter ];
71
  $result = call_user_func( $filter_callback, $var );
72
 
73
- // filter_var / filter_input treats validation/sanitization filters the same
74
- // they both return output and change the var value, this shouldn't be the case here.
75
- // We'll do a boolean check on validation function, and let sanitizers change the value
 
 
76
  $filter_type = ( $filter < 500 ) ? 'validator' : 'sanitizer';
77
- if ( 'validator' === $filter_type ) { // Validation functions
78
  if ( ! $result ) {
79
  $var = false;
80
  }
81
- } else { // Santization functions
82
  $var = $result;
83
  }
84
  }
85
 
86
- // Detect FILTER_REQUIRE_ARRAY flag
87
  if ( isset( $var ) && is_int( $options ) && FILTER_REQUIRE_ARRAY === $options ) {
88
  if ( ! is_array( $var ) ) {
89
  $var = ( 'validator' === $filter_type ) ? false : null;
@@ -102,6 +138,12 @@ class Filter_Input {
102
  return $var;
103
  }
104
 
 
 
 
 
 
 
105
  public static function is_regex( $var ) {
106
  // @codingStandardsIgnoreStart
107
  $test = @preg_match( $var, '' );
@@ -110,6 +152,12 @@ class Filter_Input {
110
  return false !== $test;
111
  }
112
 
 
 
 
 
 
 
113
  public static function is_ip_address( $var ) {
114
  return false !== \WP_Http::is_ip_address( $var );
115
  }
1
  <?php
2
+ /**
3
+ * Processes form input
4
+ *
5
+ * @package WP_Stream
6
+ */
7
+
8
  namespace WP_Stream;
9
 
10
+ /**
11
+ * Class - Filter_Input
12
+ */
13
  class Filter_Input {
14
+
15
+ /**
16
+ * Callbacks to be used for input validation/sanitation.
17
+ *
18
+ * @var array
19
+ */
20
  public static $filter_callbacks = array(
21
  FILTER_DEFAULT => null,
22
+ // Validate.
23
  FILTER_VALIDATE_BOOLEAN => 'is_bool',
24
  FILTER_VALIDATE_EMAIL => 'is_email',
25
  FILTER_VALIDATE_FLOAT => 'is_float',
27
  FILTER_VALIDATE_IP => array( __CLASS__, 'is_ip_address' ),
28
  FILTER_VALIDATE_REGEXP => array( __CLASS__, 'is_regex' ),
29
  FILTER_VALIDATE_URL => 'wp_http_validate_url',
30
+ // Sanitize.
31
  FILTER_SANITIZE_EMAIL => 'sanitize_email',
32
  FILTER_SANITIZE_ENCODED => 'esc_url_raw',
33
  FILTER_SANITIZE_NUMBER_FLOAT => 'floatval',
35
  FILTER_SANITIZE_SPECIAL_CHARS => 'htmlspecialchars',
36
  FILTER_SANITIZE_STRING => 'sanitize_text_field',
37
  FILTER_SANITIZE_URL => 'esc_url_raw',
38
+ // Other.
39
  FILTER_UNSAFE_RAW => null,
40
  );
41
 
42
+ /**
43
+ * Returns input variable
44
+ *
45
+ * @param int $type Input type.
46
+ * @param string $variable_name Variable key.
47
+ * @param int $filter Filter callback.
48
+ * @param array $options Filter callback parameters.
49
+ * @throws \Exception Invalid input type provided.
50
+ * @return mixed
51
+ */
52
  public static function super( $type, $variable_name, $filter = null, $options = array() ) {
53
  $super = null;
54
 
82
  return $var;
83
  }
84
 
85
+ /**
86
+ * Sanitize or validate input.
87
+ *
88
+ * @param mixed $var Raw input.
89
+ * @param int $filter Filter callback.
90
+ * @param array $options Filter callback parameters.
91
+ * @throws \Exception Unsupported filter provided.
92
+ * @return mixed
93
+ */
94
  public static function filter( $var, $filter = null, $options = array() ) {
95
+ // Default filter is a sanitizer, not validator.
96
  $filter_type = 'sanitizer';
97
 
98
+ // Only filter value if it is not null.
99
  if ( isset( $var ) && $filter && FILTER_DEFAULT !== $filter ) {
100
  if ( ! isset( self::$filter_callbacks[ $filter ] ) ) {
101
  throw new \Exception( esc_html__( 'Filter not supported.', 'stream' ) );
104
  $filter_callback = self::$filter_callbacks[ $filter ];
105
  $result = call_user_func( $filter_callback, $var );
106
 
107
+ /**
108
+ * "filter_var / filter_input" treats validation/sanitization filters the same
109
+ * they both return output and change the var value, this shouldn't be the case here.
110
+ * We'll do a boolean check on validation function, and let sanitizers change the value
111
+ */
112
  $filter_type = ( $filter < 500 ) ? 'validator' : 'sanitizer';
113
+ if ( 'validator' === $filter_type ) { // Validation functions.
114
  if ( ! $result ) {
115
  $var = false;
116
  }
117
+ } else { // Santization functions.
118
  $var = $result;
119
  }
120
  }
121
 
122
+ // Detect FILTER_REQUIRE_ARRAY flag.
123
  if ( isset( $var ) && is_int( $options ) && FILTER_REQUIRE_ARRAY === $options ) {
124
  if ( ! is_array( $var ) ) {
125
  $var = ( 'validator' === $filter_type ) ? false : null;
138
  return $var;
139
  }
140
 
141
+ /**
142
+ * Returns whether the variable is a Regular Expression or not?
143
+ *
144
+ * @param string $var Raw input.
145
+ * @return boolean
146
+ */
147
  public static function is_regex( $var ) {
148
  // @codingStandardsIgnoreStart
149
  $test = @preg_match( $var, '' );
152
  return false !== $test;
153
  }
154
 
155
+ /**
156
+ * Returns whether the variable is an IP address or not?
157
+ *
158
+ * @param string $var Raw input.
159
+ * @return boolean
160
+ */
161
  public static function is_ip_address( $var ) {
162
  return false !== \WP_Http::is_ip_address( $var );
163
  }
classes/class-form-generator.php CHANGED
@@ -1,6 +1,15 @@
1
  <?php
 
 
 
 
 
 
2
  namespace WP_Stream;
3
 
 
 
 
4
  class Form_Generator {
5
 
6
  /**
1
  <?php
2
+ /**
3
+ * Generates an WP Admin form.
4
+ *
5
+ * @package WP_Stream
6
+ */
7
+
8
  namespace WP_Stream;
9
 
10
+ /**
11
+ * Class - Form_Generator
12
+ */
13
  class Form_Generator {
14
 
15
  /**
classes/class-install.php CHANGED
@@ -1,9 +1,18 @@
1
  <?php
 
 
 
 
 
 
2
  namespace WP_Stream;
3
 
 
 
 
4
  class Install {
5
  /**
6
- * Hold Plugin class
7
  *
8
  * @var Plugin
9
  */
@@ -53,6 +62,8 @@ class Install {
53
 
54
  /**
55
  * Class constructor
 
 
56
  */
57
  public function __construct( $plugin ) {
58
  $this->plugin = $plugin;
@@ -60,10 +71,10 @@ class Install {
60
  $this->db_version = $this->get_db_version();
61
  $this->stream_url = self_admin_url( $this->plugin->admin->admin_parent_page . '&page=' . $this->plugin->admin->settings_page_slug );
62
 
63
- // Check DB and display an admin notice if there are tables missing
64
  add_action( 'init', array( $this, 'verify_db' ) );
65
 
66
- // Install the plugin
67
  add_action( 'wp_stream_before_db_notices', array( $this, 'check' ) );
68
 
69
  register_activation_hook( $this->plugin->locations['plugin'], array( $this, 'check' ) );
@@ -157,7 +168,7 @@ class Install {
157
  $database_message = '';
158
  $uninstall_message = '';
159
 
160
- // Check if all needed DB is present
161
  $missing_tables = array();
162
 
163
  foreach ( $this->plugin->db->get_table_names() as $table_name ) {
@@ -184,14 +195,14 @@ class Install {
184
 
185
  if ( $this->plugin->is_network_activated() && current_user_can( 'manage_network_plugins' ) ) {
186
  $uninstall_message = sprintf(
187
- // translators: Placeholders refer to HTML Link tags (e.g. "<a href="https://foo.com/wp-admin/">")
188
  __( 'Please %1$suninstall%2$s the Stream plugin and activate it again.', 'stream' ),
189
  '<a href="' . network_admin_url( 'plugins.php#stream' ) . '">',
190
  '</a>'
191
  );
192
  } elseif ( current_user_can( 'activate_plugins' ) ) {
193
  $uninstall_message = sprintf(
194
- // translators: Placeholders refer to HTML Link tags (e.g. "<a href="https://foo.com/wp-admin/">")
195
  __( 'Please %1$suninstall%2$s the Stream plugin and activate it again.', 'stream' ),
196
  '<a href="' . admin_url( 'plugins.php#stream' ) . '">',
197
  '</a>'
@@ -211,7 +222,7 @@ class Install {
211
  * Register a routine to be called when stream or a stream connector has been updated
212
  * It works by comparing the current version with the version previously stored in the database.
213
  *
214
- * @param string $file A reference to the main plugin file
215
  * @param string $callback The function to run when the hook is called.
216
  * @param string $version The version to which the plugin is updating.
217
  *
@@ -248,6 +259,8 @@ class Install {
248
  }
249
 
250
  /**
 
 
251
  * @return string
252
  */
253
  public function get_db_version() {
@@ -255,7 +268,7 @@ class Install {
255
  }
256
 
257
  /**
258
- * @return void
259
  */
260
  public function update_db_option() {
261
  if ( $this->success_db ) {
@@ -344,7 +357,7 @@ class Install {
344
  <p>
345
  <?php
346
  printf(
347
- // translators: Placeholders refer to version numbers (e.g. "4.2")
348
  esc_html__( 'Your Stream database has been successfully updated from %1$s to %2$s!', 'stream' ),
349
  esc_html( $this->db_version ),
350
  esc_html( $this->plugin->get_version() )
@@ -387,9 +400,9 @@ class Install {
387
  /**
388
  * Database user controlled update routine
389
  *
390
- * @param int $db_version
391
- * @param int $current_version
392
- * @param array $update_args
393
  *
394
  * @return mixed Version number on success, true on no update needed, mysql error message on error
395
  */
@@ -419,7 +432,7 @@ class Install {
419
  /**
420
  * Initial database install routine
421
  *
422
- * @param string $current_version
423
  *
424
  * @return string
425
  */
1
  <?php
2
+ /**
3
+ * Handles database migrations
4
+ *
5
+ * @package WP_Stream
6
+ */
7
+
8
  namespace WP_Stream;
9
 
10
+ /**
11
+ * Class - Install
12
+ */
13
  class Install {
14
  /**
15
+ * Holds Instance of plugin object
16
  *
17
  * @var Plugin
18
  */
62
 
63
  /**
64
  * Class constructor
65
+ *
66
+ * @param Plugin $plugin Instance of plugin object.
67
  */
68
  public function __construct( $plugin ) {
69
  $this->plugin = $plugin;
71
  $this->db_version = $this->get_db_version();
72
  $this->stream_url = self_admin_url( $this->plugin->admin->admin_parent_page . '&page=' . $this->plugin->admin->settings_page_slug );
73
 
74
+ // Check DB and display an admin notice if there are tables missing.
75
  add_action( 'init', array( $this, 'verify_db' ) );
76
 
77
+ // Install the plugin.
78
  add_action( 'wp_stream_before_db_notices', array( $this, 'check' ) );
79
 
80
  register_activation_hook( $this->plugin->locations['plugin'], array( $this, 'check' ) );
168
  $database_message = '';
169
  $uninstall_message = '';
170
 
171
+ // Check if all needed DB is present.
172
  $missing_tables = array();
173
 
174
  foreach ( $this->plugin->db->get_table_names() as $table_name ) {
195
 
196
  if ( $this->plugin->is_network_activated() && current_user_can( 'manage_network_plugins' ) ) {
197
  $uninstall_message = sprintf(
198
+ /* translators: %#$s: HTML Link tags (e.g. "<a href="https://foo.com/wp-admin/">") */
199
  __( 'Please %1$suninstall%2$s the Stream plugin and activate it again.', 'stream' ),
200
  '<a href="' . network_admin_url( 'plugins.php#stream' ) . '">',
201
  '</a>'
202
  );
203
  } elseif ( current_user_can( 'activate_plugins' ) ) {
204
  $uninstall_message = sprintf(
205
+ /* translators: %#$s: HTML Link tags (e.g. "<a href="https://foo.com/wp-admin/">") */
206
  __( 'Please %1$suninstall%2$s the Stream plugin and activate it again.', 'stream' ),
207
  '<a href="' . admin_url( 'plugins.php#stream' ) . '">',
208
  '</a>'
222
  * Register a routine to be called when stream or a stream connector has been updated
223
  * It works by comparing the current version with the version previously stored in the database.
224
  *
225
+ * @param string $file A reference to the main plugin file.
226
  * @param string $callback The function to run when the hook is called.
227
  * @param string $version The version to which the plugin is updating.
228
  *
259
  }
260
 
261
  /**
262
+ * Returns the database version.
263
+ *
264
  * @return string
265
  */
266
  public function get_db_version() {
268
  }
269
 
270
  /**
271
+ * Checks if migration was successful.
272
  */
273
  public function update_db_option() {
274
  if ( $this->success_db ) {
357
  <p>
358
  <?php
359
  printf(
360
+ /* translators: %1$s: old version, %2$s: new version (e.g. "4.2") */
361
  esc_html__( 'Your Stream database has been successfully updated from %1$s to %2$s!', 'stream' ),
362
  esc_html( $this->db_version ),
363
  esc_html( $this->plugin->get_version() )
400
  /**
401
  * Database user controlled update routine
402
  *
403
+ * @param int $db_version Next database version.
404
+ * @param int $current_version Current database version.
405
+ * @param array $update_args Update options.
406
  *
407
  * @return mixed Version number on success, true on no update needed, mysql error message on error
408
  */
432
  /**
433
  * Initial database install routine
434
  *
435
+ * @param string $current_version Current database version.
436
  *
437
  * @return string
438
  */
classes/class-list-table.php CHANGED
@@ -1,11 +1,19 @@
1
  <?php
 
 
 
 
 
2
 
3
  namespace WP_Stream;
4
 
 
 
 
5
  class List_Table extends \WP_List_Table {
6
 
7
  /**
8
- * Hold Plugin class
9
  *
10
  * @var Plugin
11
  */
@@ -14,8 +22,8 @@ class List_Table extends \WP_List_Table {
14
  /**
15
  * Class constructor.
16
  *
17
- * @param Plugin $plugin The main Plugin class.
18
- * @param array $args
19
  */
20
  public function __construct( $plugin, $args = array() ) {
21
  $this->plugin = $plugin;
@@ -46,7 +54,7 @@ class List_Table extends \WP_List_Table {
46
  )
47
  );
48
 
49
- // Check for default hidden columns
50
  $this->get_hidden_columns();
51
 
52
  add_filter(
@@ -71,12 +79,23 @@ class List_Table extends \WP_List_Table {
71
  set_screen_options();
72
  }
73
 
 
 
 
 
 
 
74
  public function extra_tablenav( $which ) {
75
  if ( 'top' === $which ) {
76
- echo $this->filters_form(); // xss ok
77
  }
78
  }
79
 
 
 
 
 
 
80
  public function no_items() {
81
  ?>
82
  <div class="stream-list-table-no-items">
@@ -85,6 +104,11 @@ class List_Table extends \WP_List_Table {
85
  <?php
86
  }
87
 
 
 
 
 
 
88
  public function get_columns() {
89
  /**
90
  * Allows devs to add new columns to table
@@ -104,22 +128,32 @@ class List_Table extends \WP_List_Table {
104
  );
105
  }
106
 
 
 
 
 
 
107
  public function get_sortable_columns() {
108
  return array(
109
  'date' => array( 'date', false ),
110
  );
111
  }
112
 
 
 
 
 
 
113
  public function get_hidden_columns() {
114
  $user = wp_get_current_user();
115
  if ( ! $user ) {
116
  return array();
117
  }
118
 
119
- // Directly checking the user meta; to check whether user has changed screen option or not
120
  $hidden = $this->plugin->admin->get_user_meta( $user->ID, 'manage' . $this->screen->id . 'columnshidden', true );
121
 
122
- // If user meta is not found; add the default hidden column 'id'
123
  if ( ! $hidden ) {
124
  $hidden = array( 'id' );
125
  $this->plugin->admin->update_user_meta( $user->ID, 'manage' . $this->screen->id . 'columnshidden', $hidden );
@@ -128,6 +162,11 @@ class List_Table extends \WP_List_Table {
128
  return $hidden;
129
  }
130
 
 
 
 
 
 
131
  public function prepare_items() {
132
  $columns = $this->get_columns();
133
  $sortable = $this->get_sortable_columns();
@@ -153,10 +192,15 @@ class List_Table extends \WP_List_Table {
153
  );
154
  }
155
 
 
 
 
 
 
156
  public function get_records() {
157
  $args = array();
158
 
159
- // Parse sorting params
160
  $order = wp_stream_filter_input( INPUT_GET, 'order' );
161
  if ( $order ) {
162
  $args['order'] = $order;
@@ -184,7 +228,7 @@ class List_Table extends \WP_List_Table {
184
  }
185
  }
186
 
187
- // Additional filter properties
188
  $properties = array(
189
  'record',
190
  'site_id',
@@ -198,11 +242,11 @@ class List_Table extends \WP_List_Table {
198
  'action',
199
  );
200
 
201
- // Add property fields to defaults, including their __in/__not_in variations
202
  foreach ( $properties as $property ) {
203
  $value = wp_stream_filter_input( INPUT_GET, $property );
204
 
205
- // Allow 0 values
206
  if ( isset( $value ) && '' !== $value && false !== $value ) {
207
  $args[ $property ] = $value;
208
  }
@@ -246,13 +290,20 @@ class List_Table extends \WP_List_Table {
246
  return $this->plugin->db->get_found_records_count();
247
  }
248
 
 
 
 
 
 
 
 
249
  public function column_default( $item, $column_name ) {
250
  $out = '';
251
  $record = new Record( $item );
252
 
253
  switch ( $column_name ) {
254
  case 'date':
255
- $created = date( 'Y-m-d H:i:s', strtotime( $record->created ) );
256
  $date_string = sprintf(
257
  '<time datetime="%s" class="relative-time record-created">%s</time>',
258
  wp_stream_get_iso_8601_extended_date( strtotime( $record->created ) ),
@@ -266,7 +317,7 @@ class List_Table extends \WP_List_Table {
266
  case 'summary':
267
  $out = $record->summary;
268
  $object_title = $record->get_object_title();
269
- // translators: Placeholder refers to the title of any object, like a Post (e.g. "Hello World")
270
  $view_all_text = $object_title ? sprintf( esc_html__( 'View all activity for "%s"', 'stream' ), esc_attr( $object_title ) ) : esc_html__( 'View all activity for this object', 'stream' );
271
 
272
  if ( $record->object_id ) {
@@ -381,6 +432,12 @@ class List_Table extends \WP_List_Table {
381
  echo wp_kses( $out, $allowed_tags );
382
  }
383
 
 
 
 
 
 
 
384
  public function get_action_links( $record ) {
385
  $out = '';
386
 
@@ -434,6 +491,15 @@ class List_Table extends \WP_List_Table {
434
  return $out;
435
  }
436
 
 
 
 
 
 
 
 
 
 
437
  public function column_link( $display, $key, $value = null, $title = null ) {
438
  $url = add_query_arg(
439
  array(
@@ -458,6 +524,13 @@ class List_Table extends \WP_List_Table {
458
  );
459
  }
460
 
 
 
 
 
 
 
 
461
  public function get_term_title( $term, $type ) {
462
  if ( ! isset( $this->plugin->connectors->term_labels[ 'stream_' . $type ][ $term ] ) ) {
463
  return $term;
@@ -473,7 +546,7 @@ class List_Table extends \WP_List_Table {
473
  * results of existing records. All items that do not exist in records
474
  * get assigned a disabled value of "true".
475
  *
476
- * @param string $column List table column name
477
  *
478
  * @return array Options to be displayed in search filters
479
  */
@@ -482,7 +555,7 @@ class List_Table extends \WP_List_Table {
482
  if ( 'user_id' === $column ) {
483
  $all_records = array();
484
 
485
- // If the number of users exceeds the max users constant value then return an empty array and use AJAX instead
486
  $user_count = count_users();
487
  $total_users = $user_count['total_users'];
488
 
@@ -555,7 +628,7 @@ class List_Table extends \WP_List_Table {
555
  }
556
  }
557
 
558
- // Remove WP-CLI pseudo user if no records with user=0 exist
559
  if ( isset( $disabled_records[0] ) ) {
560
  unset( $disabled_records[0] );
561
  }
@@ -574,12 +647,17 @@ class List_Table extends \WP_List_Table {
574
  uasort( $active_records, $sort );
575
  uasort( $disabled_records, $sort );
576
 
577
- // Not using array_merge() in order to preserve the array index for the users dropdown which uses the user_id as the key
578
  $all_records = $active_records + $disabled_records;
579
 
580
  return $all_records;
581
  }
582
 
 
 
 
 
 
583
  public function get_filters() {
584
  $filters = array();
585
 
@@ -620,6 +698,11 @@ class List_Table extends \WP_List_Table {
620
  return apply_filters( 'wp_stream_list_table_filters', $filters );
621
  }
622
 
 
 
 
 
 
623
  public function filters_form() {
624
  $filters = $this->get_filters();
625
 
@@ -641,7 +724,7 @@ class List_Table extends \WP_List_Table {
641
  $filters_string .= $this->filter_date( $data['items'] );
642
  } else {
643
  if ( 'context' === $name ) {
644
- // Add Connectors as parents, and apply the Contexts as children
645
  $connectors = $this->assemble_records( 'connector' );
646
  $context_items = array();
647
 
@@ -657,7 +740,7 @@ class List_Table extends \WP_List_Table {
657
  if ( isset( $context_items[ $connector ]['children'] ) ) {
658
  $labels = wp_list_pluck( $context_items[ $connector ]['children'], 'label' );
659
 
660
- // Sort child items by label
661
  array_multisort( $labels, SORT_ASC, $context_items[ $connector ]['children'] );
662
  }
663
  }
@@ -672,10 +755,10 @@ class List_Table extends \WP_List_Table {
672
 
673
  $labels = wp_list_pluck( $data['items'], 'label' );
674
 
675
- // Sort top-level items by label
676
  array_multisort( $labels, SORT_ASC, $data['items'] );
677
 
678
- // Output a hidden input to handle the connector value
679
  $filters_string .= sprintf(
680
  '<input type="hidden" name="connector" class="record-filter-connector" value="%s" />',
681
  esc_attr( wp_stream_filter_input( INPUT_GET, 'connector' ) )
@@ -688,14 +771,14 @@ class List_Table extends \WP_List_Table {
688
 
689
  $filters_string .= sprintf( '<input type="submit" id="record-query-submit" class="button" value="%s" />', __( 'Filter', 'stream' ) );
690
 
691
- // Parse all query vars into an array
692
  $query_vars = array();
693
 
694
  if ( isset( $_SERVER['QUERY_STRING'] ) ) {
695
  parse_str( urldecode( $_SERVER['QUERY_STRING'] ), $query_vars );
696
  }
697
 
698
- // Ignore certain query vars and query vars that are empty
699
  foreach ( $query_vars as $query_var => $value ) {
700
  if ( '' === $value || 'page' === $query_var || 'paged' === $query_var ) {
701
  unset( $query_vars[ $query_var ] );
@@ -709,14 +792,23 @@ class List_Table extends \WP_List_Table {
709
  self_admin_url( $this->plugin->admin->admin_parent_page )
710
  );
711
 
712
- // Display reset action if records are being filtered
713
  if ( ! empty( $query_vars ) ) {
714
  $filters_string .= sprintf( '<a href="%s" id="record-query-reset"><span class="dashicons dashicons-dismiss"></span> <span class="record-query-reset-text">%s</span></a>', esc_url( $url ), __( 'Reset filters', 'stream' ) );
715
  }
716
 
717
- return sprintf( '<div class="alignleft actions">%s</div>', $filters_string ); // xss ok
718
  }
719
 
 
 
 
 
 
 
 
 
 
720
  public function filter_select( $name, $title, $items, $ajax = false ) {
721
  $options = array( '<option value=""></option>' );
722
  $selected = wp_stream_filter_input( INPUT_GET, $name );
@@ -754,7 +846,7 @@ class List_Table extends \WP_List_Table {
754
  $out = sprintf(
755
  '<select name="%s" class="chosen-select" data-placeholder="%s">%s</select>',
756
  esc_attr( $name ),
757
- // translators: Placeholder refers to the title of the dropdown menu (e.g. "users")
758
  sprintf( esc_attr__( 'Show all %s', 'stream' ), $title ),
759
  implode( '', $options )
760
  );
@@ -762,6 +854,12 @@ class List_Table extends \WP_List_Table {
762
  return $out;
763
  }
764
 
 
 
 
 
 
 
765
  public function filter_option( $args ) {
766
  $defaults = array(
767
  'value' => null,
@@ -788,10 +886,15 @@ class List_Table extends \WP_List_Table {
788
  );
789
  }
790
 
 
 
 
 
 
791
  public function filter_search() {
792
  $search = null;
793
- if ( isset( $_GET['search'] ) ) { // CSRF okay
794
- $search = esc_attr( wp_unslash( $_GET['search'] ) ); // input var okay, CSRF okay
795
  }
796
  $out = sprintf(
797
  '<p class="search-box">
@@ -806,6 +909,12 @@ class List_Table extends \WP_List_Table {
806
  return $out;
807
  }
808
 
 
 
 
 
 
 
809
  public function filter_date( $items ) {
810
  wp_enqueue_style( 'jquery-ui' );
811
  wp_enqueue_style( 'wp-stream-datepicker' );
@@ -903,19 +1012,27 @@ class List_Table extends \WP_List_Table {
903
  return ob_get_clean();
904
  }
905
 
 
 
 
906
  public function display() {
907
  $url = self_admin_url( $this->plugin->admin->admin_parent_page );
908
 
909
  echo '<form method="get" action="' . esc_url( $url ) . '" id="record-filter-form">';
910
- echo $this->filter_search(); // xss ok
911
  parent::display();
912
  echo '</form>';
913
 
914
  echo '<form method="get" action="' . esc_url( $url ) . '" id="record-actions-form">';
915
- echo $this->record_actions_form(); // xss ok
916
  echo '</form>';
917
  }
918
 
 
 
 
 
 
919
  public function single_row( $item ) {
920
  $classes = apply_filters( 'wp_stream_record_classes', array(), $item );
921
  $class_string = '';
@@ -923,11 +1040,16 @@ class List_Table extends \WP_List_Table {
923
  $class_string = ' class="' . esc_attr( join( ' ', $classes ) ) . '"';
924
  }
925
 
926
- echo sprintf( '<tr%s>', $class_string ); // xss ok
927
  $this->single_row_columns( $item );
928
  echo '</tr>';
929
  }
930
 
 
 
 
 
 
931
  public function display_tablenav( $which ) {
932
  if ( 'top' === $which ) :
933
  ?>
@@ -956,6 +1078,14 @@ class List_Table extends \WP_List_Table {
956
  endif;
957
  }
958
 
 
 
 
 
 
 
 
 
959
  public function set_screen_option( $dummy, $option, $value ) {
960
  if ( 'edit_stream_per_page' === $option ) {
961
  return $value;
@@ -964,6 +1094,14 @@ class List_Table extends \WP_List_Table {
964
  }
965
  }
966
 
 
 
 
 
 
 
 
 
967
  public function set_live_update_option( $dummy, $option, $value ) {
968
  unset( $value );
969
 
@@ -983,6 +1121,13 @@ class List_Table extends \WP_List_Table {
983
  return $dummy;
984
  }
985
 
 
 
 
 
 
 
 
986
  public function screen_controls( $status, $args ) {
987
  unset( $status );
988
  unset( $args );
@@ -1025,7 +1170,7 @@ class List_Table extends \WP_List_Table {
1025
  /**
1026
  * This function is use to map List table column name with excluded setting keys
1027
  *
1028
- * @param string $column List table column name
1029
  *
1030
  * @return string setting name for that column
1031
  */
@@ -1056,7 +1201,7 @@ class List_Table extends \WP_List_Table {
1056
  /**
1057
  * Get users as dropdown items
1058
  *
1059
- * @param array $users
1060
  *
1061
  * @return array
1062
  */
1
  <?php
2
+ /**
3
+ * Generates a filterable list of provided records to be displayed HTML Table.
4
+ *
5
+ * @package WP_Stream
6
+ */
7
 
8
  namespace WP_Stream;
9
 
10
+ /**
11
+ * Class - List_Table
12
+ */
13
  class List_Table extends \WP_List_Table {
14
 
15
  /**
16
+ * Holds Instance of plugin object
17
  *
18
  * @var Plugin
19
  */
22
  /**
23
  * Class constructor.
24
  *
25
+ * @param Plugin $plugin Instance of plugin object.
26
+ * @param array $args Argument to filter rows by.
27
  */
28
  public function __construct( $plugin, $args = array() ) {
29
  $this->plugin = $plugin;
54
  )
55
  );
56
 
57
+ // Check for default hidden columns.
58
  $this->get_hidden_columns();
59
 
60
  add_filter(
79
  set_screen_options();
80
  }
81
 
82
+ /**
83
+ * Renders extra from navigation options.
84
+ *
85
+ * @param string $which Page location.
86
+ * @return void
87
+ */
88
  public function extra_tablenav( $which ) {
89
  if ( 'top' === $which ) {
90
+ echo $this->filters_form(); // xss ok.
91
  }
92
  }
93
 
94
+ /**
95
+ * Renders "No items found" message.
96
+ *
97
+ * @return void
98
+ */
99
  public function no_items() {
100
  ?>
101
  <div class="stream-list-table-no-items">
104
  <?php
105
  }
106
 
107
+ /**
108
+ * Returns the table columns to be rendered.
109
+ *
110
+ * @return array
111
+ */
112
  public function get_columns() {
113
  /**
114
  * Allows devs to add new columns to table
128
  );
129
  }
130
 
131
+ /**
132
+ * Returns the columns the items can be sort by.
133
+ *
134
+ * @return array
135
+ */
136
  public function get_sortable_columns() {
137
  return array(
138
  'date' => array( 'date', false ),
139
  );
140
  }
141
 
142
+ /**
143
+ * Returns columns hidden from all except specific users.
144
+ *
145
+ * @return array|bool
146
+ */
147
  public function get_hidden_columns() {
148
  $user = wp_get_current_user();
149
  if ( ! $user ) {
150
  return array();
151
  }
152
 
153
+ // Directly checking the user meta; to check whether user has changed screen option or not.
154
  $hidden = $this->plugin->admin->get_user_meta( $user->ID, 'manage' . $this->screen->id . 'columnshidden', true );
155
 
156
+ // If user meta is not found; add the default hidden column 'id'.
157
  if ( ! $hidden ) {
158
  $hidden = array( 'id' );
159
  $this->plugin->admin->update_user_meta( $user->ID, 'manage' . $this->screen->id . 'columnshidden', $hidden );
162
  return $hidden;
163
  }
164
 
165
+ /**
166
+ * Prepares table columns and data for render
167
+ *
168
+ * @return void
169
+ */
170
  public function prepare_items() {
171
  $columns = $this->get_columns();
172
  $sortable = $this->get_sortable_columns();
192
  );
193
  }
194
 
195
+ /**
196
+ * Returns records to be displayed
197
+ *
198
+ * @return array
199
+ */
200
  public function get_records() {
201
  $args = array();
202
 
203
+ // Parse sorting params.
204
  $order = wp_stream_filter_input( INPUT_GET, 'order' );
205
  if ( $order ) {
206
  $args['order'] = $order;
228
  }
229
  }
230
 
231
+ // Additional filter properties.
232
  $properties = array(
233
  'record',
234
  'site_id',
242
  'action',
243
  );
244
 
245
+ // Add property fields to defaults, including their __in/__not_in variations.
246
  foreach ( $properties as $property ) {
247
  $value = wp_stream_filter_input( INPUT_GET, $property );
248
 
249
+ // Allow 0 values.
250
  if ( isset( $value ) && '' !== $value && false !== $value ) {
251
  $args[ $property ] = $value;
252
  }
290
  return $this->plugin->db->get_found_records_count();
291
  }
292
 
293
+ /**
294
+ * Returns the column content for the provided item and column.
295
+ *
296
+ * @param array $item Record data.
297
+ * @param string $column_name Column name.
298
+ * @return void
299
+ */
300
  public function column_default( $item, $column_name ) {
301
  $out = '';
302
  $record = new Record( $item );
303
 
304
  switch ( $column_name ) {
305
  case 'date':
306
+ $created = gmdate( 'Y-m-d H:i:s', strtotime( $record->created ) );
307
  $date_string = sprintf(
308
  '<time datetime="%s" class="relative-time record-created">%s</time>',
309
  wp_stream_get_iso_8601_extended_date( strtotime( $record->created ) ),
317
  case 'summary':
318
  $out = $record->summary;
319
  $object_title = $record->get_object_title();
320
+ /* translators: %s: the title of any object, like a Post (e.g. "Hello World") */
321
  $view_all_text = $object_title ? sprintf( esc_html__( 'View all activity for "%s"', 'stream' ), esc_attr( $object_title ) ) : esc_html__( 'View all activity for this object', 'stream' );
322
 
323
  if ( $record->object_id ) {
432
  echo wp_kses( $out, $allowed_tags );
433
  }
434
 
435
+ /**
436
+ * Returns the actions links for the provided record. (Eg. Edit, View)
437
+ *
438
+ * @param Record $record Record.
439
+ * @return string
440
+ */
441
  public function get_action_links( $record ) {
442
  $out = '';
443
 
491
  return $out;
492
  }
493
 
494
+ /**
495
+ * Returns a link to be display in the table.
496
+ *
497
+ * @param string $display Text to be displayed in link.
498
+ * @param string|array $key Query string variable(s).
499
+ * @param string $value Single query string value.
500
+ * @param string $title Tooltip value.
501
+ * @return string
502
+ */
503
  public function column_link( $display, $key, $value = null, $title = null ) {
504
  $url = add_query_arg(
505
  array(
524
  );
525
  }
526
 
527
+ /**
528
+ * Returns the label for a connector term.
529
+ *
530
+ * @param string $term Connector label type.
531
+ * @param string $type Connector term.
532
+ * @return string
533
+ */
534
  public function get_term_title( $term, $type ) {
535
  if ( ! isset( $this->plugin->connectors->term_labels[ 'stream_' . $type ][ $term ] ) ) {
536
  return $term;
546
  * results of existing records. All items that do not exist in records
547
  * get assigned a disabled value of "true".
548
  *
549
+ * @param string $column List table column name.
550
  *
551
  * @return array Options to be displayed in search filters
552
  */
555
  if ( 'user_id' === $column ) {
556
  $all_records = array();
557
 
558
+ // If the number of users exceeds the max users constant value then return an empty array and use AJAX instead.
559
  $user_count = count_users();
560
  $total_users = $user_count['total_users'];
561
 
628
  }
629
  }
630
 
631
+ // Remove WP-CLI pseudo user if no records with user=0 exist.
632
  if ( isset( $disabled_records[0] ) ) {
633
  unset( $disabled_records[0] );
634
  }
647
  uasort( $active_records, $sort );
648
  uasort( $disabled_records, $sort );
649
 
650
+ // Not using array_merge() in order to preserve the array index for the users dropdown which uses the user_id as the key.
651
  $all_records = $active_records + $disabled_records;
652
 
653
  return $all_records;
654
  }
655
 
656
+ /**
657
+ * Returns list filters.
658
+ *
659
+ * @return array
660
+ */
661
  public function get_filters() {
662
  $filters = array();
663
 
698
  return apply_filters( 'wp_stream_list_table_filters', $filters );
699
  }
700
 
701
+ /**
702
+ * Returns table filters form.
703
+ *
704
+ * @return string
705
+ */
706
  public function filters_form() {
707
  $filters = $this->get_filters();
708
 
724
  $filters_string .= $this->filter_date( $data['items'] );
725
  } else {
726
  if ( 'context' === $name ) {
727
+ // Add Connectors as parents, and apply the Contexts as children.
728
  $connectors = $this->assemble_records( 'connector' );
729
  $context_items = array();
730
 
740
  if ( isset( $context_items[ $connector ]['children'] ) ) {
741
  $labels = wp_list_pluck( $context_items[ $connector ]['children'], 'label' );
742
 
743
+ // Sort child items by label.
744
  array_multisort( $labels, SORT_ASC, $context_items[ $connector ]['children'] );
745
  }
746
  }
755
 
756
  $labels = wp_list_pluck( $data['items'], 'label' );
757
 
758
+ // Sort top-level items by label.
759
  array_multisort( $labels, SORT_ASC, $data['items'] );
760
 
761
+ // Output a hidden input to handle the connector value.
762
  $filters_string .= sprintf(
763
  '<input type="hidden" name="connector" class="record-filter-connector" value="%s" />',
764
  esc_attr( wp_stream_filter_input( INPUT_GET, 'connector' ) )
771
 
772
  $filters_string .= sprintf( '<input type="submit" id="record-query-submit" class="button" value="%s" />', __( 'Filter', 'stream' ) );
773
 
774
+ // Parse all query vars into an array.
775
  $query_vars = array();
776
 
777
  if ( isset( $_SERVER['QUERY_STRING'] ) ) {
778
  parse_str( urldecode( $_SERVER['QUERY_STRING'] ), $query_vars );
779
  }
780
 
781
+ // Ignore certain query vars and query vars that are empty.
782
  foreach ( $query_vars as $query_var => $value ) {
783
  if ( '' === $value || 'page' === $query_var || 'paged' === $query_var ) {
784
  unset( $query_vars[ $query_var ] );
792
  self_admin_url( $this->plugin->admin->admin_parent_page )
793
  );
794
 
795
+ // Display reset action if records are being filtered.
796
  if ( ! empty( $query_vars ) ) {
797
  $filters_string .= sprintf( '<a href="%s" id="record-query-reset"><span class="dashicons dashicons-dismiss"></span> <span class="record-query-reset-text">%s</span></a>', esc_url( $url ), __( 'Reset filters', 'stream' ) );
798
  }
799
 
800
+ return sprintf( '<div class="alignleft actions">%s</div>', $filters_string ); // xss ok.
801
  }
802
 
803
+ /**
804
+ * Returns HTML string of filterable select control with filtered items.
805
+ *
806
+ * @param string $name Search input.
807
+ * @param string $title Name of the control.
808
+ * @param array $items Items to be filtered.
809
+ * @param boolean $ajax Whether is an ajax request or not.
810
+ * @return string
811
+ */
812
  public function filter_select( $name, $title, $items, $ajax = false ) {
813
  $options = array( '<option value=""></option>' );
814
  $selected = wp_stream_filter_input( INPUT_GET, $name );
846
  $out = sprintf(
847
  '<select name="%s" class="chosen-select" data-placeholder="%s">%s</select>',
848
  esc_attr( $name ),
849
+ /* translators: %s: the title of the dropdown menu (e.g. "users") */
850
  sprintf( esc_attr__( 'Show all %s', 'stream' ), $title ),
851
  implode( '', $options )
852
  );
854
  return $out;
855
  }
856
 
857
+ /**
858
+ * Return HTML string of a filterable select option.
859
+ *
860
+ * @param array $args Option attributes.
861
+ * @return string
862
+ */
863
  public function filter_option( $args ) {
864
  $defaults = array(
865
  'value' => null,
886
  );
887
  }
888
 
889
+ /**
890
+ * Return HTML string of a filter search box.
891
+ *
892
+ * @return string
893
+ */
894
  public function filter_search() {
895
  $search = null;
896
+ if ( isset( $_GET['search'] ) ) { // phpcs:ignore WordPress.Security.NonceVerification.Recommended
897
+ $search = sanitize_key( wp_unslash( $_GET['search'] ) ); // phpcs:ignore WordPress.Security.NonceVerification.Recommended
898
  }
899
  $out = sprintf(
900
  '<p class="search-box">
909
  return $out;
910
  }
911
 
912
+ /**
913
+ * Return HTML string of a filter select box based upon date.
914
+ *
915
+ * @param array $items Records.
916
+ * @return string
917
+ */
918
  public function filter_date( $items ) {
919
  wp_enqueue_style( 'jquery-ui' );
920
  wp_enqueue_style( 'wp-stream-datepicker' );
1012
  return ob_get_clean();
1013
  }
1014
 
1015
+ /**
1016
+ * Renders record filter forms.
1017
+ */
1018
  public function display() {
1019
  $url = self_admin_url( $this->plugin->admin->admin_parent_page );
1020
 
1021
  echo '<form method="get" action="' . esc_url( $url ) . '" id="record-filter-form">';
1022
+ echo $this->filter_search(); // xss ok.
1023
  parent::display();
1024
  echo '</form>';
1025
 
1026
  echo '<form method="get" action="' . esc_url( $url ) . '" id="record-actions-form">';
1027
+ echo $this->record_actions_form(); // xss ok.
1028
  echo '</form>';
1029
  }
1030
 
1031
+ /**
1032
+ * Renders a single record
1033
+ *
1034
+ * @param array $item Record data.
1035
+ */
1036
  public function single_row( $item ) {
1037
  $classes = apply_filters( 'wp_stream_record_classes', array(), $item );
1038
  $class_string = '';
1040
  $class_string = ' class="' . esc_attr( join( ' ', $classes ) ) . '"';
1041
  }
1042
 
1043
+ echo sprintf( '<tr%s>', $class_string ); // xss ok.
1044
  $this->single_row_columns( $item );
1045
  echo '</tr>';
1046
  }
1047
 
1048
+ /**
1049
+ * Renders table navigation controls
1050
+ *
1051
+ * @param string $which Location controls.
1052
+ */
1053
  public function display_tablenav( $which ) {
1054
  if ( 'top' === $which ) :
1055
  ?>
1078
  endif;
1079
  }
1080
 
1081
+ /**
1082
+ * Sets the screen options.
1083
+ *
1084
+ * @param string $dummy Unused.
1085
+ * @param string $option Screen option name.
1086
+ * @param string $value Screen option value.
1087
+ * @return string
1088
+ */
1089
  public function set_screen_option( $dummy, $option, $value ) {
1090
  if ( 'edit_stream_per_page' === $option ) {
1091
  return $value;
1094
  }
1095
  }
1096
 
1097
+ /**
1098
+ * Sets the live update options.
1099
+ *
1100
+ * @param string $dummy Unused.
1101
+ * @param string $option Screen option name.
1102
+ * @param string $value Screen option value.
1103
+ * @return string
1104
+ */
1105
  public function set_live_update_option( $dummy, $option, $value ) {
1106
  unset( $value );
1107
 
1121
  return $dummy;
1122
  }
1123
 
1124
+ /**
1125
+ * Return HTML string of the "Live updates" screen option.
1126
+ *
1127
+ * @param string $status Unused.
1128
+ * @param array $args Unused.
1129
+ * @return string
1130
+ */
1131
  public function screen_controls( $status, $args ) {
1132
  unset( $status );
1133
  unset( $args );
1170
  /**
1171
  * This function is use to map List table column name with excluded setting keys
1172
  *
1173
+ * @param string $column List table column name.
1174
  *
1175
  * @return string setting name for that column
1176
  */
1201
  /**
1202
  * Get users as dropdown items
1203
  *
1204
+ * @param array $users Users.
1205
  *
1206
  * @return array
1207
  */
classes/class-live-update.php CHANGED
@@ -1,9 +1,18 @@
1
  <?php
 
 
 
 
 
 
2
  namespace WP_Stream;
3
 
 
 
 
4
  class Live_Update {
5
  /**
6
- * Hold Plugin class
7
  *
8
  * @var Plugin
9
  */
@@ -26,15 +35,15 @@ class Live_Update {
26
  /**
27
  * Class constructor.
28
  *
29
- * @param Plugin $plugin The main Plugin class.
30
  */
31
  public function __construct( $plugin ) {
32
  $this->plugin = $plugin;
33
 
34
- // Heartbeat live update
35
  add_filter( 'heartbeat_received', array( $this, 'heartbeat_received' ), 10, 2 );
36
 
37
- // Enable / Disable live update per user
38
  add_action( 'wp_ajax_stream_enable_live_update', array( $this, 'enable_live_update' ) );
39
  }
40
 
@@ -87,8 +96,8 @@ class Live_Update {
87
  * @uses gather_updated_items
88
  * @uses generate_row
89
  *
90
- * @param array $response Response to heartbeat
91
- * @param array $data Data from heartbeat
92
  *
93
  * @return array Data sent to heartbeat
94
  */
@@ -106,7 +115,7 @@ class Live_Update {
106
  $query = array();
107
  }
108
 
109
- // Decode the query
110
  $query = json_decode( wp_kses_stripslashes( $query ) );
111
 
112
  $updated_items = $this->gather_updated_items( $last_time, (array) $query );
@@ -129,8 +138,8 @@ class Live_Update {
129
  /**
130
  * Sends Updated Actions to the List Table View
131
  *
132
- * @param int $last_time Timestamp of last update
133
- * @param array $args Query args
134
  *
135
  * @return array Array of recently updated items
136
  */
@@ -163,20 +172,20 @@ class Live_Update {
163
  *
164
  * @action heartbeat_recieved
165
  *
166
- * @param array $response Response to be sent to heartbeat tick
167
- * @param array $data Data from heartbeat send
168
  *
169
  * @return array Data sent to heartbeat tick
170
  */
171
  public function heartbeat_received( $response, $data ) {
172
- // Only fire when Stream is requesting a live update
173
  if ( ! isset( $data['wp-stream-heartbeat'] ) ) {
174
  return $response;
175
  }
176
 
177
  $enable_stream_update = ( 'off' !== $this->plugin->admin->get_user_meta( get_current_user_id(), $this->user_meta_key ) );
178
 
179
- // Register list table
180
  $this->list_table = new List_Table(
181
  $this->plugin,
182
  array(
@@ -190,7 +199,7 @@ class Live_Update {
190
 
191
  if ( isset( $data['wp-stream-heartbeat'] ) && isset( $total_items ) ) {
192
  $response['total_items'] = $total_items;
193
- // translators: Placeholder refers to a number of items (e.g. "42")
194
  $response['total_items_i18n'] = sprintf( _n( '%d item', '%d items', $total_items ), number_format_i18n( $total_items ) );
195
  }
196
 
1
  <?php
2
+ /**
3
+ * Processes update calls from the Stream Records page.
4
+ *
5
+ * @package WP_Stream
6
+ */
7
+
8
  namespace WP_Stream;
9
 
10
+ /**
11
+ * Class - Live_Update
12
+ */
13
  class Live_Update {
14
  /**
15
+ * Holds instance of plugin object
16
  *
17
  * @var Plugin
18
  */
35
  /**
36
  * Class constructor.
37
  *
38
+ * @param Plugin $plugin Instance of plugin object.
39
  */
40
  public function __construct( $plugin ) {
41
  $this->plugin = $plugin;
42
 
43
+ // Heartbeat live update.
44
  add_filter( 'heartbeat_received', array( $this, 'heartbeat_received' ), 10, 2 );
45
 
46
+ // Enable / Disable live update per user.
47
  add_action( 'wp_ajax_stream_enable_live_update', array( $this, 'enable_live_update' ) );
48
  }
49
 
96
  * @uses gather_updated_items
97
  * @uses generate_row
98
  *
99
+ * @param array $response Response to heartbeat.
100
+ * @param array $data Data from heartbeat.
101
  *
102
  * @return array Data sent to heartbeat
103
  */
115
  $query = array();
116
  }
117
 
118
+ // Decode the query.
119
  $query = json_decode( wp_kses_stripslashes( $query ) );
120
 
121
  $updated_items = $this->gather_updated_items( $last_time, (array) $query );
138
  /**
139
  * Sends Updated Actions to the List Table View
140
  *
141
+ * @param int $last_time Timestamp of last update.
142
+ * @param array $args Query args.
143
  *
144
  * @return array Array of recently updated items
145
  */
172
  *
173
  * @action heartbeat_recieved
174
  *
175
+ * @param array $response Response to be sent to heartbeat tick.
176
+ * @param array $data Data from heartbeat send.
177
  *
178
  * @return array Data sent to heartbeat tick
179
  */
180
  public function heartbeat_received( $response, $data ) {
181
+ // Only fire when Stream is requesting a live update.
182
  if ( ! isset( $data['wp-stream-heartbeat'] ) ) {
183
  return $response;
184
  }
185
 
186
  $enable_stream_update = ( 'off' !== $this->plugin->admin->get_user_meta( get_current_user_id(), $this->user_meta_key ) );
187
 
188
+ // Register list table.
189
  $this->list_table = new List_Table(
190
  $this->plugin,
191
  array(
199
 
200
  if ( isset( $data['wp-stream-heartbeat'] ) && isset( $total_items ) ) {
201
  $response['total_items'] = $total_items;
202
+ /* translators: %d: number of items (e.g. "42") */
203
  $response['total_items_i18n'] = sprintf( _n( '%d item', '%d items', $total_items ), number_format_i18n( $total_items ) );
204
  }
205
 
classes/class-log.php CHANGED
@@ -1,11 +1,19 @@
1
  <?php
 
 
 
 
 
2
 
3
  namespace WP_Stream;
4
 
 
 
 
5
  class Log {
6
 
7
  /**
8
- * Hold Plugin class
9
  *
10
  * @var Plugin
11
  */
@@ -29,7 +37,7 @@ class Log {
29
  /**
30
  * Class constructor.
31
  *
32
- * @param Plugin $plugin The main Plugin class.
33
  */
34
  public function __construct( $plugin ) {
35
  $this->plugin = $plugin;
@@ -146,7 +154,7 @@ class Log {
146
  $result = $this->plugin->db->insert( $recordarr );
147
 
148
  // This is helpful in development environments:
149
- // error_log( $this->debug_backtrace( $recordarr ) );
150
 
151
  return $result;
152
  }
1
  <?php
2
+ /**
3
+ * Handles top-level record keeping functionality.
4
+ *
5
+ * @package WP_Stream
6
+ */
7
 
8
  namespace WP_Stream;
9
 
10
+ /**
11
+ * Class - Log
12
+ */
13
  class Log {
14
 
15
  /**
16
+ * Holds Instance of plugin object
17
  *
18
  * @var Plugin
19
  */
37
  /**
38
  * Class constructor.
39
  *
40
+ * @param Plugin $plugin Instance of plugin object.
41
  */
42
  public function __construct( $plugin ) {
43
  $this->plugin = $plugin;
154
  $result = $this->plugin->db->insert( $recordarr );
155
 
156
  // This is helpful in development environments:
157
+ // error_log( $this->debug_backtrace( $recordarr ) );.
158
 
159
  return $result;
160
  }
classes/class-network.php CHANGED
@@ -1,32 +1,57 @@
1
  <?php
 
 
 
 
 
 
 
2
  namespace WP_Stream;
3
 
 
 
 
4
  class Network {
5
  /**
6
- * Hold Plugin class
7
  *
8
  * @var Plugin
9
  */
10
  public $plugin;
11
 
 
 
 
 
 
12
  public $network_settings_page_slug = 'wp_stream_network_settings';
13
 
 
 
 
 
 
14
  public $default_settings_page_slug = 'wp_stream_default_settings';
15
 
 
 
 
 
 
16
  public function __construct( $plugin ) {
17
  $this->plugin = $plugin;
18
 
19
- // Always add default site_id/blog_id params when multisite
20
  if ( is_multisite() ) {
21
  add_filter( 'wp_stream_query_args', array( $this, 'network_query_args' ) );
22
  }
23
 
24
- // Bail early if not network-activated
25
  if ( ! $this->is_network_activated() ) {
26
  return;
27
  }
28
 
29
- // Actions
30
  add_action( 'init', array( $this, 'ajax_network_admin' ) );
31
  add_action( 'network_admin_menu', array( $this->plugin->admin, 'register_menu' ) );
32
  add_action( 'network_admin_menu', array( $this, 'admin_menu_screens' ) );
@@ -36,7 +61,7 @@ class Network {
36
  add_action( 'wpmuadminedit', array( $this, 'network_options_action' ) );
37
  add_action( 'update_site_option_' . $this->plugin->settings->network_options_key, array( $this, 'updated_option_ttl_remove_records' ), 10, 3 );
38
 
39
- // Filters
40
  add_filter( 'wp_stream_blog_id_logged', array( $this, 'blog_id_logged' ) );
41
  add_filter( 'wp_stream_admin_page_title', array( $this, 'network_admin_page_title' ) );
42
  add_filter( 'wp_stream_list_table_screen_id', array( $this, 'list_table_screen_id' ) );
@@ -101,7 +126,7 @@ class Network {
101
  *
102
  * @action admin_bar_menu
103
  *
104
- * @param object $admin_bar
105
  *
106
  * @return void
107
  */
@@ -128,7 +153,7 @@ class Network {
128
  }
129
 
130
  /**
131
- * Add Network Settings and Default Settings menu items
132
  *
133
  * @return array
134
  */
@@ -153,9 +178,9 @@ class Network {
153
  /**
154
  * Remove records when records TTL is shortened
155
  *
156
- * @param string $option_key
157
- * @param array $old_value
158
- * @param array $new_value
159
  *
160
  * @action update_option_wp_stream
161
  * @return void
@@ -168,7 +193,7 @@ class Network {
168
  /**
169
  * Adjust the action of the settings form when in the Network Admin
170
  *
171
- * @param $action
172
  *
173
  * @return string
174
  */
@@ -189,7 +214,7 @@ class Network {
189
  /**
190
  * Add a description to each of the Settings pages in the Network Admin
191
  *
192
- * @param $description
193
  *
194
  * @return string
195
  */
@@ -215,7 +240,7 @@ class Network {
215
  /**
216
  * Adjusts the settings fields displayed in various network admin screens
217
  *
218
- * @param $fields
219
  *
220
  * @return mixed
221
  */
@@ -254,7 +279,7 @@ class Network {
254
  )
255
  );
256
 
257
- // Remove settings based on context
258
  if ( $this->plugin->settings->network_options_key === $this->plugin->settings->option_key ) {
259
  $hidden_options = $network_hidden_options;
260
  } else {
@@ -273,7 +298,7 @@ class Network {
273
  }
274
  }
275
 
276
- // Add settings based on context
277
  if ( $this->plugin->settings->network_options_key === $this->plugin->settings->option_key ) {
278
  $new_fields['general']['fields'][] = array(
279
  'name' => 'site_access',
@@ -287,7 +312,7 @@ class Network {
287
  $fields = array_merge_recursive( $new_fields, $fields );
288
  }
289
 
290
- // Remove empty settings sections
291
  foreach ( $fields as $section_key => $section ) {
292
  if ( empty( $section['fields'] ) ) {
293
  unset( $fields[ $section_key ] );
@@ -302,6 +327,8 @@ class Network {
302
  *
303
  * @filter wp_stream_serialized_labels
304
  *
 
 
305
  * @return array Multidimensional array of fields
306
  */
307
  public function get_settings_translations( $labels ) {
@@ -329,11 +356,13 @@ class Network {
329
  $this->default_settings_page_slug,
330
  );
331
 
332
- if ( ! isset( $_GET['action'] ) || ! in_array( $_GET['action'], $allowed_referers, true ) ) { // CSRF okay
 
333
  return;
334
  }
335
 
336
- $options = isset( $_POST['option_page'] ) ? explode( ',', stripslashes( $_POST['option_page'] ) ) : null; // CSRF okay
 
337
 
338
  if ( $options ) {
339
 
@@ -372,7 +401,7 @@ class Network {
372
 
373
  $go_back = add_query_arg( 'settings-updated', 'true', wp_get_referer() );
374
 
375
- wp_redirect( $go_back );
376
 
377
  exit;
378
  }
@@ -382,7 +411,7 @@ class Network {
382
  *
383
  * @filter wp_stream_list_table_filters
384
  *
385
- * @param $filters
386
  *
387
  * @return array
388
  */
@@ -393,7 +422,7 @@ class Network {
393
 
394
  $blogs = array();
395
 
396
- // Display network blog as the first option
397
  $network_blog = $this->get_network_blog();
398
 
399
  $blogs[ $network_blog->blog_id ] = array(
@@ -401,7 +430,7 @@ class Network {
401
  'disabled' => '',
402
  );
403
 
404
- // add all sites
405
  foreach ( wp_stream_get_sites() as $blog ) {
406
  $blog_data = get_blog_details( $blog->blog_id );
407
 
@@ -422,7 +451,7 @@ class Network {
422
  /**
423
  * Add the Site toggle to screen options in network admin
424
  *
425
- * @param $filters
426
  *
427
  * @return array
428
  */
@@ -437,7 +466,7 @@ class Network {
437
  /**
438
  * Add the network suffix to the $screen_id when in the network admin
439
  *
440
- * @param $screen_id
441
  *
442
  * @return string
443
  */
@@ -454,6 +483,8 @@ class Network {
454
  /**
455
  * Set blog_id for network admin activity
456
  *
 
 
457
  * @return int
458
  */
459
  public function blog_id_logged( $blog_id ) {
@@ -465,7 +496,7 @@ class Network {
465
  *
466
  * @filter wp_stream_query_args
467
  *
468
- * @param array $args
469
  *
470
  * @return array
471
  */
@@ -481,13 +512,13 @@ class Network {
481
  *
482
  * @filter wp_stream_admin_page_title
483
  *
484
- * @param string $page_title
485
  *
486
  * @return string
487
  */
488
  public function network_admin_page_title( $page_title ) {
489
  if ( is_network_admin() ) {
490
- // translators: Placeholder refers to a number of sites on the network (e.g. "42")
491
  $site_count = sprintf( _n( '%d site', '%d sites', get_blog_count(), 'stream' ), number_format( get_blog_count() ) );
492
  $page_title = sprintf( '%s (%s)', $page_title, $site_count );
493
  }
@@ -498,7 +529,7 @@ class Network {
498
  /**
499
  * Add the Site column to the network stream records
500
  *
501
- * @param $columns
502
  *
503
  * @return mixed
504
  */
@@ -519,7 +550,7 @@ class Network {
519
  /**
520
  * Prevent the Blogs connector from loading when not in Network Admin
521
  *
522
- * @param $connectors
523
  *
524
  * @return mixed
525
  */
1
  <?php
2
+ /**
3
+ * Manages functionality for the Stream Admin pages on both
4
+ * single and multi-sites.
5
+ *
6
+ * @package WP_Stream
7
+ */
8
+
9
  namespace WP_Stream;
10
 
11
+ /**
12
+ * Class - Network
13
+ */
14
  class Network {
15
  /**
16
+ * Holds instance of plugin object
17
  *
18
  * @var Plugin
19
  */
20
  public $plugin;
21
 
22
+ /**
23
+ * Network page slug
24
+ *
25
+ * @var string
26
+ */
27
  public $network_settings_page_slug = 'wp_stream_network_settings';
28
 
29
+ /**
30
+ * Default setting page slug
31
+ *
32
+ * @var string
33
+ */
34
  public $default_settings_page_slug = 'wp_stream_default_settings';
35
 
36
+ /**
37
+ * Class constructor
38
+ *
39
+ * @param Plugin $plugin Instance of plugin object.
40
+ */
41
  public function __construct( $plugin ) {
42
  $this->plugin = $plugin;
43
 
44
+ // Always add default site_id/blog_id params when multisite.
45
  if ( is_multisite() ) {
46
  add_filter( 'wp_stream_query_args', array( $this, 'network_query_args' ) );
47
  }
48
 
49
+ // Bail early if not network-activated.
50
  if ( ! $this->is_network_activated() ) {
51
  return;
52
  }
53
 
54
+ // Actions.
55
  add_action( 'init', array( $this, 'ajax_network_admin' ) );
56
  add_action( 'network_admin_menu', array( $this->plugin->admin, 'register_menu' ) );
57
  add_action( 'network_admin_menu', array( $this, 'admin_menu_screens' ) );
61
  add_action( 'wpmuadminedit', array( $this, 'network_options_action' ) );
62
  add_action( 'update_site_option_' . $this->plugin->settings->network_options_key, array( $this, 'updated_option_ttl_remove_records' ), 10, 3 );
63
 
64
+ // Filters.
65
  add_filter( 'wp_stream_blog_id_logged', array( $this, 'blog_id_logged' ) );
66
  add_filter( 'wp_stream_admin_page_title', array( $this, 'network_admin_page_title' ) );
67
  add_filter( 'wp_stream_list_table_screen_id', array( $this, 'list_table_screen_id' ) );
126
  *
127
  * @action admin_bar_menu
128
  *
129
+ * @param object $admin_bar Admin bar object.
130
  *
131
  * @return void
132
  */
153
  }
154
 
155
  /**
156
+ * Add Network Settings and Default Settings menu pages
157
  *
158
  * @return array
159
  */
178
  /**
179
  * Remove records when records TTL is shortened
180
  *
181
+ * @param string $option_key Unused.
182
+ * @param array $new_value New value.
183
+ * @param array $old_value Old value.
184
  *
185
  * @action update_option_wp_stream
186
  * @return void
193
  /**
194
  * Adjust the action of the settings form when in the Network Admin
195
  *
196
+ * @param string $action Query string.
197
  *
198
  * @return string
199
  */
214
  /**
215
  * Add a description to each of the Settings pages in the Network Admin
216
  *
217
+ * @param string $description Description of the current page.
218
  *
219
  * @return string
220
  */
240
  /**
241
  * Adjusts the settings fields displayed in various network admin screens
242
  *
243
+ * @param array $fields Page settings fields.
244
  *
245
  * @return mixed
246
  */
279
  )
280
  );
281
 
282
+ // Remove settings based on context.
283
  if ( $this->plugin->settings->network_options_key === $this->plugin->settings->option_key ) {
284
  $hidden_options = $network_hidden_options;
285
  } else {
298
  }
299
  }
300
 
301
+ // Add settings based on context.
302
  if ( $this->plugin->settings->network_options_key === $this->plugin->settings->option_key ) {
303
  $new_fields['general']['fields'][] = array(
304
  'name' => 'site_access',
312
  $fields = array_merge_recursive( $new_fields, $fields );
313
  }
314
 
315
+ // Remove empty settings sections.
316
  foreach ( $fields as $section_key => $section ) {
317
  if ( empty( $section['fields'] ) ) {
318
  unset( $fields[ $section_key ] );
327
  *
328
  * @filter wp_stream_serialized_labels
329
  *
330
+ * @param array $labels Setting labels.
331
+ *
332
  * @return array Multidimensional array of fields
333
  */
334
  public function get_settings_translations( $labels ) {
356
  $this->default_settings_page_slug,
357
  );
358
 
359
+ // @codingStandardsIgnoreLine
360
+ if ( ! isset( $_GET['action'] ) || ! in_array( $_GET['action'], $allowed_referers, true ) ) {
361
  return;
362
  }
363
 
364
+ // @codingStandardsIgnoreLine
365
+ $options = isset( $_POST['option_page'] ) ? explode( ',', stripslashes( $_POST['option_page'] ) ) : null;
366
 
367
  if ( $options ) {
368
 
401
 
402
  $go_back = add_query_arg( 'settings-updated', 'true', wp_get_referer() );
403
 
404
+ wp_safe_redirect( $go_back );
405
 
406
  exit;
407
  }
411
  *
412
  * @filter wp_stream_list_table_filters
413
  *
414
+ * @param array $filters Filters.
415
  *
416
  * @return array
417
  */
422
 
423
  $blogs = array();
424
 
425
+ // Display network blog as the first option.
426
  $network_blog = $this->get_network_blog();
427
 
428
  $blogs[ $network_blog->blog_id ] = array(
430
  'disabled' => '',
431
  );
432
 
433
+ // Add all sites.
434
  foreach ( wp_stream_get_sites() as $blog ) {
435
  $blog_data = get_blog_details( $blog->blog_id );
436
 
451
  /**
452
  * Add the Site toggle to screen options in network admin
453
  *
454
+ * @param array $filters Filters.
455
  *
456
  * @return array
457
  */
466
  /**
467
  * Add the network suffix to the $screen_id when in the network admin
468
  *
469
+ * @param int $screen_id Screen ID.
470
  *
471
  * @return string
472
  */
483
  /**
484
  * Set blog_id for network admin activity
485
  *
486
+ * @param int $blog_id Blog ID.
487
+ *
488
  * @return int
489
  */
490
  public function blog_id_logged( $blog_id ) {
496
  *
497
  * @filter wp_stream_query_args
498
  *
499
+ * @param array $args Site arguments.
500
  *
501
  * @return array
502
  */
512
  *
513
  * @filter wp_stream_admin_page_title
514
  *
515
+ * @param string $page_title Page title.
516
  *
517
  * @return string
518
  */
519
  public function network_admin_page_title( $page_title ) {
520
  if ( is_network_admin() ) {
521
+ /* translators: %d: number of sites on the network (e.g. "42") */
522
  $site_count = sprintf( _n( '%d site', '%d sites', get_blog_count(), 'stream' ), number_format( get_blog_count() ) );
523
  $page_title = sprintf( '%s (%s)', $page_title, $site_count );
524
  }
529
  /**
530
  * Add the Site column to the network stream records
531
  *
532
+ * @param array $columns Columns data.
533
  *
534
  * @return mixed
535
  */
550
  /**
551
  * Prevent the Blogs connector from loading when not in Network Admin
552
  *
553
+ * @param array $connectors Connectors.
554
  *
555
  * @return mixed
556
  */
classes/class-plugin.php CHANGED
@@ -1,6 +1,15 @@
1
  <?php
 
 
 
 
 
 
2
  namespace WP_Stream;
3
 
 
 
 
4
  class Plugin {
5
  /**
6
  * Plugin version number.
@@ -9,7 +18,7 @@ class Plugin {
9
  *
10
  * @const string
11
  */
12
- const VERSION = '3.4.3';
13
 
14
  /**
15
  * WP-CLI command
@@ -19,41 +28,57 @@ class Plugin {
19
  const WP_CLI_COMMAND = 'stream';
20
 
21
  /**
 
 
22
  * @var Admin
23
  */
24
  public $admin;
25
 
26
  /**
 
 
27
  * @var Alerts
28
  */
29
  public $alerts;
30
 
31
  /**
 
 
32
  * @var Alerts_List
33
  */
34
  public $alerts_list;
35
 
36
  /**
 
 
37
  * @var Connectors
38
  */
39
  public $connectors;
40
 
41
  /**
 
 
42
  * @var DB
43
  */
44
  public $db;
45
 
46
  /**
 
 
47
  * @var Log
48
  */
49
  public $log;
50
 
51
  /**
 
 
52
  * @var Settings
53
  */
54
  public $settings;
55
 
56
  /**
 
 
57
  * @var Install
58
  */
59
  public $install;
@@ -81,10 +106,10 @@ class Plugin {
81
 
82
  spl_autoload_register( array( $this, 'autoload' ) );
83
 
84
- // Load helper functions
85
  require_once $this->locations['inc_dir'] . 'functions.php';
86
 
87
- // Load DB helper interface/class
88
  $driver_class = apply_filters( 'wp_stream_db_driver', '\WP_Stream\DB_Driver_WPDB' );
89
  $driver = null;
90
 
@@ -107,22 +132,22 @@ class Plugin {
107
  );
108
  }
109
 
110
- // Load languages
111
  add_action( 'plugins_loaded', array( $this, 'i18n' ) );
112
 
113
- // Load logger class
114
  $this->log = apply_filters( 'wp_stream_log_handler', new Log( $this ) );
115
 
116
- // Load settings and connectors after widgets_init and before the default init priority
117
  add_action( 'init', array( $this, 'init' ), 9 );
118
 
119
- // Add frontend indicator
120
  add_action( 'wp_head', array( $this, 'frontend_indicator' ) );
121
 
122
- // Change DB driver after plugin loaded if any add-ons want to replace
123
  add_action( 'plugins_loaded', array( $this, 'plugins_loaded' ), 20 );
124
 
125
- // Load admin area classes
126
  if ( is_admin() || ( defined( 'WP_STREAM_DEV_DEBUG' ) && WP_STREAM_DEV_DEBUG ) || ( defined( 'WP_CLI' ) && WP_CLI ) ) {
127
  $this->admin = new Admin( $this );
128
  $this->install = $driver->setup_storage( $this );
@@ -130,7 +155,7 @@ class Plugin {
130
  $this->admin = new Admin( $this, $driver );
131
  }
132
 
133
- // Load WP-CLI command
134
  if ( defined( 'WP_CLI' ) && WP_CLI ) {
135
  \WP_CLI::add_command( self::WP_CLI_COMMAND, 'WP_Stream\CLI' );
136
  }
@@ -139,7 +164,7 @@ class Plugin {
139
  /**
140
  * Autoloader for classes
141
  *
142
- * @param string $class
143
  */
144
  public function autoload( $class ) {
145
  if ( ! preg_match( '/^(?P<namespace>.+)\\\\(?P<autoload>[^\\\\]+)$/', $class, $matches ) ) {
@@ -174,7 +199,7 @@ class Plugin {
174
  load_plugin_textdomain( 'stream', false, dirname( $this->locations['plugin'] ) . '/languages/' );
175
  }
176
 
177
- /*
178
  * Load Settings, Notifications, and Connectors
179
  *
180
  * @action init
@@ -196,7 +221,8 @@ class Plugin {
196
  * @return string|void An HTML comment, or nothing if the value is filtered out.
197
  */
198
  public function frontend_indicator() {
199
- $comment = sprintf( 'Stream WordPress user activity plugin v%s', esc_html( $this->get_version() ) ); // Localization not needed
 
200
 
201
  /**
202
  * Filter allows the HTML output of the frontend indicator comment
@@ -207,7 +233,7 @@ class Plugin {
207
  $comment = apply_filters( 'wp_stream_frontend_indicator', $comment );
208
 
209
  if ( ! empty( $comment ) ) {
210
- echo sprintf( "<!-- %s -->\n", esc_html( $comment ) ); // xss ok
211
  }
212
  }
213
 
@@ -215,8 +241,6 @@ class Plugin {
215
  * Version of plugin_dir_url() which works for plugins installed in the plugins directory,
216
  * and for plugins bundled with themes.
217
  *
218
- * @throws \Exception
219
- *
220
  * @return array
221
  */
222
  private function locate_plugin() {
@@ -241,7 +265,7 @@ class Plugin {
241
  * Change plugin database driver in case driver plugin loaded after stream
242
  */
243
  public function plugins_loaded() {
244
- // Load DB helper interface/class
245
  $driver_class = apply_filters( 'wp_stream_db_driver', '\WP_Stream\DB_Driver_WPDB' );
246
 
247
  if ( class_exists( $driver_class ) ) {
@@ -271,8 +295,8 @@ class Plugin {
271
  /**
272
  * Filter allows the network activated detection to be overridden.
273
  *
274
- * @param string $is_network_activated Whether the plugin is network activated
275
- * @param WP_Stream\Plugin $plugin The stream plugin object
276
  */
277
  return apply_filters( 'wp_stream_is_network_activated', $is_network_activated, $this );
278
  }
@@ -283,7 +307,6 @@ class Plugin {
283
  * @return bool
284
  */
285
  public function is_mustuse() {
286
-
287
  $stream_php = trailingslashit( WPMU_PLUGIN_DIR ) . $this->locations['plugin'];
288
 
289
  if ( file_exists( $stream_php ) && class_exists( 'WP_Stream\Plugin' ) ) {
1
  <?php
2
+ /**
3
+ * Initializes plugin
4
+ *
5
+ * @package WP_Stream;
6
+ */
7
+
8
  namespace WP_Stream;
9
 
10
+ /**
11
+ * Class Plugin
12
+ */
13
  class Plugin {
14
  /**
15
  * Plugin version number.
18
  *
19
  * @const string
20
  */
21
+ const VERSION = '3.5.0';
22
 
23
  /**
24
  * WP-CLI command
28
  const WP_CLI_COMMAND = 'stream';
29
 
30
  /**
31
+ * Holds and manages WordPress Admin configurations.
32
+ *
33
  * @var Admin
34
  */
35
  public $admin;
36
 
37
  /**
38
+ * Holds and manages alerts.
39
+ *
40
  * @var Alerts
41
  */
42
  public $alerts;
43
 
44
  /**
45
+ * Holds and manages alerts lists.
46
+ *
47
  * @var Alerts_List
48
  */
49
  public $alerts_list;
50
 
51
  /**
52
+ * Holds and manages connectors
53
+ *
54
  * @var Connectors
55
  */
56
  public $connectors;
57
 
58
  /**
59
+ * Holds and manages DB connections.
60
+ *
61
  * @var DB
62
  */
63
  public $db;
64
 
65
  /**
66
+ * Holds and manages records.
67
+ *
68
  * @var Log
69
  */
70
  public $log;
71
 
72
  /**
73
+ * Stores and manages WordPress settings.
74
+ *
75
  * @var Settings
76
  */
77
  public $settings;
78
 
79
  /**
80
+ * Process DB migrations.
81
+ *
82
  * @var Install
83
  */
84
  public $install;
106
 
107
  spl_autoload_register( array( $this, 'autoload' ) );
108
 
109
+ // Load helper functions.
110
  require_once $this->locations['inc_dir'] . 'functions.php';
111
 
112
+ // Load DB helper interface/class.
113
  $driver_class = apply_filters( 'wp_stream_db_driver', '\WP_Stream\DB_Driver_WPDB' );
114
  $driver = null;
115
 
132
  );
133
  }
134
 
135
+ // Load languages.
136
  add_action( 'plugins_loaded', array( $this, 'i18n' ) );
137
 
138
+ // Load logger class.
139
  $this->log = apply_filters( 'wp_stream_log_handler', new Log( $this ) );
140
 
141
+ // Load settings and connectors after widgets_init and before the default init priority.
142
  add_action( 'init', array( $this, 'init' ), 9 );
143
 
144
+ // Add frontend indicator.
145
  add_action( 'wp_head', array( $this, 'frontend_indicator' ) );
146
 
147
+ // Change DB driver after plugin loaded if any add-ons want to replace.
148
  add_action( 'plugins_loaded', array( $this, 'plugins_loaded' ), 20 );
149
 
150
+ // Load admin area classes.
151
  if ( is_admin() || ( defined( 'WP_STREAM_DEV_DEBUG' ) && WP_STREAM_DEV_DEBUG ) || ( defined( 'WP_CLI' ) && WP_CLI ) ) {
152
  $this->admin = new Admin( $this );
153
  $this->install = $driver->setup_storage( $this );
155
  $this->admin = new Admin( $this, $driver );
156
  }
157
 
158
+ // Load WP-CLI command.
159
  if ( defined( 'WP_CLI' ) && WP_CLI ) {
160
  \WP_CLI::add_command( self::WP_CLI_COMMAND, 'WP_Stream\CLI' );
161
  }
164
  /**
165
  * Autoloader for classes
166
  *
167
+ * @param string $class Fully qualified classname to be loaded.
168
  */
169
  public function autoload( $class ) {
170
  if ( ! preg_match( '/^(?P<namespace>.+)\\\\(?P<autoload>[^\\\\]+)$/', $class, $matches ) ) {
199
  load_plugin_textdomain( 'stream', false, dirname( $this->locations['plugin'] ) . '/languages/' );
200
  }
201
 
202
+ /**
203
  * Load Settings, Notifications, and Connectors
204
  *
205
  * @action init
221
  * @return string|void An HTML comment, or nothing if the value is filtered out.
222
  */
223
  public function frontend_indicator() {
224
+ /* translators: Localization not needed */
225
+ $comment = sprintf( 'Stream WordPress user activity plugin v%s', esc_html( $this->get_version() ) );
226
 
227
  /**
228
  * Filter allows the HTML output of the frontend indicator comment
233
  $comment = apply_filters( 'wp_stream_frontend_indicator', $comment );
234
 
235
  if ( ! empty( $comment ) ) {
236
+ echo sprintf( "<!-- %s -->\n", esc_html( $comment ) ); // xss ok.
237
  }
238
  }
239
 
241
  * Version of plugin_dir_url() which works for plugins installed in the plugins directory,
242
  * and for plugins bundled with themes.
243
  *
 
 
244
  * @return array
245
  */
246
  private function locate_plugin() {
265
  * Change plugin database driver in case driver plugin loaded after stream
266
  */
267
  public function plugins_loaded() {
268
+ // Load DB helper interface/class.
269
  $driver_class = apply_filters( 'wp_stream_db_driver', '\WP_Stream\DB_Driver_WPDB' );
270
 
271
  if ( class_exists( $driver_class ) ) {
295
  /**
296
  * Filter allows the network activated detection to be overridden.
297
  *
298
+ * @param string $is_network_activated Whether the plugin is network activated.
299
+ * @param WP_Stream\Plugin $plugin The stream plugin object.
300
  */
301
  return apply_filters( 'wp_stream_is_network_activated', $is_network_activated, $this );
302
  }
307
  * @return bool
308
  */
309
  public function is_mustuse() {
 
310
  $stream_php = trailingslashit( WPMU_PLUGIN_DIR ) . $this->locations['plugin'];
311
 
312
  if ( file_exists( $stream_php ) && class_exists( 'WP_Stream\Plugin' ) ) {
classes/class-preview-list-table.php CHANGED
@@ -1,7 +1,15 @@
1
  <?php
 
 
 
 
 
2
 
3
  namespace WP_Stream;
4
 
 
 
 
5
  class Preview_List_Table extends List_Table {
6
 
7
  /**
1
  <?php
2
+ /**
3
+ * Displays a list of provided records in a HTML Table
4
+ *
5
+ * @package WP_Stream
6
+ */
7
 
8
  namespace WP_Stream;
9
 
10
+ /**
11
+ * Class - Preview_List_Table
12
+ */
13
  class Preview_List_Table extends List_Table {
14
 
15
  /**
classes/class-query.php CHANGED
@@ -1,6 +1,15 @@
1
  <?php
 
 
 
 
 
 
2
  namespace WP_Stream;
3
 
 
 
 
4
  class Query {
5
  /**
6
  * Hold the number of records found
@@ -12,7 +21,7 @@ class Query {
12
  /**
13
  * Query records
14
  *
15
- * @param array Query args
16
  *
17
  * @return array Stream Records
18
  */
@@ -48,7 +57,7 @@ class Query {
48
  if ( ! empty( $args['search'] ) ) {
49
  $field = ! empty( $args['search_field'] ) ? $args['search_field'] : 'summary';
50
 
51
- // Sanitize field
52
  $allowed_fields = array( 'ID', 'site_id', 'blog_id', 'object_id', 'user_id', 'user_role', 'created', 'summary', 'connector', 'context', 'action', 'ip' );
53
  if ( in_array( $field, $allowed_fields, true ) ) {
54
  $where .= $wpdb->prepare( " AND $wpdb->stream.{$field} LIKE %s", "%{$args['search']}%" ); // @codingStandardsIgnoreLine can't prepare column name
@@ -80,22 +89,22 @@ class Query {
80
  }
81
 
82
  if ( ! empty( $args['date_from'] ) ) {
83
- $date = get_gmt_from_date( date( 'Y-m-d H:i:s', strtotime( $args['date_from'] . ' 00:00:00' ) ) );
84
  $where .= $wpdb->prepare( " AND DATE($wpdb->stream.created) >= %s", $date );
85
  }
86
 
87
  if ( ! empty( $args['date_to'] ) ) {
88
- $date = get_gmt_from_date( date( 'Y-m-d H:i:s', strtotime( $args['date_to'] . ' 23:59:59' ) ) );
89
  $where .= $wpdb->prepare( " AND DATE($wpdb->stream.created) <= %s", $date );
90
  }
91
 
92
  if ( ! empty( $args['date_after'] ) ) {
93
- $date = get_gmt_from_date( date( 'Y-m-d H:i:s', strtotime( $args['date_after'] ) ) );
94
  $where .= $wpdb->prepare( " AND DATE($wpdb->stream.created) > %s", $date );
95
  }
96
 
97
  if ( ! empty( $args['date_before'] ) ) {
98
- $date = get_gmt_from_date( date( 'Y-m-d H:i:s', strtotime( $args['date_before'] ) ) );
99
  $where .= $wpdb->prepare( " AND DATE($wpdb->stream.created) < %s", $date );
100
  }
101
 
@@ -194,7 +203,7 @@ class Query {
194
 
195
  if ( ! empty( $fields ) ) {
196
  foreach ( $fields as $field ) {
197
- // We'll query the meta table later
198
  if ( 'meta' === $field ) {
199
  continue;
200
  }
1
  <?php
2
+ /**
3
+ * Queries the database for stream records.
4
+ *
5
+ * @package WP_Stream
6
+ */
7
+
8
  namespace WP_Stream;
9
 
10
+ /**
11
+ * Class - Query
12
+ */
13
  class Query {
14
  /**
15
  * Hold the number of records found
21
  /**
22
  * Query records
23
  *
24
+ * @param array $args Arguments to filter the records by.
25
  *
26
  * @return array Stream Records
27
  */
57
  if ( ! empty( $args['search'] ) ) {
58
  $field = ! empty( $args['search_field'] ) ? $args['search_field'] : 'summary';
59
 
60
+ // Sanitize field.
61
  $allowed_fields = array( 'ID', 'site_id', 'blog_id', 'object_id', 'user_id', 'user_role', 'created', 'summary', 'connector', 'context', 'action', 'ip' );
62
  if ( in_array( $field, $allowed_fields, true ) ) {
63
  $where .= $wpdb->prepare( " AND $wpdb->stream.{$field} LIKE %s", "%{$args['search']}%" ); // @codingStandardsIgnoreLine can't prepare column name
89
  }
90
 
91
  if ( ! empty( $args['date_from'] ) ) {
92
+ $date = get_gmt_from_date( gmdate( 'Y-m-d H:i:s', strtotime( $args['date_from'] . ' 00:00:00' ) ) );
93
  $where .= $wpdb->prepare( " AND DATE($wpdb->stream.created) >= %s", $date );
94
  }
95
 
96
  if ( ! empty( $args['date_to'] ) ) {
97
+ $date = get_gmt_from_date( gmdate( 'Y-m-d H:i:s', strtotime( $args['date_to'] . ' 23:59:59' ) ) );
98
  $where .= $wpdb->prepare( " AND DATE($wpdb->stream.created) <= %s", $date );
99
  }
100
 
101
  if ( ! empty( $args['date_after'] ) ) {
102
+ $date = get_gmt_from_date( gmdate( 'Y-m-d H:i:s', strtotime( $args['date_after'] ) ) );
103
  $where .= $wpdb->prepare( " AND DATE($wpdb->stream.created) > %s", $date );
104
  }
105
 
106
  if ( ! empty( $args['date_before'] ) ) {
107
+ $date = get_gmt_from_date( gmdate( 'Y-m-d H:i:s', strtotime( $args['date_before'] ) ) );
108
  $where .= $wpdb->prepare( " AND DATE($wpdb->stream.created) < %s", $date );
109
  }
110
 
203
 
204
  if ( ! empty( $fields ) ) {
205
  foreach ( $fields as $field ) {
206
+ // We'll query the meta table later.
207
  if ( 'meta' === $field ) {
208
  continue;
209
  }
classes/class-record.php CHANGED
@@ -1,22 +1,119 @@
1
  <?php
 
 
 
 
 
 
2
  namespace WP_Stream;
3
 
 
 
 
4
  class Record {
 
 
 
 
 
5
  public $ID;
 
 
 
 
 
 
6
  public $created;
 
 
 
 
 
 
7
  public $site_id;
 
 
 
 
 
 
8
  public $blog_id;
 
 
 
 
 
 
9
  public $object_id;
 
 
 
 
 
 
10
  public $user_id;
 
 
 
 
 
 
11
  public $user_role;
 
 
 
 
 
 
12
  public $user_meta;
 
 
 
 
 
 
13
  public $summary;
 
 
 
 
 
 
14
  public $connector;
 
 
 
 
 
 
15
  public $context;
 
 
 
 
 
 
16
  public $action;
 
 
 
 
 
 
17
  public $ip;
 
 
 
 
 
 
18
  public $meta;
19
 
 
 
 
 
 
20
  public function __construct( $item ) {
21
  $this->ID = isset( $item->ID ) ? $item->ID : null;
22
  $this->created = isset( $item->created ) ? $item->created : null;
@@ -38,6 +135,11 @@ class Record {
38
  }
39
  }
40
 
 
 
 
 
 
41
  public function save() {
42
  if ( ! $this->validate() ) {
43
  return new \WP_Error( 'validation-error', esc_html__( 'Could not validate record data.', 'stream' ) );
@@ -46,6 +148,11 @@ class Record {
46
  return wp_stream_get_instance()->db->insert( (array) $this );
47
  }
48
 
 
 
 
 
 
49
  public function populate( array $raw ) {
50
  $keys = get_class_vars( $this );
51
  $data = array_intersect_key( $raw, $keys );
@@ -54,6 +161,13 @@ class Record {
54
  }
55
  }
56
 
 
 
 
 
 
 
 
57
  public function validate() {
58
  return true;
59
  }
@@ -61,8 +175,8 @@ class Record {
61
  /**
62
  * Query record meta
63
  *
64
- * @param string $meta_key (optional)
65
- * @param bool $single (optional)
66
  *
67
  * @return array
68
  */
@@ -73,9 +187,9 @@ class Record {
73
  /**
74
  * Update record meta
75
  *
76
- * @param string $meta_key
77
- * @param mixed $meta_value
78
- * @param mixed $prev_value (optional)
79
  *
80
  * @return bool
81
  */
@@ -86,8 +200,7 @@ class Record {
86
  /**
87
  * Determine the title of an object that a record is for.
88
  *
89
- * @param object Record object
90
- * @return mixed The title of the object as a string, otherwise false
91
  */
92
  public function get_object_title() {
93
  if ( ! isset( $this->object_id ) || empty( $this->object_id ) ) {
1
  <?php
2
+ /**
3
+ * Manages the state of a single record
4
+ *
5
+ * @package WP_Stream
6
+ */
7
+
8
  namespace WP_Stream;
9
 
10
+ /**
11
+ * Class - Record
12
+ */
13
  class Record {
14
+ /**
15
+ * Record ID
16
+ *
17
+ * @var int
18
+ */
19
  public $ID;
20
+
21
+ /**
22
+ * Date record created
23
+ *
24
+ * @var string
25
+ */
26
  public $created;
27
+
28
+ /**
29
+ * Site ID of the site where the record was created
30
+ *
31
+ * @var int
32
+ */
33
  public $site_id;
34
+
35
+ /**
36
+ * Blog ID of the site where the record was created
37
+ *
38
+ * @var int
39
+ */
40
  public $blog_id;
41
+
42
+ /**
43
+ * Record Object ID
44
+ *
45
+ * @var int
46
+ */
47
  public $object_id;
48
+
49
+ /**
50
+ * User ID of the record creator
51
+ *
52
+ * @var int
53
+ */
54
  public $user_id;
55
+
56
+ /**
57
+ * User role of the record creator
58
+ *
59
+ * @var string
60
+ */
61
  public $user_role;
62
+
63
+ /**
64
+ * Record user meta data.
65
+ *
66
+ * @var string
67
+ */
68
  public $user_meta;
69
+
70
+ /**
71
+ * Record summary
72
+ *
73
+ * @var string
74
+ */
75
  public $summary;
76
+
77
+ /**
78
+ * Record connector
79
+ *
80
+ * @var string
81
+ */
82
  public $connector;
83
+
84
+ /**
85
+ * Context record was made in.
86
+ *
87
+ * @var string
88
+ */
89
  public $context;
90
+
91
+ /**
92
+ * Record action
93
+ *
94
+ * @var string
95
+ */
96
  public $action;
97
+
98
+ /**
99
+ * IP of event requestee
100
+ *
101
+ * @var string
102
+ */
103
  public $ip;
104
+
105
+ /**
106
+ * Record meta data
107
+ *
108
+ * @var array
109
+ */
110
  public $meta;
111
 
112
+ /**
113
+ * Class constructor
114
+ *
115
+ * @param object $item Record data object.
116
+ */
117
  public function __construct( $item ) {
118
  $this->ID = isset( $item->ID ) ? $item->ID : null;
119
  $this->created = isset( $item->created ) ? $item->created : null;
135
  }
136
  }
137
 
138
+ /**
139
+ * Save record.
140
+ *
141
+ * @return int|WP_Error
142
+ */
143
  public function save() {
144
  if ( ! $this->validate() ) {
145
  return new \WP_Error( 'validation-error', esc_html__( 'Could not validate record data.', 'stream' ) );
148
  return wp_stream_get_instance()->db->insert( (array) $this );
149
  }
150
 
151
+ /**
152
+ * Populate "$this" object with provided data.
153
+ *
154
+ * @param array $raw Data to be used to populate $this object.
155
+ */
156
  public function populate( array $raw ) {
157
  $keys = get_class_vars( $this );
158
  $data = array_intersect_key( $raw, $keys );
161
  }
162
  }
163
 
164
+ /**
165
+ * Validates this record
166
+ *
167
+ * @todo Add actual validation measures.
168
+ *
169
+ * @return bool
170
+ */
171
  public function validate() {
172
  return true;
173
  }
175
  /**
176
  * Query record meta
177
  *
178
+ * @param string $meta_key Meta key (optional).
179
+ * @param bool $single Return only first found (optional).
180
  *
181
  * @return array
182
  */
187
  /**
188
  * Update record meta
189
  *
190
+ * @param string $meta_key Meta key.
191
+ * @param mixed $meta_value New meta value.
192
+ * @param mixed $prev_value Old meta value (optional).
193
  *
194
  * @return bool
195
  */
200
  /**
201
  * Determine the title of an object that a record is for.
202
  *
203
+ * @return mixed The title of the object as a string, otherwise false
 
204
  */
205
  public function get_object_title() {
206
  if ( ! isset( $this->object_id ) || empty( $this->object_id ) ) {
classes/class-settings.php CHANGED
@@ -1,4 +1,9 @@
1
  <?php
 
 
 
 
 
2
 
3
  namespace WP_Stream;
4
 
@@ -6,10 +11,13 @@ use \WP_Roles;
6
  use \WP_User;
7
  use \WP_User_Query;
8
 
 
 
 
9
  class Settings {
10
 
11
  /**
12
- * Hold Plugin class
13
  *
14
  * @var Plugin
15
  */
@@ -46,7 +54,7 @@ class Settings {
46
  /**
47
  * Class constructor.
48
  *
49
- * @param Plugin $plugin The main Plugin class.
50
  */
51
  public function __construct( $plugin ) {
52
  $this->plugin = $plugin;
@@ -54,10 +62,10 @@ class Settings {
54
  $this->option_key = $this->get_option_key();
55
  $this->options = $this->get_options();
56
 
57
- // Register settings, and fields
58
  add_action( 'admin_init', array( $this, 'register_settings' ) );
59
 
60
- // Remove records when records TTL is shortened
61
  add_action(
62
  'update_option_' . $this->option_key,
63
  array(
@@ -68,7 +76,7 @@ class Settings {
68
  2
69
  );
70
 
71
- // Apply label translations for settings
72
  add_filter(
73
  'wp_stream_serialized_labels',
74
  array(
@@ -77,10 +85,10 @@ class Settings {
77
  )
78
  );
79
 
80
- // Ajax callback function to search users
81
  add_action( 'wp_ajax_stream_get_users', array( $this, 'get_users' ) );
82
 
83
- // Ajax callback function to search IPs
84
  add_action( 'wp_ajax_stream_get_ips', array( $this, 'get_ips' ) );
85
  }
86
 
@@ -165,7 +173,7 @@ class Settings {
165
  $users_added_to_response = array();
166
 
167
  foreach ( $users_array as $key => $user ) {
168
- // exclude duplications:
169
  if ( array_key_exists( $user->ID, $users_added_to_response ) ) {
170
  continue;
171
  } else {
@@ -181,7 +189,7 @@ class Settings {
181
 
182
  $args['tooltip'] = esc_attr(
183
  sprintf(
184
- // translators: Placeholders refers to a user ID, a username, an email address, and a user role (e.g. "42", "administrator", "foo@bar.com", "subscriber").
185
  __( 'ID: %1$d\nUser: %2$s\nEmail: %3$s\nRole: %4$s', 'stream' ),
186
  $author->id,
187
  $author->user_login,
@@ -367,7 +375,7 @@ class Settings {
367
  ),
368
  );
369
 
370
- // If Akismet is active, allow Admins to opt-in to Akismet tracking
371
  if ( class_exists( 'Akismet' ) ) {
372
  $akismet_tracking = array(
373
  'name' => 'akismet_tracking',
@@ -399,7 +407,7 @@ class Settings {
399
  */
400
  $this->fields = apply_filters( 'wp_stream_settings_option_fields', $fields );
401
 
402
- // Sort option fields in each tab by title ASC
403
  foreach ( $this->fields as $tab => $options ) {
404
  $titles = array();
405
 
@@ -489,7 +497,8 @@ class Settings {
489
  );
490
 
491
  foreach ( $section['fields'] as $field_idx => $field ) {
492
- if ( ! isset( $field['type'] ) ) { // No field type associated, skip, no GUI
 
493
  continue;
494
  }
495
 
@@ -505,7 +514,7 @@ class Settings {
505
  $field + array(
506
  'section' => $section_name,
507
  'label_for' => sprintf( '%s_%s_%s', $this->option_key, $section_name, $field['name'] ),
508
- // xss ok
509
  )
510
  );
511
  }
@@ -515,7 +524,7 @@ class Settings {
515
  /**
516
  * Sanitization callback for settings field values before save
517
  *
518
- * @param array $input
519
  *
520
  * @return array
521
  */
@@ -568,7 +577,7 @@ class Settings {
568
  /**
569
  * Compile HTML needed for displaying the field
570
  *
571
- * @param array $field Field settings
572
  *
573
  * @return string HTML to be displayed
574
  */
@@ -797,7 +806,7 @@ class Settings {
797
  esc_attr( wp_stream_json_encode( $data_values ) ),
798
  esc_attr( $current_value ),
799
  esc_attr( $class ),
800
- // translators: Placeholder refers to the title of the dropdown menu (e.g. "users")
801
  sprintf( esc_html__( 'Any %s', 'stream' ), $title )
802
  );
803
 
@@ -858,7 +867,7 @@ class Settings {
858
  $action = isset( $current_value['action'][ $key ] ) ? $current_value['action'][ $key ] : '';
859
  $ip_address = isset( $current_value['ip_address'][ $key ] ) ? $current_value['ip_address'][ $key ] : '';
860
 
861
- // Author or Role dropdown menu
862
  $author_or_role_values = array();
863
  $author_or_role_selected = array();
864
 
@@ -870,7 +879,7 @@ class Settings {
870
  $count = isset( $users['avail_roles'][ $role_id ] ) ? $users['avail_roles'][ $role_id ] : 0;
871
 
872
  if ( ! empty( $count ) ) {
873
- // translators: Placeholder refers to a number of users (e.g. "42")
874
  $args['user_count'] = sprintf( _n( '%d user', '%d users', absint( $count ), 'stream' ), absint( $count ) );
875
  }
876
 
@@ -907,7 +916,7 @@ class Settings {
907
  )
908
  );
909
 
910
- // Context dropdown menu
911
  $context_values = array();
912
 
913
  foreach ( $this->get_terms_labels( 'context' ) as $context_id => $context_data ) {
@@ -969,7 +978,7 @@ class Settings {
969
  )
970
  );
971
 
972
- // Action dropdown menu
973
  $action_values = array();
974
 
975
  foreach ( $this->get_terms_labels( 'action' ) as $action_id => $action_data ) {
@@ -992,7 +1001,7 @@ class Settings {
992
  )
993
  );
994
 
995
- // IP Address input
996
  $ip_address_input = $form->render_field(
997
  'select2',
998
  array(
@@ -1007,7 +1016,7 @@ class Settings {
1007
  )
1008
  );
1009
 
1010
- // Hidden helper input
1011
  $helper_input = sprintf(
1012
  '<input type="hidden" name="%1$s[%2$s_%3$s][%4$s][]" value="" />',
1013
  esc_attr( $option_key ),
@@ -1062,7 +1071,7 @@ class Settings {
1062
  /**
1063
  * Render Callback for post_types field
1064
  *
1065
- * @param array $field
1066
  *
1067
  * @return string
1068
  */
@@ -1075,7 +1084,7 @@ class Settings {
1075
 
1076
  $output = $this->render_field( $field );
1077
 
1078
- echo $output; // xss ok
1079
  }
1080
 
1081
  /**
@@ -1097,7 +1106,7 @@ class Settings {
1097
  /**
1098
  * Function will return all terms labels of given column
1099
  *
1100
- * @param string $column string Name of the column
1101
  *
1102
  * @return array
1103
  */
@@ -1132,8 +1141,8 @@ class Settings {
1132
  *
1133
  * @action update_option_wp_stream
1134
  *
1135
- * @param array $old_value
1136
- * @param array $new_value
1137
  */
1138
  public function updated_option_ttl_remove_records( $old_value, $new_value ) {
1139
  $ttl_before = isset( $old_value['general_records_ttl'] ) ? (int) $old_value['general_records_ttl'] : - 1;
@@ -1152,6 +1161,8 @@ class Settings {
1152
  *
1153
  * @filter wp_stream_serialized_labels
1154
  *
 
 
1155
  * @return array Multidimensional array of fields
1156
  */
1157
  public function get_settings_translations( $labels ) {
1
  <?php
2
+ /**
3
+ * Renders and manages the plugin Settings page.
4
+ *
5
+ * @package WP_Stream
6
+ */
7
 
8
  namespace WP_Stream;
9
 
11
  use \WP_User;
12
  use \WP_User_Query;
13
 
14
+ /**
15
+ * Class - Settings
16
+ */
17
  class Settings {
18
 
19
  /**
20
+ * Holds instance of plugin object
21
  *
22
  * @var Plugin
23
  */
54
  /**
55
  * Class constructor.
56
  *
57
+ * @param Plugin $plugin Instance of plugin object.
58
  */
59
  public function __construct( $plugin ) {
60
  $this->plugin = $plugin;
62
  $this->option_key = $this->get_option_key();
63
  $this->options = $this->get_options();
64
 
65
+ // Register settings, and fields.
66
  add_action( 'admin_init', array( $this, 'register_settings' ) );
67
 
68
+ // Remove records when records TTL is shortened.
69
  add_action(
70
  'update_option_' . $this->option_key,
71
  array(
76
  2
77
  );
78
 
79
+ // Apply label translations for settings.
80
  add_filter(
81
  'wp_stream_serialized_labels',
82
  array(
85
  )
86
  );
87
 
88
+ // Ajax callback function to search users.
89
  add_action( 'wp_ajax_stream_get_users', array( $this, 'get_users' ) );
90
 
91
+ // Ajax callback function to search IPs.
92
  add_action( 'wp_ajax_stream_get_ips', array( $this, 'get_ips' ) );
93
  }
94
 
173
  $users_added_to_response = array();
174
 
175
  foreach ( $users_array as $key => $user ) {
176
+ // exclude duplications.
177
  if ( array_key_exists( $user->ID, $users_added_to_response ) ) {
178
  continue;
179
  } else {
189
 
190
  $args['tooltip'] = esc_attr(
191
  sprintf(
192
+ /* translators: %1$d: user ID, %2$s: username, %3$s: email, %4$s: user role (e.g. "42", "administrator", "foo@bar.com", "subscriber") */
193
  __( 'ID: %1$d\nUser: %2$s\nEmail: %3$s\nRole: %4$s', 'stream' ),
194
  $author->id,
195
  $author->user_login,
375
  ),
376
  );
377
 
378
+ // If Akismet is active, allow Admins to opt-in to Akismet tracking.
379
  if ( class_exists( 'Akismet' ) ) {
380
  $akismet_tracking = array(
381
  'name' => 'akismet_tracking',
407
  */
408
  $this->fields = apply_filters( 'wp_stream_settings_option_fields', $fields );
409
 
410
+ // Sort option fields in each tab by title ASC.
411
  foreach ( $this->fields as $tab => $options ) {
412
  $titles = array();
413
 
497
  );
498
 
499
  foreach ( $section['fields'] as $field_idx => $field ) {
500
+ // No field type associated, skip, no GUI.
501
+ if ( ! isset( $field['type'] ) ) {
502
  continue;
503
  }
504
 
514
  $field + array(
515
  'section' => $section_name,
516
  'label_for' => sprintf( '%s_%s_%s', $this->option_key, $section_name, $field['name'] ),
517
+ // xss ok.
518
  )
519
  );
520
  }
524
  /**
525
  * Sanitization callback for settings field values before save
526
  *
527
+ * @param array $input Raw input.
528
  *
529
  * @return array
530
  */
577
  /**
578
  * Compile HTML needed for displaying the field
579
  *
580
+ * @param array $field Field settings.
581
  *
582
  * @return string HTML to be displayed
583
  */
806
  esc_attr( wp_stream_json_encode( $data_values ) ),
807
  esc_attr( $current_value ),
808
  esc_attr( $class ),
809
+ /* translators: %s: the title of the dropdown menu (e.g. "users") */
810
  sprintf( esc_html__( 'Any %s', 'stream' ), $title )
811
  );
812
 
867
  $action = isset( $current_value['action'][ $key ] ) ? $current_value['action'][ $key ] : '';
868
  $ip_address = isset( $current_value['ip_address'][ $key ] ) ? $current_value['ip_address'][ $key ] : '';
869
 
870
+ // Author or Role dropdown menu.
871
  $author_or_role_values = array();
872
  $author_or_role_selected = array();
873
 
879
  $count = isset( $users['avail_roles'][ $role_id ] ) ? $users['avail_roles'][ $role_id ] : 0;
880
 
881
  if ( ! empty( $count ) ) {
882
+ /* translators: %d: a number of users (e.g. "42") */
883
  $args['user_count'] = sprintf( _n( '%d user', '%d users', absint( $count ), 'stream' ), absint( $count ) );
884
  }
885
 
916
  )
917
  );
918
 
919
+ // Context dropdown menu.
920
  $context_values = array();
921
 
922
  foreach ( $this->get_terms_labels( 'context' ) as $context_id => $context_data ) {
978
  )
979
  );
980
 
981
+ // Action dropdown menu.
982
  $action_values = array();
983
 
984
  foreach ( $this->get_terms_labels( 'action' ) as $action_id => $action_data ) {
1001
  )
1002
  );
1003
 
1004
+ // IP Address input.
1005
  $ip_address_input = $form->render_field(
1006
  'select2',
1007
  array(
1016
  )
1017
  );
1018
 
1019
+ // Hidden helper input.
1020
  $helper_input = sprintf(
1021
  '<input type="hidden" name="%1$s[%2$s_%3$s][%4$s][]" value="" />',
1022
  esc_attr( $option_key ),
1071
  /**
1072
  * Render Callback for post_types field
1073
  *
1074
+ * @param array $field Field to be rendered.
1075
  *
1076
  * @return string
1077
  */
1084
 
1085
  $output = $this->render_field( $field );
1086
 
1087
+ echo $output; // xss ok.
1088
  }
1089
 
1090
  /**
1106
  /**
1107
  * Function will return all terms labels of given column
1108
  *
1109
+ * @param string $column Name of the column.
1110
  *
1111
  * @return array
1112
  */
1141
  *
1142
  * @action update_option_wp_stream
1143
  *
1144
+ * @param array $old_value Old value.
1145
+ * @param array $new_value New value.
1146
  */
1147
  public function updated_option_ttl_remove_records( $old_value, $new_value ) {
1148
  $ttl_before = isset( $old_value['general_records_ttl'] ) ? (int) $old_value['general_records_ttl'] : - 1;
1161
  *
1162
  * @filter wp_stream_serialized_labels
1163
  *
1164
+ * @param array $labels Setting labels.
1165
+ *
1166
  * @return array Multidimensional array of fields
1167
  */
1168
  public function get_settings_translations( $labels ) {
classes/class-uninstall.php CHANGED
@@ -1,9 +1,18 @@
1
  <?php
 
 
 
 
 
 
2
  namespace WP_Stream;
3
 
 
 
 
4
  class Uninstall {
5
  /**
6
- * Hold Plugin class
7
  *
8
  * @var Plugin
9
  */
@@ -23,14 +32,19 @@ class Uninstall {
23
  */
24
  public $user_meta;
25
 
 
 
 
 
 
26
  public function __construct( $plugin ) {
27
  $this->plugin = $plugin;
28
 
29
  $this->user_meta = array(
30
  'edit_stream_per_page',
31
- 'stream_last_read', // Deprecated
32
- 'stream_unread_count', // Deprecated
33
- 'stream_user_feed_key', // Deprecated
34
  );
35
  }
36
 
@@ -44,7 +58,7 @@ class Uninstall {
44
  $this->plugin->settings->network_options_key,
45
  );
46
 
47
- // Verify current user's permissions before proceeding
48
  if ( ! current_user_can( $this->plugin->admin->settings_cap ) ) {
49
  wp_die(
50
  esc_html__( "You don't have sufficient privileges to do this action.", 'stream' )
@@ -57,16 +71,18 @@ class Uninstall {
57
  );
58
  }
59
 
60
- // Prevent this action from firing
61
  remove_action( 'deactivate_plugin', array( 'Connector_Installer', 'callback' ), null );
62
 
63
- // Just in case
64
  if ( ! function_exists( 'is_plugin_active_for_network' ) ) {
65
  require_once ABSPATH . '/wp-admin/includes/plugin.php';
66
  }
67
 
68
- // Drop everything on single site installs or when network activated
69
- // Otherwise only delete data relative to the current blog
 
 
70
  if ( ! is_multisite() || $this->plugin->is_network_activated() ) {
71
  $this->delete_all_records();
72
  $this->delete_all_options();
@@ -97,7 +113,7 @@ class Uninstall {
97
  /**
98
  * Delete records and record meta from a specific blog
99
  *
100
- * @param int $blog_id (optional)
101
  */
102
  private function delete_blog_records( $blog_id = 1 ) {
103
  if ( empty( $blog_id ) || ! is_int( $blog_id ) ) {
@@ -124,23 +140,23 @@ class Uninstall {
124
  private function delete_all_options() {
125
  global $wpdb;
126
 
127
- // Wildcard matches
128
  $wpdb->query( "DELETE FROM {$wpdb->options} WHERE option_name LIKE '%wp_stream%';" );
129
 
130
- // Specific options
131
  foreach ( $this->options as $option ) {
132
- delete_site_option( $option ); // Supports both multisite and single site installs
133
  }
134
 
135
- // Single site installs can stop here
136
  if ( ! is_multisite() ) {
137
  return;
138
  }
139
 
140
- // Wildcard matches on network options
141
  $wpdb->query( "DELETE FROM {$wpdb->sitemeta} WHERE meta_key LIKE '%wp_stream%';" );
142
 
143
- // Delete options from each blog on network
144
  foreach ( wp_stream_get_sites() as $blog ) {
145
  $this->delete_blog_options( absint( $blog->blog_id ) );
146
  }
@@ -149,7 +165,7 @@ class Uninstall {
149
  /**
150
  * Delete options from a specific blog
151
  *
152
- * @param int $blog_id (optional)
153
  */
154
  private function delete_blog_options( $blog_id = 1 ) {
155
  if ( empty( $blog_id ) || ! is_int( $blog_id ) ) {
@@ -158,10 +174,10 @@ class Uninstall {
158
 
159
  global $wpdb;
160
 
161
- // Wildcard matches
162
  $wpdb->query( "DELETE FROM {$wpdb->prefix}options WHERE option_name LIKE '%wp_stream%';" );
163
 
164
- // Specific options
165
  foreach ( $this->options as $option ) {
166
  delete_blog_option( $blog_id, $option );
167
  }
@@ -173,10 +189,10 @@ class Uninstall {
173
  private function delete_all_user_meta() {
174
  global $wpdb;
175
 
176
- // Wildcard matches
177
  $wpdb->query( "DELETE FROM {$wpdb->usermeta} WHERE meta_key LIKE '%wp_stream%';" );
178
 
179
- // Specific user meta
180
  foreach ( $this->user_meta as $meta_key ) {
181
  $wpdb->query(
182
  $wpdb->prepare( "DELETE FROM {$wpdb->usermeta} WHERE meta_key = %s;", $meta_key )
@@ -187,7 +203,7 @@ class Uninstall {
187
  /**
188
  * Delete user meta from a specific blog
189
  *
190
- * @param int $blog_id (optional)
191
  */
192
  private function delete_blog_user_meta( $blog_id = 1 ) {
193
  if ( empty( $blog_id ) || ! is_int( $blog_id ) ) {
@@ -196,10 +212,10 @@ class Uninstall {
196
 
197
  global $wpdb;
198
 
199
- // Wildcard matches
200
  $wpdb->query( "DELETE FROM {$wpdb->usermeta} WHERE meta_key LIKE '{$wpdb->prefix}%wp_stream%';" );
201
 
202
- // Specific user meta
203
  foreach ( $this->user_meta as $meta_key ) {
204
  $wpdb->query(
205
  $wpdb->prepare( "DELETE FROM {$wpdb->usermeta} WHERE meta_key = {$wpdb->prefix}%s;", $meta_key )
1
  <?php
2
+ /**
3
+ * Manages the uninstallation of the plugin.
4
+ *
5
+ * @package WP_Stream
6
+ */
7
+
8
  namespace WP_Stream;
9
 
10
+ /**
11
+ * Class - Uninstall
12
+ */
13
  class Uninstall {
14
  /**
15
+ * Holds Instance of plugin object
16
  *
17
  * @var Plugin
18
  */
32
  */
33
  public $user_meta;
34
 
35
+ /**
36
+ * Class constructor
37
+ *
38
+ * @param Plugin $plugin Instance of plugin object.
39
+ */
40
  public function __construct( $plugin ) {
41
  $this->plugin = $plugin;
42
 
43
  $this->user_meta = array(
44
  'edit_stream_per_page',
45
+ 'stream_last_read', // Deprecated.
46
+ 'stream_unread_count', // Deprecated.
47
+ 'stream_user_feed_key', // Deprecated.
48
  );
49
  }
50
 
58
  $this->plugin->settings->network_options_key,
59
  );
60
 
61
+ // Verify current user's permissions before proceeding.
62
  if ( ! current_user_can( $this->plugin->admin->settings_cap ) ) {
63
  wp_die(
64
  esc_html__( "You don't have sufficient privileges to do this action.", 'stream' )
71
  );
72
  }
73
 
74
+ // Prevent this action from firing.
75
  remove_action( 'deactivate_plugin', array( 'Connector_Installer', 'callback' ), null );
76
 
77
+ // Just in case.
78
  if ( ! function_exists( 'is_plugin_active_for_network' ) ) {
79
  require_once ABSPATH . '/wp-admin/includes/plugin.php';
80
  }
81
 
82
+ /**
83
+ * Drop everything on single site installs or when network activated
84
+ * Otherwise only delete data relative to the current blog.
85
+ */
86
  if ( ! is_multisite() || $this->plugin->is_network_activated() ) {
87
  $this->delete_all_records();
88
  $this->delete_all_options();
113
  /**
114
  * Delete records and record meta from a specific blog
115
  *
116
+ * @param int $blog_id Blog ID (optional).
117
  */
118
  private function delete_blog_records( $blog_id = 1 ) {
119
  if ( empty( $blog_id ) || ! is_int( $blog_id ) ) {
140
  private function delete_all_options() {
141
  global $wpdb;
142
 
143
+ // Wildcard matches.
144
  $wpdb->query( "DELETE FROM {$wpdb->options} WHERE option_name LIKE '%wp_stream%';" );
145
 
146
+ // Specific options.
147
  foreach ( $this->options as $option ) {
148
+ delete_site_option( $option ); // Supports both multisite and single site installs.
149
  }
150
 
151
+ // Single site installs can stop here.
152
  if ( ! is_multisite() ) {
153
  return;
154
  }
155
 
156
+ // Wildcard matches on network options.
157
  $wpdb->query( "DELETE FROM {$wpdb->sitemeta} WHERE meta_key LIKE '%wp_stream%';" );
158
 
159
+ // Delete options from each blog on network.
160
  foreach ( wp_stream_get_sites() as $blog ) {
161
  $this->delete_blog_options( absint( $blog->blog_id ) );
162
  }
165
  /**
166
  * Delete options from a specific blog
167
  *
168
+ * @param int $blog_id Blog ID (optional).
169
  */
170
  private function delete_blog_options( $blog_id = 1 ) {
171
  if ( empty( $blog_id ) || ! is_int( $blog_id ) ) {
174
 
175
  global $wpdb;
176
 
177
+ // Wildcard matches.
178
  $wpdb->query( "DELETE FROM {$wpdb->prefix}options WHERE option_name LIKE '%wp_stream%';" );
179
 
180
+ // Specific options.
181
  foreach ( $this->options as $option ) {
182
  delete_blog_option( $blog_id, $option );
183
  }
189
  private function delete_all_user_meta() {
190
  global $wpdb;
191
 
192
+ // Wildcard matches.
193
  $wpdb->query( "DELETE FROM {$wpdb->usermeta} WHERE meta_key LIKE '%wp_stream%';" );
194
 
195
+ // Specific user meta.
196
  foreach ( $this->user_meta as $meta_key ) {
197
  $wpdb->query(
198
  $wpdb->prepare( "DELETE FROM {$wpdb->usermeta} WHERE meta_key = %s;", $meta_key )
203
  /**
204
  * Delete user meta from a specific blog
205
  *
206
+ * @param int $blog_id Blog ID (optional).
207
  */
208
  private function delete_blog_user_meta( $blog_id = 1 ) {
209
  if ( empty( $blog_id ) || ! is_int( $blog_id ) ) {
212
 
213
  global $wpdb;
214
 
215
+ // Wildcard matches.
216
  $wpdb->query( "DELETE FROM {$wpdb->usermeta} WHERE meta_key LIKE '{$wpdb->prefix}%wp_stream%';" );
217
 
218
+ // Specific user meta.
219
  foreach ( $this->user_meta as $meta_key ) {
220
  $wpdb->query(
221
  $wpdb->prepare( "DELETE FROM {$wpdb->usermeta} WHERE meta_key = {$wpdb->prefix}%s;", $meta_key )
connectors/class-connector-acf.php CHANGED
@@ -1,6 +1,15 @@
1
  <?php
 
 
 
 
 
 
2
  namespace WP_Stream;
3
 
 
 
 
4
  class Connector_ACF extends Connector {
5
  /**
6
  * Connector slug
@@ -126,8 +135,8 @@ class Connector_ACF extends Connector {
126
  *
127
  * @filter wp_stream_action_links_{connector}
128
  *
129
- * @param array $links Previous links registered
130
- * @param object $record Stream record
131
  *
132
  * @return array Action links
133
  */
@@ -201,12 +210,12 @@ class Connector_ACF extends Connector {
201
  /**
202
  * Track addition of post/user meta
203
  *
204
- * @param string $type Type of object, post or user
205
- * @param string $action Added, updated, deleted
206
- * @param integer $meta_id
207
- * @param integer $object_id
208
- * @param string $meta_key
209
- * @param mixed|null $meta_value
210
  */
211
  public function check_meta( $type, $action, $meta_id, $object_id, $meta_key, $meta_value = null ) {
212
  $post = get_post( $object_id );
@@ -217,14 +226,14 @@ class Connector_ACF extends Connector {
217
 
218
  $action_labels = $this->get_action_labels();
219
 
220
- // Fields
221
  if ( 0 === strpos( $meta_key, 'field_' ) ) {
222
  if ( 'deleted' === $action ) {
223
  $meta_value = get_post_meta( $object_id, $meta_key, true );
224
  }
225
 
226
  $this->log(
227
- // translators: Placeholders refer to a field label, a form title, and an action (e.g. "Message", "Contact", "Created")
228
  esc_html_x( '"%1$s" field in "%2$s" %3$s', 'acf', 'stream' ),
229
  array(
230
  'label' => $meta_value['label'],
@@ -255,7 +264,7 @@ class Connector_ACF extends Connector {
255
  );
256
 
257
  $this->log(
258
- // translators: Placeholders refer to a form title, and a position (e.g. "Contact", "Side")
259
  esc_html_x( 'Position of "%1$s" updated to "%2$s"', 'acf', 'stream' ),
260
  array(
261
  'title' => $post->post_title,
@@ -278,7 +287,7 @@ class Connector_ACF extends Connector {
278
  );
279
 
280
  $this->log(
281
- // translators: Placeholders refer to a form title, and a layout (e.g. "Contact", "Seamless")
282
  esc_html_x( 'Style of "%1$s" updated to "%2$s"', 'acf', 'stream' ),
283
  array(
284
  'title' => $post->post_title,
@@ -321,7 +330,7 @@ class Connector_ACF extends Connector {
321
  }
322
 
323
  $this->log(
324
- // translators: Placeholders refer to a form title, and a display option (e.g. "Contact", "All screens")
325
  esc_html_x( '"%1$s" set to display on "%2$s"', 'acf', 'stream' ),
326
  array(
327
  'title' => $post->post_title,
@@ -339,12 +348,12 @@ class Connector_ACF extends Connector {
339
  /**
340
  * Track changes to ACF values within rendered post meta forms
341
  *
342
- * @param string $type Type of object, post or user
343
- * @param string $action Added, updated, deleted
344
- * @param integer $meta_id
345
- * @param integer $object_id
346
- * @param string $key
347
- * @param mixed|null $value
348
  *
349
  * @return bool
350
  */
@@ -361,7 +370,7 @@ class Connector_ACF extends Connector {
361
  if ( 'user' === $type ) {
362
  $object_key = 'user_' . $object_id;
363
  } elseif ( 'taxonomy' === $type ) {
364
- if ( 0 === strpos( $key, '_' ) ) { // Ignore the 'revision' stuff!
365
  return false;
366
  }
367
 
@@ -369,7 +378,7 @@ class Connector_ACF extends Connector {
369
  return false;
370
  }
371
 
372
- list( , $taxonomy, $term_id, $key ) = $matches; // Skips 0 index
373
 
374
  $object_key = $taxonomy . '_' . $term_id;
375
  } elseif ( 'option' === $type ) {
@@ -403,7 +412,7 @@ class Connector_ACF extends Connector {
403
  $cache = $this->cached_field_values_updates[ $object_key ][ $key ];
404
 
405
  $this->log(
406
- // translators: Placeholders refer to a field label, an object title, and an object type (e.g. "Message", "Hello World", "post")
407
  esc_html_x( '"%1$s" of "%2$s" %3$s updated', 'acf', 'stream' ),
408
  array(
409
  'field_label' => $cache['field']['label'],
@@ -442,7 +451,7 @@ class Connector_ACF extends Connector {
442
  $deleted = array_diff( $old, $new );
443
 
444
  $this->log(
445
- // translators: Placeholders refer to a form title, the number of rules added, and the number of rules deleted (e.g. "Contact", "42", "7")
446
  esc_html_x( 'Updated rules of "%1$s" (%2$d added, %3$d deleted)', 'acf', 'stream' ),
447
  array(
448
  'title' => $post->post_title,
@@ -461,7 +470,7 @@ class Connector_ACF extends Connector {
461
  /**
462
  * Override connector log for our own Settings / Actions
463
  *
464
- * @param array $data
465
  *
466
  * @return array|bool
467
  */
@@ -483,9 +492,9 @@ class Connector_ACF extends Connector {
483
  * Track changes to custom field values updates, saves filtered values to be
484
  * processed by callback_updated_post_meta
485
  *
486
- * @param string $value
487
- * @param int $post_id
488
- * @param string $field
489
  *
490
  * @return string
491
  */
@@ -497,8 +506,8 @@ class Connector_ACF extends Connector {
497
  /**
498
  * Track changes to post main attributes, ie: Order No.
499
  *
500
- * @param int $post_id
501
- * @param array $data Array with the updated post data
502
  */
503
  public function callback_pre_post_update( $post_id, $data ) {
504
  $post = get_post( $post_id );
@@ -510,7 +519,7 @@ class Connector_ACF extends Connector {
510
  // menu_order, aka Order No.
511
  if ( $data['menu_order'] !== $post->menu_order ) {
512
  $this->log(
513
- // translators: Placeholders refer to a form title, a numeric position, and another numeric position (e.g. "Contact", "42", "7")
514
  esc_html_x( '"%1$s" reordered from %2$d to %3$d', 'acf', 'stream' ),
515
  array(
516
  'title' => $post->post_title,
@@ -527,8 +536,8 @@ class Connector_ACF extends Connector {
527
  /**
528
  * Track addition of new options
529
  *
530
- * @param string $key Option name
531
- * @param string $value Option value
532
  */
533
  public function callback_added_option( $key, $value ) {
534
  $this->check_meta_values( self::get_saved_option_type( $key ), 'added', null, null, $key, $value );
@@ -537,9 +546,9 @@ class Connector_ACF extends Connector {
537
  /**
538
  * Track addition of new options
539
  *
540
- * @param $key
541
- * @param $old
542
- * @param $value
543
  */
544
  public function callback_updated_option( $key, $old, $value ) {
545
  unset( $old );
@@ -549,7 +558,7 @@ class Connector_ACF extends Connector {
549
  /**
550
  * Track addition of new options
551
  *
552
- * @param $key
553
  */
554
  public function callback_deleted_option( $key ) {
555
  $this->check_meta_values( self::get_saved_option_type( $key ), 'deleted', null, null, $key, null );
@@ -558,7 +567,7 @@ class Connector_ACF extends Connector {
558
  /**
559
  * Determines the type of option that is saved
560
  *
561
- * @param $key
562
  * @return string
563
  */
564
  private function get_saved_option_type( $key ) {
1
  <?php
2
+ /**
3
+ * Connector - Advanced Custom Fields
4
+ *
5
+ * @package WP_Stream
6
+ */
7
+
8
  namespace WP_Stream;
9
 
10
+ /**
11
+ * Class - Connector_ACF
12
+ */
13
  class Connector_ACF extends Connector {
14
  /**
15
  * Connector slug
135
  *
136
  * @filter wp_stream_action_links_{connector}
137
  *
138
+ * @param array $links Previous links registered.
139
+ * @param object $record Stream record.
140
  *
141
  * @return array Action links
142
  */
210
  /**
211
  * Track addition of post/user meta
212
  *
213
+ * @param string $type Type of object, post or user.
214
+ * @param string $action Added, updated, deleted.
215
+ * @param integer $meta_id Meta ID.
216
+ * @param integer $object_id Object ID.
217
+ * @param string $meta_key Meta Key.
218
+ * @param mixed|null $meta_value Value being stored in meta.
219
  */
220
  public function check_meta( $type, $action, $meta_id, $object_id, $meta_key, $meta_value = null ) {
221
  $post = get_post( $object_id );
226
 
227
  $action_labels = $this->get_action_labels();
228
 
229
+ // Fields.
230
  if ( 0 === strpos( $meta_key, 'field_' ) ) {
231
  if ( 'deleted' === $action ) {
232
  $meta_value = get_post_meta( $object_id, $meta_key, true );
233
  }
234
 
235
  $this->log(
236
+ /* translators: %1$s: field label, %2$s: form title, %3$s: action (e.g. "Message", "Contact", "Created") */
237
  esc_html_x( '"%1$s" field in "%2$s" %3$s', 'acf', 'stream' ),
238
  array(
239
  'label' => $meta_value['label'],
264
  );
265
 
266
  $this->log(
267
+ /* translators: %1$s: form title, %2$s a position (e.g. "Contact", "Side") */
268
  esc_html_x( 'Position of "%1$s" updated to "%2$s"', 'acf', 'stream' ),
269
  array(
270
  'title' => $post->post_title,
287
  );
288
 
289
  $this->log(
290
+ /* translators: %1$s: form title, %2$s a layout (e.g. "Contact", "Seamless") */
291
  esc_html_x( 'Style of "%1$s" updated to "%2$s"', 'acf', 'stream' ),
292
  array(
293
  'title' => $post->post_title,
330
  }
331
 
332
  $this->log(
333
+ /* translators: %1$s: a form title, %2$s: a display option (e.g. "Contact", "All screens") */
334
  esc_html_x( '"%1$s" set to display on "%2$s"', 'acf', 'stream' ),
335
  array(
336
  'title' => $post->post_title,
348
  /**
349
  * Track changes to ACF values within rendered post meta forms
350
  *
351
+ * @param string $type Type of object, post or user.
352
+ * @param string $action Added, updated, deleted.
353
+ * @param integer $meta_id Meta ID.
354
+ * @param integer $object_id Object ID.
355
+ * @param string $key Meta Key.
356
+ * @param mixed|null $value Value being stored in meta.
357
  *
358
  * @return bool
359
  */
370
  if ( 'user' === $type ) {
371
  $object_key = 'user_' . $object_id;
372
  } elseif ( 'taxonomy' === $type ) {
373
+ if ( 0 === strpos( $key, '_' ) ) { // Ignore the 'revision' stuff!.
374
  return false;
375
  }
376
 
378
  return false;
379
  }
380
 
381
+ list( , $taxonomy, $term_id, $key ) = $matches; // Skips 0 index.
382
 
383
  $object_key = $taxonomy . '_' . $term_id;
384
  } elseif ( 'option' === $type ) {
412
  $cache = $this->cached_field_values_updates[ $object_key ][ $key ];
413
 
414
  $this->log(
415
+ /* translators: %1$s: a field label, %2$s: an object title, %3$s: an object type (e.g. "Message", "Hello World", "post") */
416
  esc_html_x( '"%1$s" of "%2$s" %3$s updated', 'acf', 'stream' ),
417
  array(
418
  'field_label' => $cache['field']['label'],
451
  $deleted = array_diff( $old, $new );
452
 
453
  $this->log(
454
+ /* translators: %1$s: a form title, %2$d: the number of rules added, %3$d: the number of rules deleted (e.g. "Contact", "42", "7") */
455
  esc_html_x( 'Updated rules of "%1$s" (%2$d added, %3$d deleted)', 'acf', 'stream' ),
456
  array(
457
  'title' => $post->post_title,
470
  /**
471
  * Override connector log for our own Settings / Actions
472
  *
473
+ * @param array $data Record data.
474
  *
475
  * @return array|bool
476
  */
492
  * Track changes to custom field values updates, saves filtered values to be
493
  * processed by callback_updated_post_meta
494
  *
495
+ * @param string $value Field value.
496
+ * @param int $post_id Field post ID.
497
+ * @param string $field Field name.
498
  *
499
  * @return string
500
  */
506
  /**
507
  * Track changes to post main attributes, ie: Order No.
508
  *
509
+ * @param int $post_id Field post ID.
510
+ * @param array $data Array with the updated post data.
511
  */
512
  public function callback_pre_post_update( $post_id, $data ) {
513
  $post = get_post( $post_id );
519
  // menu_order, aka Order No.
520
  if ( $data['menu_order'] !== $post->menu_order ) {
521
  $this->log(
522
+ /* translators: %1$s: a form title, %2$d: a numeric position, %3$d: numeric position (e.g. "Contact", "42", "7") */
523
  esc_html_x( '"%1$s" reordered from %2$d to %3$d', 'acf', 'stream' ),
524
  array(
525
  'title' => $post->post_title,
536
  /**
537
  * Track addition of new options
538
  *
539
+ * @param string $key Option name.
540
+ * @param string $value Option value.
541
  */
542
  public function callback_added_option( $key, $value ) {
543
  $this->check_meta_values( self::get_saved_option_type( $key ), 'added', null, null, $key, $value );
546
  /**
547
  * Track addition of new options
548
  *
549
+ * @param string $key Option key.
550
+ * @param string $old Old value.
551
+ * @param string $value New value.
552
  */
553
  public function callback_updated_option( $key, $old, $value ) {
554
  unset( $old );
558
  /**
559
  * Track addition of new options
560
  *
561
+ * @param string $key Option key.
562
  */
563
  public function callback_deleted_option( $key ) {
564
  $this->check_meta_values( self::get_saved_option_type( $key ), 'deleted', null, null, $key, null );
567
  /**
568
  * Determines the type of option that is saved
569
  *
570
+ * @param string $key Option key.
571
  * @return string
572
  */
573
  private function get_saved_option_type( $key ) {
connectors/class-connector-bbpress.php CHANGED
@@ -1,6 +1,15 @@
1
  <?php
 
 
 
 
 
 
2
  namespace WP_Stream;
3
 
 
 
 
4
  class Connector_BbPress extends Connector {
5
  /**
6
  * Connector slug
@@ -42,16 +51,22 @@ class Connector_BbPress extends Connector {
42
  public $is_update = false;
43
 
44
  /**
 
 
45
  * @var bool
46
  */
47
- public $_deleted_activity = false;
48
 
49
  /**
 
 
50
  * @var array
51
  */
52
- public $_delete_activity_args = array();
53
 
54
  /**
 
 
55
  * @var bool
56
  */
57
  public $ignore_activity_bulk_deletion = false;
@@ -120,8 +135,8 @@ class Connector_BbPress extends Connector {
120
  *
121
  * @filter wp_stream_action_links_{connector}
122
  *
123
- * @param array $links Previous links registered
124
- * @param object $record Stream record
125
  *
126
  * @return array Action links
127
  */
@@ -140,6 +155,9 @@ class Connector_BbPress extends Connector {
140
  return $links;
141
  }
142
 
 
 
 
143
  public function register() {
144
  parent::register();
145
 
@@ -149,7 +167,7 @@ class Connector_BbPress extends Connector {
149
  /**
150
  * Override connector log for our own Settings / Actions
151
  *
152
- * @param array $data
153
  *
154
  * @return array|bool
155
  */
@@ -184,12 +202,12 @@ class Connector_BbPress extends Connector {
184
  } elseif ( 'posts' === $data['connector'] && in_array( $data['context'], array( 'forum', 'topic', 'reply' ), true ) ) {
185
  if ( 'reply' === $data['context'] ) {
186
  if ( 'updated' === $data['action'] ) {
187
- // translators: Placeholder refers to a post title (e.g. "Hello World")
188
- $data['message'] = esc_html__( 'Replied on "%1$s"', 'stream' );
189
  $data['args']['post_title'] = get_post( wp_get_post_parent_id( $data['object_id'] ) )->post_title;
190
  }
191
  $data['args']['post_title'] = sprintf(
192
- // translators: Placeholder refers to a post title (e.g. "Hello World")
193
  __( 'Reply to: %s', 'stream' ),
194
  get_post( wp_get_post_parent_id( $data['object_id'] ) )->post_title
195
  );
@@ -206,10 +224,10 @@ class Connector_BbPress extends Connector {
206
  /**
207
  * Tracks togging the forum topics
208
  *
209
- * @param bool $success
210
- * @param \WP_Post $post_data
211
- * @param string $action
212
- * @param string $message
213
  *
214
  * @return array|bool
215
  */
@@ -232,7 +250,7 @@ class Connector_BbPress extends Connector {
232
  $topic = get_post( $message['topic_id'] );
233
 
234
  $this->log(
235
- // translators: Placeholders refer to an action, and a topic title (e.g. "Created", "Read this first")
236
  _x( '%1$s "%2$s" topic', '1: Action, 2: Topic title', 'stream' ),
237
  array(
238
  'action_title' => $actions[ $action ],
1
  <?php
2
+ /**
3
+ * Connector for bbPress
4
+ *
5
+ * @package WP_Stream
6
+ */
7
+
8
  namespace WP_Stream;
9
 
10
+ /**
11
+ * Class - Connector_BbPress
12
+ */
13
  class Connector_BbPress extends Connector {
14
  /**
15
  * Connector slug
51
  public $is_update = false;
52
 
53
  /**
54
+ * Stores an activity to be deleted for use across multiple callbacks.
55
+ *
56
  * @var bool
57
  */
58
+ public $deleted_activity = false;
59
 
60
  /**
61
+ * Stores post data of an activity to be deleted for use across multiple callbacks.
62
+ *
63
  * @var array
64
  */
65
+ public $delete_activity_args = array();
66
 
67
  /**
68
+ * Flag for ignoring irrelevant activity deletions.
69
+ *
70
  * @var bool
71
  */
72
  public $ignore_activity_bulk_deletion = false;
135
  *
136
  * @filter wp_stream_action_links_{connector}
137
  *
138
+ * @param array $links Previous links registered.
139
+ * @param object $record Stream record.
140
  *
141
  * @return array Action links
142
  */
155
  return $links;
156
  }
157
 
158
+ /**
159
+ * Register the connector
160
+ */
161
  public function register() {
162
  parent::register();
163
 
167
  /**
168
  * Override connector log for our own Settings / Actions
169
  *
170
+ * @param array $data Record data.
171
  *
172
  * @return array|bool
173
  */
202
  } elseif ( 'posts' === $data['connector'] && in_array( $data['context'], array( 'forum', 'topic', 'reply' ), true ) ) {
203
  if ( 'reply' === $data['context'] ) {
204
  if ( 'updated' === $data['action'] ) {
205
+ /* translators: %s: a post title (e.g. "Hello World") */
206
+ $data['message'] = esc_html__( 'Replied on "%s"', 'stream' );
207
  $data['args']['post_title'] = get_post( wp_get_post_parent_id( $data['object_id'] ) )->post_title;
208
  }
209
  $data['args']['post_title'] = sprintf(
210
+ /* translators: %s a post title (e.g. "Hello World") */
211
  __( 'Reply to: %s', 'stream' ),
212
  get_post( wp_get_post_parent_id( $data['object_id'] ) )->post_title
213
  );
224
  /**
225
  * Tracks togging the forum topics
226
  *
227
+ * @param bool $success If action success.
228
+ * @param \WP_Post $post_data Post data.
229
+ * @param string $action Record action.
230
+ * @param string $message Message status data.
231
  *
232
  * @return array|bool
233
  */
250
  $topic = get_post( $message['topic_id'] );
251
 
252
  $this->log(
253
+ /* translators: %1$s: an action, %2$s: a topic title (e.g. "Created", "Read this first") */
254
  _x( '%1$s "%2$s" topic', '1: Action, 2: Topic title', 'stream' ),
255
  array(
256
  'action_title' => $actions[ $action ],
connectors/class-connector-blogs.php CHANGED
@@ -1,6 +1,15 @@
1
  <?php
 
 
 
 
 
 
2
  namespace WP_Stream;
3
 
 
 
 
4
  class Connector_Blogs extends Connector {
5
  /**
6
  * Connector slug
@@ -74,7 +83,7 @@ class Connector_Blogs extends Connector {
74
 
75
  foreach ( $blogs as $blog ) {
76
  $blog_details = get_blog_details( $blog->blog_id );
77
- $key = sanitize_key( $blog_details->blogname );
78
  $labels[ $key ] = $blog_details->blogname;
79
  }
80
  }
@@ -87,8 +96,8 @@ class Connector_Blogs extends Connector {
87
  *
88
  * @filter wp_stream_action_links_{connector}
89
  *
90
- * @param array $links
91
- * @param Record $record
92
  *
93
  * @return array
94
  */
@@ -122,15 +131,15 @@ class Connector_Blogs extends Connector {
122
  *
123
  * @action wpmu_new_blog
124
  *
125
- * @param int $blog_id
126
  */
127
  public function callback_wpmu_new_blog( $blog_id ) {
128
  $blog = get_blog_details( $blog_id );
129
 
130
  $this->log(
131
- // translators: Placeholder refers to site name (e.g. "FooBar Blog")
132
  _x(
133
- '"%1$s" site was created',
134
  '1. Site name',
135
  'stream'
136
  ),
@@ -148,16 +157,16 @@ class Connector_Blogs extends Connector {
148
  *
149
  * @action wpmu_activate_blog
150
  *
151
- * @param int $blog_id
152
- * @param int $user_id
153
  */
154
  public function callback_wpmu_activate_blog( $blog_id, $user_id ) {
155
  $blog = get_blog_details( $blog_id );
156
 
157
  $this->log(
158
- // translators: Placeholder refers to site name (e.g. "FooBar Blog")
159
  _x(
160
- '"%1$s" site was registered',
161
  '1. Site name',
162
  'stream'
163
  ),
@@ -176,9 +185,9 @@ class Connector_Blogs extends Connector {
176
  *
177
  * @action add_user_to_blog
178
  *
179
- * @param int $user_id
180
- * @param string $role
181
- * @param int $blog_id
182
  */
183
  public function callback_add_user_to_blog( $user_id, $role, $blog_id ) {
184
  $blog = get_blog_details( $blog_id );
@@ -189,7 +198,7 @@ class Connector_Blogs extends Connector {
189
  }
190
 
191
  $this->log(
192
- // translators: Placeholders refer to a user's display name, a site name, and a user role (e.g. "Jane Doe", "FooBar Blog", "subscriber")
193
  _x(
194
  '%1$s was added to the "%2$s" site with %3$s capabilities',
195
  '1. User\'s name, 2. Site name, 3. Role',
@@ -211,8 +220,8 @@ class Connector_Blogs extends Connector {
211
  *
212
  * @action remove_user_from_blog
213
  *
214
- * @param int $user_id
215
- * @param int $blog_id
216
  */
217
  public function callback_remove_user_from_blog( $user_id, $blog_id ) {
218
  $blog = get_blog_details( $blog_id );
@@ -223,7 +232,7 @@ class Connector_Blogs extends Connector {
223
  }
224
 
225
  $this->log(
226
- // translators: Placeholders refer to a user's display name, and a site name (e.g. "Jane Doe", "FooBar Blog")
227
  _x(
228
  '%1$s was removed from the "%2$s" site',
229
  '1. User\'s name, 2. Site name',
@@ -244,7 +253,7 @@ class Connector_Blogs extends Connector {
244
  *
245
  * @action make_spam_blog
246
  *
247
- * @param int $blog_id
248
  */
249
  public function callback_make_spam_blog( $blog_id ) {
250
  $this->callback_update_blog_status( $blog_id, esc_html__( 'marked as spam', 'stream' ), 'updated' );
@@ -255,7 +264,7 @@ class Connector_Blogs extends Connector {
255
  *
256
  * @action make_ham_blog
257
  *
258
- * @param int $blog_id
259
  */
260
  public function callback_make_ham_blog( $blog_id ) {
261
  $this->callback_update_blog_status( $blog_id, esc_html__( 'marked as not spam', 'stream' ), 'updated' );
@@ -266,7 +275,7 @@ class Connector_Blogs extends Connector {
266
  *
267
  * @action mature_blog
268
  *
269
- * @param int $blog_id
270
  */
271
  public function callback_mature_blog( $blog_id ) {
272
  $this->callback_update_blog_status( $blog_id, esc_html__( 'marked as mature', 'stream' ), 'updated' );
@@ -277,7 +286,7 @@ class Connector_Blogs extends Connector {
277
  *
278
  * @action unmature_blog
279
  *
280
- * @param int $blog_id
281
  */
282
  public function callback_unmature_blog( $blog_id ) {
283
  $this->callback_update_blog_status( $blog_id, esc_html__( 'marked as not mature', 'stream' ), 'updated' );
@@ -288,7 +297,7 @@ class Connector_Blogs extends Connector {
288
  *
289
  * @action archive_blog
290
  *
291
- * @param int $blog_id
292
  */
293
  public function callback_archive_blog( $blog_id ) {
294
  $this->callback_update_blog_status( $blog_id, esc_html__( 'archived', 'stream' ), 'archive_blog' );
@@ -299,7 +308,7 @@ class Connector_Blogs extends Connector {
299
  *
300
  * @action unarchive_blog
301
  *
302
- * @param int $blog_id
303
  */
304
  public function callback_unarchive_blog( $blog_id ) {
305
  $this->callback_update_blog_status( $blog_id, esc_html__( 'restored from archive', 'stream' ), 'updated' );
@@ -310,7 +319,7 @@ class Connector_Blogs extends Connector {
310
  *
311
  * @action make_delete_blog
312
  *
313
- * @param int $blog_id
314
  */
315
  public function callback_make_delete_blog( $blog_id ) {
316
  $this->callback_update_blog_status( $blog_id, esc_html__( 'deleted', 'stream' ), 'deleted' );
@@ -321,7 +330,7 @@ class Connector_Blogs extends Connector {
321
  *
322
  * @action undelete_blog
323
  *
324
- * @param int $blog_id
325
  */
326
  public function callback_make_undelete_blog( $blog_id ) {
327
  $this->callback_update_blog_status( $blog_id, esc_html__( 'restored', 'stream' ), 'updated' );
@@ -332,8 +341,8 @@ class Connector_Blogs extends Connector {
332
  *
333
  * @action update_blog_public
334
  *
335
- * @param int $blog_id
336
- * @param string $value
337
  */
338
  public function callback_update_blog_public( $blog_id, $value ) {
339
  if ( $value ) {
@@ -350,15 +359,15 @@ class Connector_Blogs extends Connector {
350
  *
351
  * @action update_blog_status
352
  *
353
- * @param int $blog_id
354
- * @param string $status
355
- * @param string $action
356
  */
357
  public function callback_update_blog_status( $blog_id, $status, $action ) {
358
  $blog = get_blog_details( $blog_id );
359
 
360
  $this->log(
361
- // translators: Placeholders refer to a site name, and a blog status (e.g. "FooBar Blog", "archived")
362
  _x(
363
  '"%1$s" site was %2$s',
364
  '1. Site name, 2. Status',
1
  <?php
2
+ /**
3
+ * Connector for Blog actions.
4
+ *
5
+ * @package WP_Stream
6
+ */
7
+
8
  namespace WP_Stream;
9
 
10
+ /**
11
+ * Class - Connector_Blogs
12
+ */
13
  class Connector_Blogs extends Connector {
14
  /**
15
  * Connector slug
83
 
84
  foreach ( $blogs as $blog ) {
85
  $blog_details = get_blog_details( $blog->blog_id );
86
+ $key = sprintf( 'blog-%d', $blog->blog_id );
87
  $labels[ $key ] = $blog_details->blogname;
88
  }
89
  }
96
  *
97
  * @filter wp_stream_action_links_{connector}
98
  *
99
+ * @param array $links Previous links registered.
100
+ * @param object $record Stream record.
101
  *
102
  * @return array
103
  */
131
  *
132
  * @action wpmu_new_blog
133
  *
134
+ * @param int $blog_id Blog ID.
135
  */
136
  public function callback_wpmu_new_blog( $blog_id ) {
137
  $blog = get_blog_details( $blog_id );
138
 
139
  $this->log(
140
+ /* translators: %s: site name (e.g. "FooBar Blog") */
141
  _x(
142
+ '"%s" site was created',
143
  '1. Site name',
144
  'stream'
145
  ),
157
  *
158
  * @action wpmu_activate_blog
159
  *
160
+ * @param int $blog_id Blog ID.
161
+ * @param int $user_id User ID.
162
  */
163
  public function callback_wpmu_activate_blog( $blog_id, $user_id ) {
164
  $blog = get_blog_details( $blog_id );
165
 
166
  $this->log(
167
+ /* translators: %s: site name (e.g. "FooBar Blog") */
168
  _x(
169
+ '"%s" site was registered',
170
  '1. Site name',
171
  'stream'
172
  ),
185
  *
186
  * @action add_user_to_blog
187
  *
188
+ * @param int $user_id User ID.
189
+ * @param string $role User role.
190
+ * @param int $blog_id Blog ID.
191
  */
192
  public function callback_add_user_to_blog( $user_id, $role, $blog_id ) {
193
  $blog = get_blog_details( $blog_id );
198
  }
199
 
200
  $this->log(
201
+ /* translators: %1$s: a user's display name, %2$s: a site name, %3$s: a user role (e.g. "Jane Doe", "FooBar Blog", "subscriber") */
202
  _x(
203
  '%1$s was added to the "%2$s" site with %3$s capabilities',
204
  '1. User\'s name, 2. Site name, 3. Role',
220
  *
221
  * @action remove_user_from_blog
222
  *
223
+ * @param int $user_id User ID.
224
+ * @param int $blog_id Blog ID.
225
  */
226
  public function callback_remove_user_from_blog( $user_id, $blog_id ) {
227
  $blog = get_blog_details( $blog_id );
232
  }
233
 
234
  $this->log(
235
+ /* translators: %1$s: a user's display name, %2$s: a site name (e.g. "Jane Doe", "FooBar Blog") */
236
  _x(
237
  '%1$s was removed from the "%2$s" site',
238
  '1. User\'s name, 2. Site name',
253
  *
254
  * @action make_spam_blog
255
  *
256
+ * @param int $blog_id Blog ID.
257
  */
258
  public function callback_make_spam_blog( $blog_id ) {
259
  $this->callback_update_blog_status( $blog_id, esc_html__( 'marked as spam', 'stream' ), 'updated' );
264
  *
265
  * @action make_ham_blog
266
  *
267
+ * @param int $blog_id Blog ID.
268
  */
269
  public function callback_make_ham_blog( $blog_id ) {
270
  $this->callback_update_blog_status( $blog_id, esc_html__( 'marked as not spam', 'stream' ), 'updated' );
275
  *
276
  * @action mature_blog
277
  *
278
+ * @param int $blog_id Blog ID.
279
  */
280
  public function callback_mature_blog( $blog_id ) {
281
  $this->callback_update_blog_status( $blog_id, esc_html__( 'marked as mature', 'stream' ), 'updated' );
286
  *
287
  * @action unmature_blog
288
  *
289
+ * @param int $blog_id Blog ID.
290
  */
291
  public function callback_unmature_blog( $blog_id ) {
292
  $this->callback_update_blog_status( $blog_id, esc_html__( 'marked as not mature', 'stream' ), 'updated' );
297
  *
298
  * @action archive_blog
299
  *
300
+ * @param int $blog_id Blog ID.
301
  */
302
  public function callback_archive_blog( $blog_id ) {
303
  $this->callback_update_blog_status( $blog_id, esc_html__( 'archived', 'stream' ), 'archive_blog' );
308
  *
309
  * @action unarchive_blog
310
  *
311
+ * @param int $blog_id Blog ID.
312
  */
313
  public function callback_unarchive_blog( $blog_id ) {
314
  $this->callback_update_blog_status( $blog_id, esc_html__( 'restored from archive', 'stream' ), 'updated' );
319
  *
320
  * @action make_delete_blog
321
  *
322
+ * @param int $blog_id Blog ID.
323
  */
324
  public function callback_make_delete_blog( $blog_id ) {
325
  $this->callback_update_blog_status( $blog_id, esc_html__( 'deleted', 'stream' ), 'deleted' );
330
  *
331
  * @action undelete_blog
332
  *
333
+ * @param int $blog_id Blog ID.
334
  */
335
  public function callback_make_undelete_blog( $blog_id ) {
336
  $this->callback_update_blog_status( $blog_id, esc_html__( 'restored', 'stream' ), 'updated' );
341
  *
342
  * @action update_blog_public
343
  *
344
+ * @param int $blog_id Blog ID.
345
+ * @param string $value Status flag.
346
  */
347
  public function callback_update_blog_public( $blog_id, $value ) {
348
  if ( $value ) {
359
  *
360
  * @action update_blog_status
361
  *
362
+ * @param int $blog_id Blog ID.
363
+ * @param string $status Blog Status.
364
+ * @param string $action Action.
365
  */
366
  public function callback_update_blog_status( $blog_id, $status, $action ) {
367
  $blog = get_blog_details( $blog_id );
368
 
369
  $this->log(
370
+ /* translators: %1$s: a site name, %2$s: a blog status (e.g. "FooBar Blog", "archived") */
371
  _x(
372
  '"%1$s" site was %2$s',
373
  '1. Site name, 2. Status',
connectors/class-connector-buddypress.php CHANGED
@@ -1,7 +1,15 @@
1
  <?php
 
 
 
 
 
2
 
3
  namespace WP_Stream;
4
 
 
 
 
5
  class Connector_BuddyPress extends Connector {
6
 
7
  /**
@@ -79,16 +87,22 @@ class Connector_BuddyPress extends Connector {
79
  public $is_update = false;
80
 
81
  /**
 
 
82
  * @var bool
83
  */
84
- public $_deleted_activity = false;
85
 
86
  /**
 
 
87
  * @var array
88
  */
89
- public $_delete_activity_args = array();
90
 
91
  /**
 
 
92
  * @var bool
93
  */
94
  public $ignore_activity_bulk_deletion = false;
@@ -153,8 +167,8 @@ class Connector_BuddyPress extends Connector {
153
  *
154
  * @filter wp_stream_action_links_{connector}
155
  *
156
- * @param array $links Previous links registered
157
- * @param object $record Stream record
158
  *
159
  * @return array Action links
160
  */
@@ -200,7 +214,7 @@ class Connector_BuddyPress extends Connector {
200
  );
201
 
202
  if ( $group ) {
203
- // Build actions URLs
204
  $base_url = \bp_get_admin_url( 'admin.php?page=bp-groups&amp;gid=' . $group_id );
205
  $delete_url = wp_nonce_url( $base_url . '&amp;action=delete', 'bp-groups-delete' );
206
  $edit_url = $base_url . '&amp;action=edit';
@@ -240,7 +254,7 @@ class Connector_BuddyPress extends Connector {
240
  $field_id = $record->get_meta( 'field_id', true );
241
  $group_id = $record->get_meta( 'group_id', true );
242
 
243
- if ( empty( $field_id ) ) { // is a group action
244
  $links[ esc_html__( 'Edit', 'stream' ) ] = add_query_arg(
245
  array(
246
  'page' => 'bp-profile-setup',
@@ -285,6 +299,9 @@ class Connector_BuddyPress extends Connector {
285
  return $links;
286
  }
287
 
 
 
 
288
  public function register() {
289
  parent::register();
290
 
@@ -335,30 +352,73 @@ class Connector_BuddyPress extends Connector {
335
  );
336
  }
337
 
 
 
 
 
 
 
 
338
  public function callback_update_option( $option, $old, $new ) {
339
  $this->check( $option, $old, $new );
340
  }
341
 
 
 
 
 
 
 
342
  public function callback_add_option( $option, $val ) {
343
  $this->check( $option, null, $val );
344
  }
345
 
 
 
 
 
 
346
  public function callback_delete_option( $option ) {
347
  $this->check( $option, null, null );
348
  }
349
 
 
 
 
 
 
 
 
350
  public function callback_update_site_option( $option, $old, $new ) {
351
  $this->check( $option, $old, $new );
352
  }
353
 
 
 
 
 
 
 
354
  public function callback_add_site_option( $option, $val ) {
355
  $this->check( $option, null, $val );
356
  }
357
 
 
 
 
 
 
358
  public function callback_delete_site_option( $option ) {
359
  $this->check( $option, null, null );
360
  }
361
 
 
 
 
 
 
 
 
362
  public function check( $option, $old_value, $new_value ) {
363
  if ( ! array_key_exists( $option, $this->options ) ) {
364
  return;
@@ -382,7 +442,7 @@ class Connector_BuddyPress extends Connector {
382
  $page = isset( $data['page'] ) ? $data['page'] : null;
383
 
384
  $this->log(
385
- // translators: Placeholder refers to setting name (e.g. "Group Creation")
386
  __( '"%s" setting updated', 'stream' ),
387
  compact( 'option_title', 'option', 'old_value', 'new_value', 'page' ),
388
  null,
@@ -392,6 +452,12 @@ class Connector_BuddyPress extends Connector {
392
  }
393
  }
394
 
 
 
 
 
 
 
395
  public function check_bp_active_components( $old_value, $new_value ) {
396
  $options = array();
397
 
@@ -417,7 +483,7 @@ class Connector_BuddyPress extends Connector {
417
 
418
  $this->log(
419
  sprintf(
420
- // translators: Placeholder refers to component title (e.g. "Members")
421
  __( '"%1$s" component %2$s', 'stream' ),
422
  $components[ $option ]['title'],
423
  $actions[ $option_value ]
@@ -435,6 +501,12 @@ class Connector_BuddyPress extends Connector {
435
  }
436
  }
437
 
 
 
 
 
 
 
438
  public function check_bp_pages( $old_value, $new_value ) {
439
  $options = array();
440
 
@@ -463,7 +535,7 @@ class Connector_BuddyPress extends Connector {
463
 
464
  $this->log(
465
  sprintf(
466
- // translators: Placeholders refer to a directory page, and a page title (e.g. "Register", "Registration" )
467
  __( '"%1$s" page set to "%2$s"', 'stream' ),
468
  $pages[ $option ],
469
  $page
@@ -482,26 +554,40 @@ class Connector_BuddyPress extends Connector {
482
  }
483
  }
484
 
 
 
 
 
 
 
 
485
  public function callback_bp_before_activity_delete( $args ) {
486
- if ( empty( $args['id'] ) ) { // Bail if we're deleting in bulk
487
- $this->_delete_activity_args = $args;
488
 
489
  return;
490
  }
491
 
492
  $activity = new \BP_Activity_Activity( $args['id'] );
493
 
494
- $this->_deleted_activity = $activity;
495
  }
496
 
 
 
 
 
 
 
 
497
  public function callback_bp_activity_deleted_activities( $activities_ids ) {
498
- if ( 1 === count( $activities_ids ) && isset( $this->_deleted_activity ) ) { // Single activity deletion
499
- $activity = $this->_deleted_activity;
500
  $this->log(
501
  sprintf(
502
- // translators: Placeholder refers to an activity title (e.g. "Update")
503
  __( '"%s" activity deleted', 'stream' ),
504
- strip_tags( $activity->action )
505
  ),
506
  array(
507
  'id' => $activity->id,
@@ -513,9 +599,12 @@ class Connector_BuddyPress extends Connector {
513
  $activity->component,
514
  'deleted'
515
  );
516
- } else { // Bulk deletion
517
- // Sometimes some objects removal are followed by deleting relevant
518
- // activities, so we probably don't need to track those
 
 
 
519
  if ( $this->ignore_activity_bulk_deletion ) {
520
  $this->ignore_activity_bulk_deletion = false;
521
 
@@ -523,13 +612,13 @@ class Connector_BuddyPress extends Connector {
523
  }
524
  $this->log(
525
  sprintf(
526
- // translators: Placeholder refers to an activity title (e.g. "Update")
527
  __( '"%s" activities were deleted', 'stream' ),
528
  count( $activities_ids )
529
  ),
530
  array(
531
  'count' => count( $activities_ids ),
532
- 'args' => $this->_delete_activity_args,
533
  'ids' => $activities_ids,
534
  ),
535
  null,
@@ -539,14 +628,22 @@ class Connector_BuddyPress extends Connector {
539
  }
540
  }
541
 
 
 
 
 
 
 
 
 
542
  public function callback_bp_activity_mark_as_spam( $activity, $by ) {
543
  unset( $by );
544
 
545
  $this->log(
546
  sprintf(
547
- // translators: Placeholder refers to an activity title (e.g. "Update")
548
  __( 'Marked activity "%s" as spam', 'stream' ),
549
- strip_tags( $activity->action )
550
  ),
551
  array(
552
  'id' => $activity->id,
@@ -560,14 +657,22 @@ class Connector_BuddyPress extends Connector {
560
  );
561
  }
562
 
 
 
 
 
 
 
 
 
563
  public function callback_bp_activity_mark_as_ham( $activity, $by ) {
564
  unset( $by );
565
 
566
  $this->log(
567
  sprintf(
568
- // translators: Placeholder refers to an activity title (e.g. "Update")
569
  __( 'Unmarked activity "%s" as spam', 'stream' ),
570
- strip_tags( $activity->action )
571
  ),
572
  array(
573
  'id' => $activity->id,
@@ -581,14 +686,22 @@ class Connector_BuddyPress extends Connector {
581
  );
582
  }
583
 
 
 
 
 
 
 
 
 
584
  public function callback_bp_activity_admin_edit_after( $activity, $error ) {
585
  unset( $error );
586
 
587
  $this->log(
588
  sprintf(
589
- // translators: Placeholder refers to an activity title (e.g. "Update")
590
  __( '"%s" activity updated', 'stream' ),
591
- strip_tags( $activity->action )
592
  ),
593
  array(
594
  'id' => $activity->id,
@@ -602,6 +715,14 @@ class Connector_BuddyPress extends Connector {
602
  );
603
  }
604
 
 
 
 
 
 
 
 
 
605
  public function group_action( $group, $action, $meta = array(), $message = null ) {
606
  if ( is_numeric( $group ) ) {
607
  $group = \groups_get_group(
@@ -617,30 +738,30 @@ class Connector_BuddyPress extends Connector {
617
 
618
  if ( ! $message ) {
619
  if ( 'created' === $action ) {
620
- // translators: Placeholder refers to a group name (e.g. "Favourites")
621
  $message = esc_html__( '"%s" group created', 'stream' );
622
  } elseif ( 'updated' === $action ) {
623
- // translators: Placeholder refers to a group name (e.g. "Favourites")
624
  $message = esc_html__( '"%s" group updated', 'stream' );
625
  } elseif ( 'deleted' === $action ) {
626
- // translators: Placeholder refers to a group name (e.g. "Favourites")
627
  $message = esc_html__( '"%s" group deleted', 'stream' );
628
  } elseif ( 'joined' === $action ) {
629
- // translators: Placeholder refers to a group name (e.g. "Favourites")
630
  $message = esc_html__( 'Joined group "%s"', 'stream' );
631
  } elseif ( 'left' === $action ) {
632
- // translators: Placeholder refers to a group name (e.g. "Favourites")
633
  $message = esc_html__( 'Left group "%s"', 'stream' );
634
  } elseif ( 'banned' === $action ) {
635
- // translators: Placeholders refer to a user display name, and a group name (e.g. "Jane Doe", "Favourites")
636
  $message = esc_html__( 'Banned "%2$s" from "%1$s"', 'stream' );
637
  $replacements[] = get_user_by( 'id', $meta['user_id'] )->display_name;
638
  } elseif ( 'unbanned' === $action ) {
639
- // translators: Placeholders refer to a user display name, and a group name (e.g. "Jane Doe", "Favourites")
640
  $message = esc_html__( 'Unbanned "%2$s" from "%1$s"', 'stream' );
641
  $replacements[] = get_user_by( 'id', $meta['user_id'] )->display_name;
642
  } elseif ( 'removed' === $action ) {
643
- // translators: Placeholders refer to a user display name, and a group name (e.g. "Jane Doe", "Favourites")
644
  $message = esc_html__( 'Removed "%2$s" from "%1$s"', 'stream' );
645
  $replacements[] = get_user_by( 'id', $meta['user_id'] )->display_name;
646
  } else {
@@ -667,6 +788,15 @@ class Connector_BuddyPress extends Connector {
667
  );
668
  }
669
 
 
 
 
 
 
 
 
 
 
670
  public function callback_groups_create_group( $group_id, $member, $group ) {
671
  unset( $group_id );
672
  unset( $member );
@@ -674,22 +804,51 @@ class Connector_BuddyPress extends Connector {
674
  $this->group_action( $group, 'created' );
675
  }
676
 
 
 
 
 
 
 
 
 
677
  public function callback_groups_update_group( $group_id, $group ) {
678
  unset( $group_id );
679
 
680
  $this->group_action( $group, 'updated' );
681
  }
682
 
 
 
 
 
 
 
 
683
  public function callback_groups_before_delete_group( $group_id ) {
684
  $this->ignore_activity_bulk_deletion = true;
685
  $this->group_action( $group_id, 'deleted' );
686
  }
687
 
 
 
 
 
 
 
 
688
  public function callback_groups_details_updated( $group_id ) {
689
  $this->is_update = true;
690
  $this->group_action( $group_id, 'updated' );
691
  }
692
 
 
 
 
 
 
 
 
693
  public function callback_groups_settings_updated( $group_id ) {
694
  if ( $this->is_update ) {
695
  return;
@@ -697,14 +856,39 @@ class Connector_BuddyPress extends Connector {
697
  $this->group_action( $group_id, 'updated' );
698
  }
699
 
 
 
 
 
 
 
 
 
700
  public function callback_groups_leave_group( $group_id, $user_id ) {
701
  $this->group_action( $group_id, 'left', compact( 'user_id' ) );
702
  }
703
 
 
 
 
 
 
 
 
 
704
  public function callback_groups_join_group( $group_id, $user_id ) {
705
  $this->group_action( $group_id, 'joined', compact( 'user_id' ) );
706
  }
707
 
 
 
 
 
 
 
 
 
 
708
  public function callback_groups_promote_member( $group_id, $user_id, $status ) {
709
  $group = \groups_get_group(
710
  array(
@@ -717,7 +901,7 @@ class Connector_BuddyPress extends Connector {
717
  'mod' => esc_html_x( 'Moderator', 'buddypress', 'stream' ),
718
  );
719
  $message = sprintf(
720
- // translators: Placeholders refer to a user's display name, a user role, and a group name (e.g. "Jane Doe", "subscriber", "Favourites")
721
  __( 'Promoted "%1$s" to "%2$s" in "%3$s"', 'stream' ),
722
  $user->display_name,
723
  $roles[ $status ],
@@ -726,6 +910,14 @@ class Connector_BuddyPress extends Connector {
726
  $this->group_action( $group_id, 'promoted', compact( 'user_id', 'status' ), $message );
727
  }
728
 
 
 
 
 
 
 
 
 
729
  public function callback_groups_demote_member( $group_id, $user_id ) {
730
  $group = \groups_get_group(
731
  array(
@@ -734,7 +926,7 @@ class Connector_BuddyPress extends Connector {
734
  );
735
  $user = new \WP_User( $user_id );
736
  $message = sprintf(
737
- // translators: Placeholders refer to a user's display name, a user role, and a group name (e.g. "Jane Doe", "Member", "Favourites")
738
  __( 'Demoted "%1$s" to "%2$s" in "%3$s"', 'stream' ),
739
  $user->display_name,
740
  _x( 'Member', 'buddypress', 'stream' ),
@@ -743,18 +935,50 @@ class Connector_BuddyPress extends Connector {
743
  $this->group_action( $group_id, 'demoted', compact( 'user_id' ), $message );
744
  }
745
 
 
 
 
 
 
 
 
 
746
  public function callback_groups_ban_member( $group_id, $user_id ) {
747
  $this->group_action( $group_id, 'banned', compact( 'user_id' ) );
748
  }
749
 
 
 
 
 
 
 
 
 
750
  public function callback_groups_unban_member( $group_id, $user_id ) {
751
  $this->group_action( $group_id, 'unbanned', compact( 'user_id' ) );
752
  }
753
 
 
 
 
 
 
 
 
 
754
  public function callback_groups_remove_member( $group_id, $user_id ) {
755
  $this->group_action( $group_id, 'removed', compact( 'user_id' ) );
756
  }
757
 
 
 
 
 
 
 
 
 
758
  public function field_action( $field, $action, $meta = array(), $message = null ) {
759
  $replacements = array(
760
  $field->name,
@@ -762,13 +986,13 @@ class Connector_BuddyPress extends Connector {
762
 
763
  if ( ! $message ) {
764
  if ( 'created' === $action ) {
765
- // translators: Placeholder refers to a user profile field (e.g. "Job Title")
766
  $message = esc_html__( 'Created profile field "%s"', 'stream' );
767
  } elseif ( 'updated' === $action ) {
768
- // translators: Placeholder refers to a user profile field (e.g. "Job Title")
769
  $message = esc_html__( 'Updated profile field "%s"', 'stream' );
770
  } elseif ( 'deleted' === $action ) {
771
- // translators: Placeholder refers to a user profile field (e.g. "Job Title")
772
  $message = esc_html__( 'Deleted profile field "%s"', 'stream' );
773
  } else {
774
  return;
@@ -794,15 +1018,37 @@ class Connector_BuddyPress extends Connector {
794
  );
795
  }
796
 
 
 
 
 
 
 
 
797
  public function callback_xprofile_field_after_save( $field ) {
798
  $action = isset( $field->id ) ? 'updated' : 'created';
799
  $this->field_action( $field, $action );
800
  }
801
 
 
 
 
 
 
 
 
802
  public function callback_xprofile_fields_deleted_field( $field ) {
803
  $this->field_action( $field, 'deleted' );
804
  }
805
 
 
 
 
 
 
 
 
 
806
  public function field_group_action( $group, $action, $meta = array(), $message = null ) {
807
  $replacements = array(
808
  $group->name,
@@ -810,13 +1056,13 @@ class Connector_BuddyPress extends Connector {
810
 
811
  if ( ! $message ) {
812
  if ( 'created' === $action ) {
813
- // translators: Placeholder refers to a user profile field group (e.g. "Appearance")
814
  $message = esc_html__( 'Created profile field group "%s"', 'stream' );
815
  } elseif ( 'updated' === $action ) {
816
- // translators: Placeholder refers to a user profile field group (e.g. "Appearance")
817
  $message = esc_html__( 'Updated profile field group "%s"', 'stream' );
818
  } elseif ( 'deleted' === $action ) {
819
- // translators: Placeholder refers to a user profile field group (e.g. "Appearance")
820
  $message = esc_html__( 'Deleted profile field group "%s"', 'stream' );
821
  } else {
822
  return;
@@ -841,27 +1087,49 @@ class Connector_BuddyPress extends Connector {
841
  );
842
  }
843
 
 
 
 
 
 
 
 
844
  public function callback_xprofile_group_after_save( $group ) {
845
  global $wpdb;
846
- // a bit hacky, due to inconsistency with BP action scheme, see callback_xprofile_field_after_save for correct behavior
 
 
 
847
  $action = ( $group->id === $wpdb->insert_id ) ? 'created' : 'updated';
848
  $this->field_group_action( $group, $action );
849
  }
850
 
 
 
 
 
 
 
 
851
  public function callback_xprofile_groups_deleted_group( $group ) {
852
  $this->field_group_action( $group, 'deleted' );
853
  }
854
 
 
 
 
 
 
855
  private function bp_get_directory_pages() {
856
  $bp = \buddypress();
857
  $directory_pages = array();
858
 
859
- // Loop through loaded components and collect directories
860
  if ( is_array( $bp->loaded_components ) ) {
861
  foreach ( $bp->loaded_components as $component_slug => $component_id ) {
862
- // Only components that need directories should be listed here
863
  if ( isset( $bp->{$component_id} ) && ! empty( $bp->{$component_id}->has_directory ) ) {
864
- // component->name was introduced in BP 1.5, so we must provide a fallback
865
  $directory_pages[ $component_id ] = ! empty( $bp->{$component_id}->name ) ? $bp->{$component_id}->name : ucwords( $component_id );
866
  }
867
  }
1
  <?php
2
+ /**
3
+ * Connector for BuddyPress
4
+ *
5
+ * @package WP_Stream
6
+ */
7
 
8
  namespace WP_Stream;
9
 
10
+ /**
11
+ * Class - Connector_BuddyPress
12
+ */
13
  class Connector_BuddyPress extends Connector {
14
 
15
  /**
87
  public $is_update = false;
88
 
89
  /**
90
+ * Stores an activity to be deleted for use across multiple callbacks.
91
+ *
92
  * @var bool
93
  */
94
+ public $deleted_activity = false;
95
 
96
  /**
97
+ * Stores post data of an activity to be deleted for use across multiple callbacks.
98
+ *
99
  * @var array
100
  */
101
+ public $delete_activity_args = array();
102
 
103
  /**
104
+ * Flag for ignoring irrelevant activity deletions.
105
+ *
106
  * @var bool
107
  */
108
  public $ignore_activity_bulk_deletion = false;
167
  *
168
  * @filter wp_stream_action_links_{connector}
169
  *
170
+ * @param array $links Previous links registered.
171
+ * @param object $record Stream record.
172
  *
173
  * @return array Action links
174
  */
214
  );
215
 
216
  if ( $group ) {
217
+ // Build actions URLs.
218
  $base_url = \bp_get_admin_url( 'admin.php?page=bp-groups&amp;gid=' . $group_id );
219
  $delete_url = wp_nonce_url( $base_url . '&amp;action=delete', 'bp-groups-delete' );
220
  $edit_url = $base_url . '&amp;action=edit';
254
  $field_id = $record->get_meta( 'field_id', true );
255
  $group_id = $record->get_meta( 'group_id', true );
256
 
257
+ if ( empty( $field_id ) ) { // is a group action.
258
  $links[ esc_html__( 'Edit', 'stream' ) ] = add_query_arg(
259
  array(
260
  'page' => 'bp-profile-setup',
299
  return $links;
300
  }
301
 
302
+ /**
303
+ * Register the connector
304
+ */
305
  public function register() {
306
  parent::register();
307
 
352
  );
353
  }
354
 
355
+ /**
356
+ * Track buddyPress-specific option changes.
357
+ *
358
+ * @param string $option Option key.
359
+ * @param string $old Old value.
360
+ * @param string $new New value.
361
+ */
362
  public function callback_update_option( $option, $old, $new ) {
363
  $this->check( $option, $old, $new );
364
  }
365
 
366
+ /**
367
+ * Track buddyPress-specific option creations.
368
+ *
369
+ * @param string $option Option key.
370
+ * @param string $val Value.
371
+ */
372
  public function callback_add_option( $option, $val ) {
373
  $this->check( $option, null, $val );
374
  }
375
 
376
+ /**
377
+ * Track buddyPress-specific option deletions.
378
+ *
379
+ * @param string $option Option key.
380
+ */
381
  public function callback_delete_option( $option ) {
382
  $this->check( $option, null, null );
383
  }
384
 
385
+ /**
386
+ * Track buddyPress-specific site option changes
387
+ *
388
+ * @param string $option Option key.
389
+ * @param string $old Old value.
390
+ * @param string $new New value.
391
+ */
392
  public function callback_update_site_option( $option, $old, $new ) {
393
  $this->check( $option, $old, $new );
394
  }
395
 
396
+ /**
397
+ * Track buddyPress-specific site option creations.
398
+ *
399
+ * @param string $option Option key.
400
+ * @param string $val Value.
401
+ */
402
  public function callback_add_site_option( $option, $val ) {
403
  $this->check( $option, null, $val );
404
  }
405
 
406
+ /**
407
+ * Track buddyPress-specific site option deletions.
408
+ *
409
+ * @param string $option Option key.
410
+ */
411
  public function callback_delete_site_option( $option ) {
412
  $this->check( $option, null, null );
413
  }
414
 
415
+ /**
416
+ * Logs buddyPress-specific (site) option action.
417
+ *
418
+ * @param string $option Option key.
419
+ * @param string $old_value Old value.
420
+ * @param string $new_value New value.
421
+ */
422
  public function check( $option, $old_value, $new_value ) {
423
  if ( ! array_key_exists( $option, $this->options ) ) {
424
  return;
442
  $page = isset( $data['page'] ) ? $data['page'] : null;
443
 
444
  $this->log(
445
+ /* translators: %s: setting name (e.g. "Group Creation") */
446
  __( '"%s" setting updated', 'stream' ),
447
  compact( 'option_title', 'option', 'old_value', 'new_value', 'page' ),
448
  null,
452
  }
453
  }
454
 
455
+ /**
456
+ * Log buddyPress' components' state.
457
+ *
458
+ * @param array $old_value Old value.
459
+ * @param array $new_value New value.
460
+ */
461
  public function check_bp_active_components( $old_value, $new_value ) {
462
  $options = array();
463
 
483
 
484
  $this->log(
485
  sprintf(
486
+ /* translators: %1$s: component title, %2$s: component action (e.g. "Members component deactivated") */
487
  __( '"%1$s" component %2$s', 'stream' ),
488
  $components[ $option ]['title'],
489
  $actions[ $option_value ]
501
  }
502
  }
503
 
504
+ /**
505
+ * Log buddyPress' page assignment.
506
+ *
507
+ * @param array $old_value Old value.
508
+ * @param array $new_value New value.
509
+ */
510
  public function check_bp_pages( $old_value, $new_value ) {
511
  $options = array();
512
 
535
 
536
  $this->log(
537
  sprintf(
538
+ /* translators: %1$s: a directory page, %2$s: a page title (e.g. "Register", "Registration" ) */
539
  __( '"%1$s" page set to "%2$s"', 'stream' ),
540
  $pages[ $option ],
541
  $page
554
  }
555
  }
556
 
557
+ /**
558
+ * Logs activity deletions
559
+ *
560
+ * @action bp_before_activity_delete
561
+ *
562
+ * @param array $args Target activity data.
563
+ */
564
  public function callback_bp_before_activity_delete( $args ) {
565
+ if ( empty( $args['id'] ) ) { // Bail if we're deleting in bulk.
566
+ $this->delete_activity_args = $args;
567
 
568
  return;
569
  }
570
 
571
  $activity = new \BP_Activity_Activity( $args['id'] );
572
 
573
+ $this->deleted_activity = $activity;
574
  }
575
 
576
+ /**
577
+ * Logs activity bulk deletions.
578
+ *
579
+ * @action bp_activity_deleted_activities
580
+ *
581
+ * @param array $activities_ids Activity IDs of deleted activities.
582
+ */
583
  public function callback_bp_activity_deleted_activities( $activities_ids ) {
584
+ if ( 1 === count( $activities_ids ) && isset( $this->deleted_activity ) ) { // Single activity deletion.
585
+ $activity = $this->deleted_activity;
586
  $this->log(
587
  sprintf(
588
+ /* translators: %s: an activity title (e.g. "Update") */
589
  __( '"%s" activity deleted', 'stream' ),
590
+ wp_strip_all_tags( $activity->action )
591
  ),
592
  array(
593
  'id' => $activity->id,
599
  $activity->component,
600
  'deleted'
601
  );
602
+ } else {
603
+ /**
604
+ * Bulk deletion
605
+ * Sometimes some objects removal are followed by deleting relevant
606
+ * activities, so we probably don't need to track those
607
+ */
608
  if ( $this->ignore_activity_bulk_deletion ) {
609
  $this->ignore_activity_bulk_deletion = false;
610
 
612
  }
613
  $this->log(
614
  sprintf(
615
+ /* translators: %s: an activity title (e.g. "Update") */
616
  __( '"%s" activities were deleted', 'stream' ),
617
  count( $activities_ids )
618
  ),
619
  array(
620
  'count' => count( $activities_ids ),
621
+ 'args' => $this->delete_activity_args,
622
  'ids' => $activities_ids,
623
  ),
624
  null,
628
  }
629
  }
630
 
631
+ /**
632
+ * Logs activates marked as spam
633
+ *
634
+ * @action bp_activity_mark_as_spam
635
+ *
636
+ * @param array $activity Activity.
637
+ * @param mixed $by Marker.
638
+ */
639
  public function callback_bp_activity_mark_as_spam( $activity, $by ) {
640
  unset( $by );
641
 
642
  $this->log(
643
  sprintf(
644
+ /* translators: %s an activity title (e.g. "Update") */
645
  __( 'Marked activity "%s" as spam', 'stream' ),
646
+ wp_strip_all_tags( $activity->action )
647
  ),
648
  array(
649
  'id' => $activity->id,
657
  );
658
  }
659
 
660
+ /**
661
+ * Log activities marked as ham
662
+ *
663
+ * @action bp_activity_mark_as_ham
664
+ *
665
+ * @param array $activity Activity.
666
+ * @param mixed $by Marker.
667
+ */
668
  public function callback_bp_activity_mark_as_ham( $activity, $by ) {
669
  unset( $by );
670
 
671
  $this->log(
672
  sprintf(
673
+ /* translators: %s: an activity title (e.g. "Update") */
674
  __( 'Unmarked activity "%s" as spam', 'stream' ),
675
+ wp_strip_all_tags( $activity->action )
676
  ),
677
  array(
678
  'id' => $activity->id,
686
  );
687
  }
688
 
689
+ /**
690
+ * Log activity changes made in the WP Admin.
691
+ *
692
+ * @action bp_activity_admin_edit_after
693
+ *
694
+ * @param array $activity Activity.
695
+ * @param mixed $error Any errors.
696
+ */
697
  public function callback_bp_activity_admin_edit_after( $activity, $error ) {
698
  unset( $error );
699
 
700
  $this->log(
701
  sprintf(
702
+ /* translators: %s: an activity title (e.g. "Update") */
703
  __( '"%s" activity updated', 'stream' ),
704
+ wp_strip_all_tags( $activity->action )
705
  ),
706
  array(
707
  'id' => $activity->id,
715
  );
716
  }
717
 
718
+ /**
719
+ * Logs group actions
720
+ *
721
+ * @param int|object $group Group object or group ID.
722
+ * @param string $action Action.
723
+ * @param array $meta Meta data.
724
+ * @param string $message Message.
725
+ */
726
  public function group_action( $group, $action, $meta = array(), $message = null ) {
727
  if ( is_numeric( $group ) ) {
728
  $group = \groups_get_group(
738
 
739
  if ( ! $message ) {
740
  if ( 'created' === $action ) {
741
+ /* translators: %s: a group name (e.g. "Favourites") */
742
  $message = esc_html__( '"%s" group created', 'stream' );
743
  } elseif ( 'updated' === $action ) {
744
+ /* translators: %s: a group name (e.g. "Favourites") */
745
  $message = esc_html__( '"%s" group updated', 'stream' );
746
  } elseif ( 'deleted' === $action ) {
747
+ /* translators: %s: a group name (e.g. "Favourites") */
748
  $message = esc_html__( '"%s" group deleted', 'stream' );
749
  } elseif ( 'joined' === $action ) {
750
+ /* translators: %s: a group name (e.g. "Favourites") */
751
  $message = esc_html__( 'Joined group "%s"', 'stream' );
752
  } elseif ( 'left' === $action ) {
753
+ /* translators: %s: a group name (e.g. "Favourites") */
754
  $message = esc_html__( 'Left group "%s"', 'stream' );
755
  } elseif ( 'banned' === $action ) {
756
+ /* translators: %1$s: a user display name, %2$s: a group name (e.g. "Jane Doe", "Favourites") */
757
  $message = esc_html__( 'Banned "%2$s" from "%1$s"', 'stream' );
758
  $replacements[] = get_user_by( 'id', $meta['user_id'] )->display_name;
759
  } elseif ( 'unbanned' === $action ) {
760
+ /* translators: %1$s: a user display name, %2$s: a group name (e.g. "Jane Doe", "Favourites") */
761
  $message = esc_html__( 'Unbanned "%2$s" from "%1$s"', 'stream' );
762
  $replacements[] = get_user_by( 'id', $meta['user_id'] )->display_name;
763
  } elseif ( 'removed' === $action ) {
764
+ /* translators: %1$s: a user display name, %2$s: a group name (e.g. "Jane Doe", "Favourites") */
765
  $message = esc_html__( 'Removed "%2$s" from "%1$s"', 'stream' );
766
  $replacements[] = get_user_by( 'id', $meta['user_id'] )->display_name;
767
  } else {
788
  );
789
  }
790
 
791
+ /**
792
+ * Log creation of new group.
793
+ *
794
+ * @action groups_create_group
795
+ *
796
+ * @param int $group_id Group ID.
797
+ * @param object $member Group founder user object.
798
+ * @param object $group Group object.
799
+ */
800
  public function callback_groups_create_group( $group_id, $member, $group ) {
801
  unset( $group_id );
802
  unset( $member );
804
  $this->group_action( $group, 'created' );
805
  }
806
 
807
+ /**
808
+ * Log update to existing group.
809
+ *
810
+ * @action groups_update_group
811
+ *
812
+ * @param int $group_id Group ID.
813
+ * @param object $group Group object.
814
+ */
815
  public function callback_groups_update_group( $group_id, $group ) {
816
  unset( $group_id );
817
 
818
  $this->group_action( $group, 'updated' );
819
  }
820
 
821
+ /**
822
+ * Log group deletion
823
+ *
824
+ * @action groups_before_delete_group
825
+ *
826
+ * @param int $group_id Group ID.
827
+ */
828
  public function callback_groups_before_delete_group( $group_id ) {
829
  $this->ignore_activity_bulk_deletion = true;
830
  $this->group_action( $group_id, 'deleted' );
831
  }
832
 
833
+ /**
834
+ * Log change to group details
835
+ *
836
+ * @action groups_details_updated
837
+ *
838
+ * @param int $group_id Group ID.
839
+ */
840
  public function callback_groups_details_updated( $group_id ) {
841
  $this->is_update = true;
842
  $this->group_action( $group_id, 'updated' );
843
  }
844
 
845
+ /**
846
+ * Log change to group settings
847
+ *
848
+ * @action groups_settings_updated
849
+ *
850
+ * @param int $group_id Group ID.
851
+ */
852
  public function callback_groups_settings_updated( $group_id ) {
853
  if ( $this->is_update ) {
854
  return;
856
  $this->group_action( $group_id, 'updated' );
857
  }
858
 
859
+ /**
860
+ * Logs user leaving group
861
+ *
862
+ * @action groups_leave_group
863
+ *
864
+ * @param int $group_id Group ID.
865
+ * @param int $user_id User ID of member.
866
+ */
867
  public function callback_groups_leave_group( $group_id, $user_id ) {
868
  $this->group_action( $group_id, 'left', compact( 'user_id' ) );
869
  }
870
 
871
+ /**
872
+ * Logs user joining group
873
+ *
874
+ * @action groups_join_group
875
+ *
876
+ * @param int $group_id Group ID.
877
+ * @param int $user_id User ID of member.
878
+ */
879
  public function callback_groups_join_group( $group_id, $user_id ) {
880
  $this->group_action( $group_id, 'joined', compact( 'user_id' ) );
881
  }
882
 
883
+ /**
884
+ * Logs group member promotion.
885
+ *
886
+ * @action groups_promote_member
887
+ *
888
+ * @param int $group_id Group ID.
889
+ * @param int $user_id User ID of member.
890
+ * @param string $status Member's new user role.
891
+ */
892
  public function callback_groups_promote_member( $group_id, $user_id, $status ) {
893
  $group = \groups_get_group(
894
  array(
901
  'mod' => esc_html_x( 'Moderator', 'buddypress', 'stream' ),
902
  );
903
  $message = sprintf(
904
+ /* translators: %1$s: a user's display name, %2$s: a user role, %3$s: a group name (e.g. "Jane Doe", "subscriber", "Favourites") */
905
  __( 'Promoted "%1$s" to "%2$s" in "%3$s"', 'stream' ),
906
  $user->display_name,
907
  $roles[ $status ],
910
  $this->group_action( $group_id, 'promoted', compact( 'user_id', 'status' ), $message );
911
  }
912
 
913
+ /**
914
+ * Log group member demotion
915
+ *
916
+ * @action groups_demote_member
917
+ *
918
+ * @param int $group_id Group ID.
919
+ * @param int $user_id User ID of member.
920
+ */
921
  public function callback_groups_demote_member( $group_id, $user_id ) {
922
  $group = \groups_get_group(
923
  array(
926
  );
927
  $user = new \WP_User( $user_id );
928
  $message = sprintf(
929
+ /* translators: %1$s: a user's display name, %2$s: a user role, %3$s: a group name (e.g. "Jane Doe", "Member", "Favourites") */
930
  __( 'Demoted "%1$s" to "%2$s" in "%3$s"', 'stream' ),
931
  $user->display_name,
932
  _x( 'Member', 'buddypress', 'stream' ),
935
  $this->group_action( $group_id, 'demoted', compact( 'user_id' ), $message );
936
  }
937
 
938
+ /**
939
+ * Log member banning
940
+ *
941
+ * @action groups_ban_member
942
+ *
943
+ * @param int $group_id Group ID.
944
+ * @param int $user_id User ID of banned member.
945
+ */
946
  public function callback_groups_ban_member( $group_id, $user_id ) {
947
  $this->group_action( $group_id, 'banned', compact( 'user_id' ) );
948
  }
949
 
950
+ /**
951
+ * Log member reinstatement
952
+ *
953
+ * @action groups_unban_member
954
+ *
955
+ * @param int $group_id Group ID.
956
+ * @param int $user_id User ID of reinstated member.
957
+ */
958
  public function callback_groups_unban_member( $group_id, $user_id ) {
959
  $this->group_action( $group_id, 'unbanned', compact( 'user_id' ) );
960
  }
961
 
962
+ /**
963
+ * Log member removal.
964
+ *
965
+ * @action groups_remove_member
966
+ *
967
+ * @param int $group_id Group ID.
968
+ * @param int $user_id User ID of removed member.
969
+ */
970
  public function callback_groups_remove_member( $group_id, $user_id ) {
971
  $this->group_action( $group_id, 'removed', compact( 'user_id' ) );
972
  }
973
 
974
+ /**
975
+ * Logs user profile field actions
976
+ *
977
+ * @param object $field Field object.
978
+ * @param string $action Action.
979
+ * @param array $meta Meta.
980
+ * @param string $message Message.
981
+ */
982
  public function field_action( $field, $action, $meta = array(), $message = null ) {
983
  $replacements = array(
984
  $field->name,
986
 
987
  if ( ! $message ) {
988
  if ( 'created' === $action ) {
989
+ /* translators: %s: a user profile field (e.g. "Job Title") */
990
  $message = esc_html__( 'Created profile field "%s"', 'stream' );
991
  } elseif ( 'updated' === $action ) {
992
+ /* translators: %s: a user profile field (e.g. "Job Title") */
993
  $message = esc_html__( 'Updated profile field "%s"', 'stream' );
994
  } elseif ( 'deleted' === $action ) {
995
+ /* translators: %s: a user profile field (e.g. "Job Title") */
996
  $message = esc_html__( 'Deleted profile field "%s"', 'stream' );
997
  } else {
998
  return;
1018
  );
1019
  }
1020
 
1021
+ /**
1022
+ * Logs field writes
1023
+ *
1024
+ * @action xprofile_field_after_save
1025
+ *
1026
+ * @param object $field Field object.
1027
+ */
1028
  public function callback_xprofile_field_after_save( $field ) {
1029
  $action = isset( $field->id ) ? 'updated' : 'created';
1030
  $this->field_action( $field, $action );
1031
  }
1032
 
1033
+ /**
1034
+ * Logs field deletions
1035
+ *
1036
+ * @action xprofile_fields_deleted_field
1037
+ *
1038
+ * @param object $field Field object.
1039
+ */
1040
  public function callback_xprofile_fields_deleted_field( $field ) {
1041
  $this->field_action( $field, 'deleted' );
1042
  }
1043
 
1044
+ /**
1045
+ * Logs user profile field group actions
1046
+ *
1047
+ * @param int $group Field group object.
1048
+ * @param string $action Action.
1049
+ * @param array $meta Meta.
1050
+ * @param string $message Message.
1051
+ */
1052
  public function field_group_action( $group, $action, $meta = array(), $message = null ) {
1053
  $replacements = array(
1054
  $group->name,
1056
 
1057
  if ( ! $message ) {
1058
  if ( 'created' === $action ) {
1059
+ /* translators: %s: a user profile field group (e.g. "Appearance") */
1060
  $message = esc_html__( 'Created profile field group "%s"', 'stream' );
1061
  } elseif ( 'updated' === $action ) {
1062
+ /* translators: %s: a user profile field group (e.g. "Appearance") */
1063
  $message = esc_html__( 'Updated profile field group "%s"', 'stream' );
1064
  } elseif ( 'deleted' === $action ) {
1065
+ /* translators: %s: a user profile field group (e.g. "Appearance") */
1066
  $message = esc_html__( 'Deleted profile field group "%s"', 'stream' );
1067
  } else {
1068
  return;
1087
  );
1088
  }
1089
 
1090
+ /**
1091
+ * Logs field group writes
1092
+ *
1093
+ * @action xprofile_group_after_save
1094
+ *
1095
+ * @param object $group Field group.
1096
+ */
1097
  public function callback_xprofile_group_after_save( $group ) {
1098
  global $wpdb;
1099
+ /**
1100
+ * A bit hacky, due to inconsistency with BP action scheme,
1101
+ * see callback_xprofile_field_after_save for correct behavior.
1102
+ */
1103
  $action = ( $group->id === $wpdb->insert_id ) ? 'created' : 'updated';
1104
  $this->field_group_action( $group, $action );
1105
  }
1106
 
1107
+ /**
1108
+ * Logs field group deletions
1109
+ *
1110
+ * @action xprofile_groups_deleted_group
1111
+ *
1112
+ * @param object $group Field group object.
1113
+ */
1114
  public function callback_xprofile_groups_deleted_group( $group ) {
1115
  $this->field_group_action( $group, 'deleted' );
1116
  }
1117
 
1118
+ /**
1119
+ * Returns the directory pages
1120
+ *
1121
+ * @return array
1122
+ */
1123
  private function bp_get_directory_pages() {
1124
  $bp = \buddypress();
1125
  $directory_pages = array();
1126
 
1127
+ // Loop through loaded components and collect directories.
1128
  if ( is_array( $bp->loaded_components ) ) {
1129
  foreach ( $bp->loaded_components as $component_slug => $component_id ) {
1130
+ // Only components that need directories should be listed here.
1131
  if ( isset( $bp->{$component_id} ) && ! empty( $bp->{$component_id}->has_directory ) ) {
1132
+ // component->name was introduced in BP 1.5, so we must provide a fallback.
1133
  $directory_pages[ $component_id ] = ! empty( $bp->{$component_id}->name ) ? $bp->{$component_id}->name : ucwords( $component_id );
1134
  }
1135
  }
connectors/class-connector-comments.php CHANGED
@@ -1,6 +1,15 @@
1
  <?php
 
 
 
 
 
 
2
  namespace WP_Stream;
3
 
 
 
 
4
  class Connector_Comments extends Connector {
5
  /**
6
  * Connector slug
@@ -97,7 +106,7 @@ class Connector_Comments extends Connector {
97
  /**
98
  * Return the comment type label for a given comment ID
99
  *
100
- * @param int $comment_id ID of the comment
101
  *
102
  * @return string The comment type label
103
  */
@@ -120,8 +129,8 @@ class Connector_Comments extends Connector {
120
  *
121
  * @filter wp_stream_action_links_{connector}
122
  *
123
- * @param array $links Previous links registered
124
- * @param object $record Stream record
125
  *
126
  * @return array Action links
127
  */
@@ -163,8 +172,8 @@ class Connector_Comments extends Connector {
163
  * name and e-mail or that users be logged in to comment. In either case it
164
  * will try to see if the e-mail provided does belong to a registered user.
165
  *
166
- * @param object|int $comment A comment object or comment ID
167
- * @param string $field What field you want to return
168
  *
169
  * @return int|string $output User ID or user display name
170
  */
@@ -205,8 +214,8 @@ class Connector_Comments extends Connector {
205
  *
206
  * @action comment_flood_trigger
207
  *
208
- * @param string $time_lastcomment
209
- * @param string $time_newcomment
210
  */
211
  public function callback_comment_flood_trigger( $time_lastcomment, $time_newcomment ) {
212
  $options = wp_stream_get_instance()->settings->options;
@@ -227,7 +236,7 @@ class Connector_Comments extends Connector {
227
  }
228
 
229
  $this->log(
230
- // translators: Placeholder refers to a username (e.g. "administrator")
231
  __( 'Comment flooding by %s detected and prevented', 'stream' ),
232
  compact( 'user_name', 'user_id', 'time_lastcomment', 'time_newcomment' ),
233
  null,
@@ -241,8 +250,8 @@ class Connector_Comments extends Connector {
241
  *
242
  * @action wp_insert_comment
243
  *
244
- * @param int $comment_id
245
- * @param object $comment
246
  */
247
  public function callback_wp_insert_comment( $comment_id, $comment ) {
248
  if ( in_array( $comment->comment_type, $this->get_ignored_comment_types(), true ) ) {
@@ -258,7 +267,7 @@ class Connector_Comments extends Connector {
258
  $comment_status = ( 1 === $comment->comment_approved ) ? esc_html__( 'approved automatically', 'stream' ) : esc_html__( 'pending approval', 'stream' );
259
  $is_spam = false;
260
 
261
- // Auto-marked spam comments
262
  $options = wp_stream_get_instance()->settings->options;
263
  $ak_tracking = isset( $options['advanced_akismet_tracking'] ) ? $options['advanced_akismet_tracking'] : false;
264
 
@@ -276,7 +285,7 @@ class Connector_Comments extends Connector {
276
  $parent_user_name = get_comment_author( $comment->comment_parent );
277
 
278
  $this->log(
279
- // translators: Placeholders refer to a parent comment's author, a comment author, a post title, a comment status, and a comment type
280
  _x(
281
  'Reply to %1$s\'s %5$s by %2$s on %3$s %4$s',
282
  "1: Parent comment's author, 2: Comment author, 3: Post title, 4: Comment status, 5: Comment type",
@@ -290,7 +299,7 @@ class Connector_Comments extends Connector {
290
  );
291
  } else {
292
  $this->log(
293
- // translators: Placeholders refer to a comment author, a post title, a comment status, and a comment type
294
  _x(
295
  'New %4$s by %1$s on %2$s %3$s',
296
  '1: Comment author, 2: Post title 3: Comment status, 4: Comment type',
@@ -310,7 +319,7 @@ class Connector_Comments extends Connector {
310
  *
311
  * @action edit_comment
312
  *
313
- * @param int $comment_id
314
  */
315
  public function callback_edit_comment( $comment_id ) {
316
  $comment = get_comment( $comment_id );
@@ -328,7 +337,7 @@ class Connector_Comments extends Connector {
328
  $comment_type = mb_strtolower( $this->get_comment_type_label( $comment_id ) );
329
 
330
  $this->log(
331
- // translators: Placeholders refer to a comment author, a post title, and a comment type
332
  _x(
333
  '%1$s\'s %3$s on %2$s edited',
334
  '1: Comment author, 2: Post title, 3: Comment type',
@@ -346,7 +355,7 @@ class Connector_Comments extends Connector {
346
  *
347
  * @action before_delete_post
348
  *
349
- * @param int $post_id
350
  */
351
  public function callback_before_delete_post( $post_id ) {
352
  if ( wp_is_post_revision( $post_id ) ) {
@@ -361,7 +370,7 @@ class Connector_Comments extends Connector {
361
  *
362
  * @action deleted_post
363
  *
364
- * @param int $post_id
365
  */
366
  public function callback_deleted_post( $post_id ) {
367
  if ( wp_is_post_revision( $post_id ) ) {
@@ -376,7 +385,7 @@ class Connector_Comments extends Connector {
376
  *
377
  * @action delete_comment
378
  *
379
- * @param int $comment_id
380
  */
381
  public function callback_delete_comment( $comment_id ) {
382
  $comment = get_comment( $comment_id );
@@ -398,7 +407,7 @@ class Connector_Comments extends Connector {
398
  }
399
 
400
  $this->log(
401
- // translators: Placeholders refer to a comment author, a post title, and a comment type
402
  _x(
403
  '%1$s\'s %3$s on %2$s deleted permanently',
404
  '1: Comment author, 2: Post title, 3: Comment type',
@@ -416,7 +425,7 @@ class Connector_Comments extends Connector {
416
  *
417
  * @action trash_comment
418
  *
419
- * @param int $comment_id
420
  */
421
  public function callback_trash_comment( $comment_id ) {
422
  $comment = get_comment( $comment_id );
@@ -434,7 +443,7 @@ class Connector_Comments extends Connector {
434
  $comment_type = mb_strtolower( $this->get_comment_type_label( $comment_id ) );
435
 
436
  $this->log(
437
- // translators: Placeholders refer to a comment author, a post title, and a comment type
438
  _x(
439
  '%1$s\'s %3$s on %2$s trashed',
440
  '1: Comment author, 2: Post title, 3: Comment type',
@@ -452,7 +461,7 @@ class Connector_Comments extends Connector {
452
  *
453
  * @action untrash_comment
454
  *
455
- * @param int $comment_id
456
  */
457
  public function callback_untrash_comment( $comment_id ) {
458
  $comment = get_comment( $comment_id );
@@ -470,7 +479,7 @@ class Connector_Comments extends Connector {
470
  $comment_type = mb_strtolower( $this->get_comment_type_label( $comment_id ) );
471
 
472
  $this->log(
473
- // translators: Placeholders refer to a comment author, a post title, and a comment type
474
  _x(
475
  '%1$s\'s %3$s on %2$s restored',
476
  '1: Comment author, 2: Post title, 3: Comment type',
@@ -488,7 +497,7 @@ class Connector_Comments extends Connector {
488
  *
489
  * @action spam_comment
490
  *
491
- * @param int $comment_id
492
  */
493
  public function callback_spam_comment( $comment_id ) {
494
  $comment = get_comment( $comment_id );
@@ -506,7 +515,7 @@ class Connector_Comments extends Connector {
506
  $comment_type = mb_strtolower( $this->get_comment_type_label( $comment_id ) );
507
 
508
  $this->log(
509
- // translators: Placeholders refer to a comment author, a post title, and a comment type
510
  _x(
511
  '%1$s\'s %3$s on %2$s marked as spam',
512
  '1: Comment author, 2: Post title, 3: Comment type',
@@ -524,7 +533,7 @@ class Connector_Comments extends Connector {
524
  *
525
  * @action unspam_comment
526
  *
527
- * @param int $comment_id
528
  */
529
  public function callback_unspam_comment( $comment_id ) {
530
  $comment = get_comment( $comment_id );
@@ -542,7 +551,7 @@ class Connector_Comments extends Connector {
542
  $comment_type = mb_strtolower( $this->get_comment_type_label( $comment_id ) );
543
 
544
  $this->log(
545
- // translators: Placeholders refer to a comment author, a post title, and a comment type
546
  _x(
547
  '%1$s\'s %3$s on %2$s unmarked as spam',
548
  '1: Comment author, 2: Post title, 3: Comment type',
@@ -560,9 +569,9 @@ class Connector_Comments extends Connector {
560
  *
561
  * @action transition_comment_status
562
  *
563
- * @param string $new_status
564
- * @param string $old_status
565
- * @param object $comment
566
  */
567
  public function callback_transition_comment_status( $new_status, $old_status, $comment ) {
568
  if ( in_array( $comment->comment_type, $this->get_ignored_comment_types(), true ) ) {
@@ -582,7 +591,7 @@ class Connector_Comments extends Connector {
582
  $comment_type = get_comment_type( $comment->comment_ID );
583
 
584
  $this->log(
585
- // translators: Placeholders refer to a comment author, a post title, and a comment type
586
  _x(
587
  '%1$s\'s %3$s %2$s',
588
  'Comment status transition. 1: Comment author, 2: Post title, 3: Comment type',
@@ -600,7 +609,7 @@ class Connector_Comments extends Connector {
600
  *
601
  * @action comment_duplicate_trigger
602
  *
603
- * @param array $comment_data
604
  */
605
  public function callback_comment_duplicate_trigger( $comment_data ) {
606
  global $wpdb;
@@ -622,7 +631,7 @@ class Connector_Comments extends Connector {
622
  $comment_type = mb_strtolower( $this->get_comment_type_label( $comment_id ) );
623
 
624
  $this->log(
625
- // translators: Placeholders refer to a comment author, a post title, and a comment type
626
  _x(
627
  'Duplicate %3$s by %1$s prevented on %2$s',
628
  '1: Comment author, 2: Post title, 3: Comment type',
1
  <?php
2
+ /**
3
+ * Connector for Comments
4
+ *
5
+ * @package WP_Stream
6
+ */
7
+
8
  namespace WP_Stream;
9
 
10
+ /**
11
+ * Class - Connector_Comments
12
+ */
13
  class Connector_Comments extends Connector {
14
  /**
15
  * Connector slug
106
  /**
107
  * Return the comment type label for a given comment ID
108
  *
109
+ * @param int $comment_id ID of the comment.
110
  *
111
  * @return string The comment type label
112
  */
129
  *
130
  * @filter wp_stream_action_links_{connector}
131
  *
132
+ * @param array $links Previous links registered.
133
+ * @param object $record Stream record.
134
  *
135
  * @return array Action links
136
  */
172
  * name and e-mail or that users be logged in to comment. In either case it
173
  * will try to see if the e-mail provided does belong to a registered user.
174
  *
175
+ * @param object|int $comment A comment object or comment ID.
176
+ * @param string $field What field you want to return.
177
  *
178
  * @return int|string $output User ID or user display name
179
  */
214
  *
215
  * @action comment_flood_trigger
216
  *
217
+ * @param string $time_lastcomment Time of last comment before block.
218
+ * @param string $time_newcomment Time of first comment after block.
219
  */
220
  public function callback_comment_flood_trigger( $time_lastcomment, $time_newcomment ) {
221
  $options = wp_stream_get_instance()->settings->options;
236
  }
237
 
238
  $this->log(
239
+ /* translators: %s: a username (e.g. "administrator") */
240
  __( 'Comment flooding by %s detected and prevented', 'stream' ),
241
  compact( 'user_name', 'user_id', 'time_lastcomment', 'time_newcomment' ),
242
  null,
250
  *
251
  * @action wp_insert_comment
252
  *
253
+ * @param int $comment_id Comment ID.
254
+ * @param WP_Comment $comment Comment object.
255
  */
256
  public function callback_wp_insert_comment( $comment_id, $comment ) {
257
  if ( in_array( $comment->comment_type, $this->get_ignored_comment_types(), true ) ) {
267
  $comment_status = ( 1 === $comment->comment_approved ) ? esc_html__( 'approved automatically', 'stream' ) : esc_html__( 'pending approval', 'stream' );
268
  $is_spam = false;
269
 
270
+ // Auto-marked spam comments.
271
  $options = wp_stream_get_instance()->settings->options;
272
  $ak_tracking = isset( $options['advanced_akismet_tracking'] ) ? $options['advanced_akismet_tracking'] : false;
273
 
285
  $parent_user_name = get_comment_author( $comment->comment_parent );
286
 
287
  $this->log(
288
+ /* translators: %1$s: a parent comment's author, %2$s: a comment author, %3$s: a post title, %4$s: a comment status, %5$s: a comment type */
289
  _x(
290
  'Reply to %1$s\'s %5$s by %2$s on %3$s %4$s',
291
  "1: Parent comment's author, 2: Comment author, 3: Post title, 4: Comment status, 5: Comment type",
299
  );
300
  } else {
301
  $this->log(
302
+ /* translators: %1$s: a comment author, %2$s: a post title, %3$s: a comment status, %4$s: and a comment type */
303
  _x(
304
  'New %4$s by %1$s on %2$s %3$s',
305
  '1: Comment author, 2: Post title 3: Comment status, 4: Comment type',
319
  *
320
  * @action edit_comment
321
  *
322
+ * @param int $comment_id Comment ID.
323
  */
324
  public function callback_edit_comment( $comment_id ) {
325
  $comment = get_comment( $comment_id );
337
  $comment_type = mb_strtolower( $this->get_comment_type_label( $comment_id ) );
338
 
339
  $this->log(
340
+ /* translators: %1$s: a comment author, %2$s: a post title, %3$s: a comment type */
341
  _x(
342
  '%1$s\'s %3$s on %2$s edited',
343
  '1: Comment author, 2: Post title, 3: Comment type',
355
  *
356
  * @action before_delete_post
357
  *
358
+ * @param int $post_id Post ID.
359
  */
360
  public function callback_before_delete_post( $post_id ) {
361
  if ( wp_is_post_revision( $post_id ) ) {
370
  *
371
  * @action deleted_post
372
  *
373
+ * @param int $post_id Post ID.
374
  */
375
  public function callback_deleted_post( $post_id ) {
376
  if ( wp_is_post_revision( $post_id ) ) {
385
  *
386
  * @action delete_comment
387
  *
388
+ * @param int $comment_id Comment ID.
389
  */
390
  public function callback_delete_comment( $comment_id ) {
391
  $comment = get_comment( $comment_id );
407
  }
408
 
409
  $this->log(
410
+ /* translators: %1$s: a comment author, %2$s: a post title, %3$s: a comment type */
411
  _x(
412
  '%1$s\'s %3$s on %2$s deleted permanently',
413
  '1: Comment author, 2: Post title, 3: Comment type',
425
  *
426
  * @action trash_comment
427
  *
428
+ * @param int $comment_id Comment ID.
429
  */
430
  public function callback_trash_comment( $comment_id ) {
431
  $comment = get_comment( $comment_id );
443
  $comment_type = mb_strtolower( $this->get_comment_type_label( $comment_id ) );
444
 
445
  $this->log(
446
+ /* translators: %1$s: a comment author, %2$s a post title, %3$s a comment type */
447
  _x(
448
  '%1$s\'s %3$s on %2$s trashed',
449
  '1: Comment author, 2: Post title, 3: Comment type',
461
  *
462
  * @action untrash_comment
463
  *
464
+ * @param int $comment_id Comment ID.
465
  */
466
  public function callback_untrash_comment( $comment_id ) {
467
  $comment = get_comment( $comment_id );
479
  $comment_type = mb_strtolower( $this->get_comment_type_label( $comment_id ) );
480
 
481
  $this->log(
482
+ /* translators: %1$s: a comment author, %2$s: a post title, %3$s: a comment type */
483
  _x(
484
  '%1$s\'s %3$s on %2$s restored',
485
  '1: Comment author, 2: Post title, 3: Comment type',
497
  *
498
  * @action spam_comment
499
  *
500
+ * @param int $comment_id Comment ID.
501
  */
502
  public function callback_spam_comment( $comment_id ) {
503
  $comment = get_comment( $comment_id );
515
  $comment_type = mb_strtolower( $this->get_comment_type_label( $comment_id ) );
516
 
517
  $this->log(
518
+ /* translators: %1$s: a comment author, %2$s: a post title, %3$s: a comment type */
519
  _x(
520
  '%1$s\'s %3$s on %2$s marked as spam',
521
  '1: Comment author, 2: Post title, 3: Comment type',
533
  *
534
  * @action unspam_comment
535
  *
536
+ * @param int $comment_id Comment ID.
537
  */
538
  public function callback_unspam_comment( $comment_id ) {
539
  $comment = get_comment( $comment_id );
551
  $comment_type = mb_strtolower( $this->get_comment_type_label( $comment_id ) );
552
 
553
  $this->log(
554
+ /* translators: %1$s: a comment author, %2$s: a post title, %3$s: a comment type */
555
  _x(
556
  '%1$s\'s %3$s on %2$s unmarked as spam',
557
  '1: Comment author, 2: Post title, 3: Comment type',
569
  *
570
  * @action transition_comment_status
571
  *
572
+ * @param string $new_status New comment status.
573
+ * @param string $old_status Old comment status.
574
+ * @param WP_Comment $comment Comment object.
575
  */
576
  public function callback_transition_comment_status( $new_status, $old_status, $comment ) {
577
  if ( in_array( $comment->comment_type, $this->get_ignored_comment_types(), true ) ) {
591
  $comment_type = get_comment_type( $comment->comment_ID );
592
 
593
  $this->log(
594
+ /* translators: %1$s: a comment author, %2$s: a post title, %3$s: a comment type */
595
  _x(
596
  '%1$s\'s %3$s %2$s',
597
  'Comment status transition. 1: Comment author, 2: Post title, 3: Comment type',
609
  *
610
  * @action comment_duplicate_trigger
611
  *
612
+ * @param array $comment_data Comment data.
613
  */
614
  public function callback_comment_duplicate_trigger( $comment_data ) {
615
  global $wpdb;
631
  $comment_type = mb_strtolower( $this->get_comment_type_label( $comment_id ) );
632
 
633
  $this->log(
634
+ /* translators: %1$s: a comment author, %2$s: a post title, %3$s: a comment type */
635
  _x(
636
  'Duplicate %3$s by %1$s prevented on %2$s',
637
  '1: Comment author, 2: Post title, 3: Comment type',
connectors/class-connector-edd.php CHANGED
@@ -1,7 +1,15 @@
1
  <?php
 
 
 
 
 
2
 
3
  namespace WP_Stream;
4
 
 
 
 
5
  class Connector_EDD extends Connector {
6
 
7
  /**
@@ -135,7 +143,6 @@ class Connector_EDD extends Connector {
135
  'discounts' => esc_html_x( 'Discounts', 'edd', 'stream' ),
136
  'reports' => esc_html_x( 'Reports', 'edd', 'stream' ),
137
  'api_keys' => esc_html_x( 'API Keys', 'edd', 'stream' ),
138
- // 'payments' => esc_html_x( 'Payments', 'edd', 'stream' ),
139
  );
140
  }
141
 
@@ -144,8 +151,8 @@ class Connector_EDD extends Connector {
144
  *
145
  * @filter wp_stream_action_links_{connector}
146
  *
147
- * @param array $links Previous links registered
148
- * @param object $record Stream record
149
  *
150
  * @return array Action links
151
  */
@@ -157,7 +164,7 @@ class Connector_EDD extends Connector {
157
  $post_type_label = get_post_type_labels( get_post_type_object( 'edd_discount' ) )->singular_name;
158
  $base = admin_url( 'edit.php?post_type=download&page=edd-discounts' );
159
 
160
- // translators: Placeholder refers to a post type (e.g. "Post")
161
  $links[ sprintf( esc_html__( 'Edit %s', 'stream' ), $post_type_label ) ] = add_query_arg(
162
  array(
163
  'edd-action' => 'edit_discount',
@@ -167,7 +174,7 @@ class Connector_EDD extends Connector {
167
  );
168
 
169
  if ( 'active' === get_post( $record->object_id )->post_status ) {
170
- // translators: Placeholder refers to a post type (e.g. "Post")
171
  $links[ sprintf( esc_html__( 'Deactivate %s', 'stream' ), $post_type_label ) ] = add_query_arg(
172
  array(
173
  'edd-action' => 'deactivate_discount',
@@ -176,7 +183,7 @@ class Connector_EDD extends Connector {
176
  $base
177
  );
178
  } else {
179
- // translators: Placeholder refers to a post type (e.g. "Post")
180
  $links[ sprintf( esc_html__( 'Activate %s', 'stream' ), $post_type_label ) ] = add_query_arg(
181
  array(
182
  'edd-action' => 'activate_discount',
@@ -194,7 +201,7 @@ class Connector_EDD extends Connector {
194
  true
195
  ) ) {
196
  $tax_label = get_taxonomy_labels( get_taxonomy( $record->context ) )->singular_name;
197
- // translators: Placeholder refers to a taxonomy (e.g. "Category")
198
  $links[ sprintf( esc_html__( 'Edit %s', 'stream' ), $tax_label ) ] = get_edit_term_link( $record->object_id, $record->get_meta( 'taxonomy', true ) );
199
  } elseif ( 'api_keys' === $record->context ) {
200
  $user = new \WP_User( $record->object_id );
@@ -235,6 +242,9 @@ class Connector_EDD extends Connector {
235
  return $links;
236
  }
237
 
 
 
 
238
  public function register() {
239
  parent::register();
240
 
@@ -245,30 +255,73 @@ class Connector_EDD extends Connector {
245
  );
246
  }
247
 
 
 
 
 
 
 
 
248
  public function callback_update_option( $option, $old, $new ) {
249
  $this->check( $option, $old, $new );
250
  }
251
 
 
 
 
 
 
 
252
  public function callback_add_option( $option, $val ) {
253
  $this->check( $option, null, $val );
254
  }
255
 
 
 
 
 
 
256
  public function callback_delete_option( $option ) {
257
  $this->check( $option, null, null );
258
  }
259
 
 
 
 
 
 
 
 
260
  public function callback_update_site_option( $option, $old, $new ) {
261
  $this->check( $option, $old, $new );
262
  }
263
 
 
 
 
 
 
 
264
  public function callback_add_site_option( $option, $val ) {
265
  $this->check( $option, null, $val );
266
  }
267
 
 
 
 
 
 
268
  public function callback_delete_site_option( $option ) {
269
  $this->check( $option, null, null );
270
  }
271
 
 
 
 
 
 
 
 
272
  public function check( $option, $old_value, $new_value ) {
273
  if ( ! array_key_exists( $option, $this->options ) ) {
274
  return;
@@ -291,7 +344,7 @@ class Connector_EDD extends Connector {
291
  $context = isset( $data['context'] ) ? $data['context'] : 'settings';
292
 
293
  $this->log(
294
- // translators: Placeholder refers to a setting title (e.g. "Language")
295
  __( '"%s" setting updated', 'stream' ),
296
  compact( 'option_title', 'option', 'old_value', 'new_value' ),
297
  null,
@@ -301,6 +354,12 @@ class Connector_EDD extends Connector {
301
  }
302
  }
303
 
 
 
 
 
 
 
304
  public function check_edd_settings( $old_value, $new_value ) {
305
  $options = array();
306
 
@@ -312,7 +371,7 @@ class Connector_EDD extends Connector {
312
  $options[ $field_key ] = $field_value;
313
  }
314
 
315
- // TODO: Check this exists first
316
  $settings = \edd_get_registered_settings();
317
 
318
  foreach ( $options as $option => $option_value ) {
@@ -337,7 +396,7 @@ class Connector_EDD extends Connector {
337
  }
338
 
339
  $this->log(
340
- // translators: Placeholder refers to a setting title (e.g. "Language")
341
  __( '"%s" setting updated', 'stream' ),
342
  array(
343
  'option_title' => $field['name'],
@@ -356,7 +415,7 @@ class Connector_EDD extends Connector {
356
  /**
357
  * Override connector log for our own Settings / Actions
358
  *
359
- * @param array $data
360
  *
361
  * @return array|bool
362
  */
@@ -366,31 +425,31 @@ class Connector_EDD extends Connector {
366
  }
367
 
368
  if ( 'posts' === $data['connector'] && 'download' === $data['context'] ) {
369
- // Download posts operations
370
  $data['context'] = 'downloads';
371
  $data['connector'] = $this->name;
372
  } elseif ( 'posts' === $data['connector'] && 'edd_discount' === $data['context'] ) {
373
- // Discount posts operations
374
  if ( $this->is_discount_status_change ) {
375
  return false;
376
  }
377
 
378
  if ( 'deleted' === $data['action'] ) {
379
- // translators: Placeholder refers to a discount title (e.g. "Mother's Day")
380
- $data['message'] = esc_html__( '"%1s" discount deleted', 'stream' );
381
  }
382
 
383
  $data['context'] = 'discounts';
384
  $data['connector'] = $this->name;
385
  } elseif ( 'posts' === $data['connector'] && 'edd_payment' === $data['context'] ) {
386
- // Payment posts operations
387
  return false; // Do not track payments, they're well logged!
388
  } elseif ( 'posts' === $data['connector'] && 'edd_log' === $data['context'] ) {
389
- // Logging operations
390
- return false; // Do not track notes, because they're basically logs
391
  } elseif ( 'comments' === $data['connector'] && 'edd_payment' === $data['context'] ) {
392
- // Payment notes ( comments ) operations
393
- return false; // Do not track notes, because they're basically logs
394
  } elseif ( 'taxonomies' === $data['connector'] && 'download_category' === $data['context'] ) {
395
  $data['connector'] = $this->name;
396
  } elseif ( 'taxonomies' === $data['connector'] && 'download_tag' === $data['context'] ) {
@@ -404,12 +463,21 @@ class Connector_EDD extends Connector {
404
  return $data;
405
  }
406
 
 
 
 
 
 
 
 
 
 
407
  public function callback_edd_pre_update_discount_status( $code_id, $new_status ) {
408
  $this->is_discount_status_change = true;
409
 
410
  $this->log(
411
  sprintf(
412
- // translators: Placeholders refer to a discount title, and a status (e.g. "Mother's Day", "activated")
413
  __( '"%1$s" discount %2$s', 'stream' ),
414
  get_post( $code_id )->post_title,
415
  'active' === $new_status ? esc_html__( 'activated', 'stream' ) : esc_html__( 'deactivated', 'stream' )
@@ -423,27 +491,56 @@ class Connector_EDD extends Connector {
423
  'updated'
424
  );
425
  }
426
-
 
 
 
 
427
  private function callback_edd_generate_pdf() {
428
  $this->report_generated( 'pdf' );
429
  }
430
 
 
 
 
 
 
431
  public function callback_edd_earnings_export() {
432
  $this->report_generated( 'earnings' );
433
  }
434
 
 
 
 
 
 
435
  public function callback_edd_payment_export() {
436
  $this->report_generated( 'payments' );
437
  }
438
 
 
 
 
 
 
439
  public function callback_edd_email_export() {
440
  $this->report_generated( 'emails' );
441
  }
442
 
 
 
 
 
 
443
  public function callback_edd_downloads_history_export() {
444
  $this->report_generated( 'download-history' );
445
  }
446
 
 
 
 
 
 
447
  private function report_generated( $type ) {
448
  $label = '';
449
 
@@ -461,7 +558,7 @@ class Connector_EDD extends Connector {
461
 
462
  $this->log(
463
  sprintf(
464
- // translators: Placeholder refers to a report title (e.g. "Sales and Earnings")
465
  __( 'Generated %s report', 'stream' ),
466
  $label
467
  ),
@@ -474,6 +571,11 @@ class Connector_EDD extends Connector {
474
  );
475
  }
476
 
 
 
 
 
 
477
  public function callback_edd_export_settings() {
478
  $this->log(
479
  __( 'Exported Settings', 'stream' ),
@@ -484,6 +586,11 @@ class Connector_EDD extends Connector {
484
  );
485
  }
486
 
 
 
 
 
 
487
  public function callback_edd_import_settings() {
488
  $this->log(
489
  __( 'Imported Settings', 'stream' ),
@@ -494,19 +601,56 @@ class Connector_EDD extends Connector {
494
  );
495
  }
496
 
 
 
 
 
 
 
 
 
 
 
497
  public function callback_update_user_meta( $meta_id, $object_id, $meta_key, $_meta_value ) {
498
  unset( $meta_id );
499
  $this->meta( $object_id, $meta_key, $_meta_value );
500
  }
501
 
 
 
 
 
 
 
 
 
 
502
  public function callback_add_user_meta( $object_id, $meta_key, $_meta_value ) {
503
  $this->meta( $object_id, $meta_key, $_meta_value, true );
504
  }
505
 
 
 
 
 
 
 
 
 
 
 
506
  public function callback_delete_user_meta( $meta_id, $object_id, $meta_key, $_meta_value ) {
507
  $this->meta( $object_id, $meta_key, null );
508
  }
509
 
 
 
 
 
 
 
 
 
510
  public function meta( $object_id, $key, $value, $is_add = false ) {
511
  if ( ! in_array( $key, $this->user_meta, true ) ) {
512
  return false;
@@ -529,6 +673,13 @@ class Connector_EDD extends Connector {
529
  );
530
  }
531
 
 
 
 
 
 
 
 
532
  private function meta_edd_user_public_key( $user_id, $value, $is_add = false ) {
533
  if ( is_null( $value ) ) {
534
  $action = 'revoked';
@@ -543,7 +694,7 @@ class Connector_EDD extends Connector {
543
 
544
  $this->log(
545
  sprintf(
546
- // translators: Placeholder refers to a status (e.g. "revoked")
547
  __( 'User API Key %s', 'stream' ),
548
  $action_title
549
  ),
1
  <?php
2
+ /**
3
+ * Connector for Easy Digital Downloads
4
+ *
5
+ * @package WP_Stream
6
+ */
7
 
8
  namespace WP_Stream;
9
 
10
+ /**
11
+ * Class - Connector_EDD
12
+ */
13
  class Connector_EDD extends Connector {
14
 
15
  /**
143
  'discounts' => esc_html_x( 'Discounts', 'edd', 'stream' ),
144
  'reports' => esc_html_x( 'Reports', 'edd', 'stream' ),
145
  'api_keys' => esc_html_x( 'API Keys', 'edd', 'stream' ),
 
146
  );
147
  }
148
 
151
  *
152
  * @filter wp_stream_action_links_{connector}
153
  *
154
+ * @param array $links Previous links registered.
155
+ * @param object $record Stream record.
156
  *
157
  * @return array Action links
158
  */
164
  $post_type_label = get_post_type_labels( get_post_type_object( 'edd_discount' ) )->singular_name;
165
  $base = admin_url( 'edit.php?post_type=download&page=edd-discounts' );
166
 
167
+ /* translators: %s: a post type (e.g. "Post") */
168
  $links[ sprintf( esc_html__( 'Edit %s', 'stream' ), $post_type_label ) ] = add_query_arg(
169
  array(
170
  'edd-action' => 'edit_discount',
174
  );
175
 
176
  if ( 'active' === get_post( $record->object_id )->post_status ) {
177
+ /* translators: %s: a post type (e.g. "Post") */
178
  $links[ sprintf( esc_html__( 'Deactivate %s', 'stream' ), $post_type_label ) ] = add_query_arg(
179
  array(
180
  'edd-action' => 'deactivate_discount',
183
  $base
184
  );
185
  } else {
186
+ /* translators: %s a post type (e.g. "Post") */
187
  $links[ sprintf( esc_html__( 'Activate %s', 'stream' ), $post_type_label ) ] = add_query_arg(
188
  array(
189
  'edd-action' => 'activate_discount',
201
  true
202
  ) ) {
203
  $tax_label = get_taxonomy_labels( get_taxonomy( $record->context ) )->singular_name;
204
+ /* translators: %s a taxonomy (e.g. "Category") */
205
  $links[ sprintf( esc_html__( 'Edit %s', 'stream' ), $tax_label ) ] = get_edit_term_link( $record->object_id, $record->get_meta( 'taxonomy', true ) );
206
  } elseif ( 'api_keys' === $record->context ) {
207
  $user = new \WP_User( $record->object_id );
242
  return $links;
243
  }
244
 
245
+ /**
246
+ * Register the connector
247
+ */
248
  public function register() {
249
  parent::register();
250
 
255
  );
256
  }
257
 
258
+ /**
259
+ * Track EDD-specific option changes.
260
+ *
261
+ * @param string $option Option key.
262
+ * @param string $old Old value.
263
+ * @param string $new New value.
264
+ */
265
  public function callback_update_option( $option, $old, $new ) {
266
  $this->check( $option, $old, $new );
267
  }
268
 
269
+ /**
270
+ * Track EDD-specific option creations.
271
+ *
272
+ * @param string $option Option key.
273
+ * @param string $val Value.
274
+ */
275
  public function callback_add_option( $option, $val ) {
276
  $this->check( $option, null, $val );
277
  }
278
 
279
+ /**
280
+ * Track EDD-specific option deletions.
281
+ *
282
+ * @param string $option Option key.
283
+ */
284
  public function callback_delete_option( $option ) {
285
  $this->check( $option, null, null );
286
  }
287
 
288
+ /**
289
+ * Track EDD-specific site option changes
290
+ *
291
+ * @param string $option Option key.
292
+ * @param string $old Old value.
293
+ * @param string $new New value.
294
+ */
295
  public function callback_update_site_option( $option, $old, $new ) {
296
  $this->check( $option, $old, $new );
297
  }
298
 
299
+ /**
300
+ * Track EDD-specific site option creations.
301
+ *
302
+ * @param string $option Option key.
303
+ * @param string $val Value.
304
+ */
305
  public function callback_add_site_option( $option, $val ) {
306
  $this->check( $option, null, $val );
307
  }
308
 
309
+ /**
310
+ * Track EDD-specific site option deletions.
311
+ *
312
+ * @param string $option Option key.
313
+ */
314
  public function callback_delete_site_option( $option ) {
315
  $this->check( $option, null, null );
316
  }
317
 
318
+ /**
319
+ * Logs EDD-specific (site) option action.
320
+ *
321
+ * @param string $option Option key.
322
+ * @param string $old_value Old value.
323
+ * @param string $new_value New value.
324
+ */
325
  public function check( $option, $old_value, $new_value ) {
326
  if ( ! array_key_exists( $option, $this->options ) ) {
327
  return;
344
  $context = isset( $data['context'] ) ? $data['context'] : 'settings';
345
 
346
  $this->log(
347
+ /* translators: %s: a setting title (e.g. "Language") */
348
  __( '"%s" setting updated', 'stream' ),
349
  compact( 'option_title', 'option', 'old_value', 'new_value' ),
350
  null,
354
  }
355
  }
356
 
357
+ /**
358
+ * Logs EDD setting changes.
359
+ *
360
+ * @param string $old_value Old value.
361
+ * @param string $new_value New value.
362
+ */
363
  public function check_edd_settings( $old_value, $new_value ) {
364
  $options = array();
365
 
371
  $options[ $field_key ] = $field_value;
372
  }
373
 
374
+ // TODO: Check this exists first.
375
  $settings = \edd_get_registered_settings();
376
 
377
  foreach ( $options as $option => $option_value ) {
396
  }
397
 
398
  $this->log(
399
+ /* translators: %s: a setting title (e.g. "Language") */
400
  __( '"%s" setting updated', 'stream' ),
401
  array(
402
  'option_title' => $field['name'],
415
  /**
416
  * Override connector log for our own Settings / Actions
417
  *
418
+ * @param array $data Record data.
419
  *
420
  * @return array|bool
421
  */
425
  }
426
 
427
  if ( 'posts' === $data['connector'] && 'download' === $data['context'] ) {
428
+ // Download posts operations.
429
  $data['context'] = 'downloads';
430
  $data['connector'] = $this->name;
431
  } elseif ( 'posts' === $data['connector'] && 'edd_discount' === $data['context'] ) {
432
+ // Discount posts operations.
433
  if ( $this->is_discount_status_change ) {
434
  return false;
435
  }
436
 
437
  if ( 'deleted' === $data['action'] ) {
438
+ /* translators: %s: a discount title (e.g. "Mother's Day") */
439
+ $data['message'] = esc_html__( '"%s" discount deleted', 'stream' );
440
  }
441
 
442
  $data['context'] = 'discounts';
443
  $data['connector'] = $this->name;
444
  } elseif ( 'posts' === $data['connector'] && 'edd_payment' === $data['context'] ) {
445
+ // Payment posts operations.
446
  return false; // Do not track payments, they're well logged!
447
  } elseif ( 'posts' === $data['connector'] && 'edd_log' === $data['context'] ) {
448
+ // Logging operations.
449
+ return false; // Do not track notes, because they're basically logs.
450
  } elseif ( 'comments' === $data['connector'] && 'edd_payment' === $data['context'] ) {
451
+ // Payment notes ( comments ) operations.
452
+ return false; // Do not track notes, because they're basically logs.
453
  } elseif ( 'taxonomies' === $data['connector'] && 'download_category' === $data['context'] ) {
454
  $data['connector'] = $this->name;
455
  } elseif ( 'taxonomies' === $data['connector'] && 'download_tag' === $data['context'] ) {
463
  return $data;
464
  }
465
 
466
+ /**
467
+ * Undocumented function
468
+ *
469
+ * @action edd_pre_update_discount_status
470
+ *
471
+ * @param int $code_id Post ID.
472
+ * @param string $new_status Post status.
473
+ * @return void
474
+ */
475
  public function callback_edd_pre_update_discount_status( $code_id, $new_status ) {
476
  $this->is_discount_status_change = true;
477
 
478
  $this->log(
479
  sprintf(
480
+ /* translators: %1$s: a discount title, %2$s: a status (e.g. "Mother's Day", "activated") */
481
  __( '"%1$s" discount %2$s', 'stream' ),
482
  get_post( $code_id )->post_title,
483
  'active' === $new_status ? esc_html__( 'activated', 'stream' ) : esc_html__( 'deactivated', 'stream' )
491
  'updated'
492
  );
493
  }
494
+ /**
495
+ * Logs PDFs
496
+ *
497
+ * @action edd_generate_pdf
498
+ */
499
  private function callback_edd_generate_pdf() {
500
  $this->report_generated( 'pdf' );
501
  }
502
 
503
+ /**
504
+ * Logs earning reports.
505
+ *
506
+ * @action edd_earnings_export
507
+ */
508
  public function callback_edd_earnings_export() {
509
  $this->report_generated( 'earnings' );
510
  }
511
 
512
+ /**
513
+ * Logs payment reports.
514
+ *
515
+ * @action edd_payment_export
516
+ */
517
  public function callback_edd_payment_export() {
518
  $this->report_generated( 'payments' );
519
  }
520
 
521
+ /**
522
+ * Logs email reports.
523
+ *
524
+ * @action edd_email_export
525
+ */
526
  public function callback_edd_email_export() {
527
  $this->report_generated( 'emails' );
528
  }
529
 
530
+ /**
531
+ * Logs download history reports.
532
+ *
533
+ * @action edd_downloads_history_export
534
+ */
535
  public function callback_edd_downloads_history_export() {
536
  $this->report_generated( 'download-history' );
537
  }
538
 
539
+ /**
540
+ * Logs generated reports.
541
+ *
542
+ * @param string $type Report type.
543
+ */
544
  private function report_generated( $type ) {
545
  $label = '';
546
 
558
 
559
  $this->log(
560
  sprintf(
561
+ /* translators: %s: a report title (e.g. "Sales and Earnings") */
562
  __( 'Generated %s report', 'stream' ),
563
  $label
564
  ),
571
  );
572
  }
573
 
574
+ /**
575
+ * Logs exported settings
576
+ *
577
+ * @action edd_export_settings
578
+ */
579
  public function callback_edd_export_settings() {
580
  $this->log(
581
  __( 'Exported Settings', 'stream' ),
586
  );
587
  }
588
 
589
+ /**
590
+ * Logs imported settings
591
+ *
592
+ * @action edd_import_settings
593
+ */
594
  public function callback_edd_import_settings() {
595
  $this->log(
596
  __( 'Imported Settings', 'stream' ),
601
  );
602
  }
603
 
604
+ /**
605
+ * Logs EDD-specific user meta changes.
606
+ *
607
+ * @action update_user_meta
608
+ *
609
+ * @param int $meta_id Meta ID.
610
+ * @param int $object_id Object ID.
611
+ * @param string $meta_key Meta key.
612
+ * @param string $_meta_value Meta value.
613
+ */
614
  public function callback_update_user_meta( $meta_id, $object_id, $meta_key, $_meta_value ) {
615
  unset( $meta_id );
616
  $this->meta( $object_id, $meta_key, $_meta_value );
617
  }
618
 
619
+ /**
620
+ * Logs EDD-specific user meta creations.
621
+ *
622
+ * @action add_user_meta
623
+ *
624
+ * @param int $object_id Object ID.
625
+ * @param string $meta_key Meta key.
626
+ * @param string $_meta_value Meta value.
627
+ */
628
  public function callback_add_user_meta( $object_id, $meta_key, $_meta_value ) {
629
  $this->meta( $object_id, $meta_key, $_meta_value, true );
630
  }
631
 
632
+ /**
633
+ * Logs EDD-specific user meta deletions.
634
+ *
635
+ * @action delete_user_meta
636
+ *
637
+ * @param int $meta_id Meta ID.
638
+ * @param int $object_id Object ID.
639
+ * @param string $meta_key Meta key.
640
+ * @param string $_meta_value Meta value.
641
+ */
642
  public function callback_delete_user_meta( $meta_id, $object_id, $meta_key, $_meta_value ) {
643
  $this->meta( $object_id, $meta_key, null );
644
  }
645
 
646
+ /**
647
+ * Logs EDD-specific user meta activity.
648
+ *
649
+ * @param int $object_id Object ID.
650
+ * @param string $key Meta key.
651
+ * @param string $value Meta value.
652
+ * @param bool $is_add Is this a new meta?.
653
+ */
654
  public function meta( $object_id, $key, $value, $is_add = false ) {
655
  if ( ! in_array( $key, $this->user_meta, true ) ) {
656
  return false;
673
  );
674
  }
675
 
676
+ /**
677
+ * Logs change to User API key
678
+ *
679
+ * @param int $user_id User ID.
680
+ * @param string $value API Key.
681
+ * @param bool $is_add Is this a new API key.
682
+ */
683
  private function meta_edd_user_public_key( $user_id, $value, $is_add = false ) {
684
  if ( is_null( $value ) ) {
685
  $action = 'revoked';
694
 
695
  $this->log(
696
  sprintf(
697
+ /* translators: %s: a status (e.g. "revoked") */
698
  __( 'User API Key %s', 'stream' ),
699
  $action_title
700
  ),
connectors/class-connector-editor.php CHANGED
@@ -1,6 +1,15 @@
1
  <?php
 
 
 
 
 
 
2
  namespace WP_Stream;
3
 
 
 
 
4
  class Connector_Editor extends Connector {
5
  /**
6
  * Connector slug
@@ -85,8 +94,9 @@ class Connector_Editor extends Connector {
85
  /**
86
  * Get the context based on wp_redirect location
87
  *
88
- * @param string $location The URL of the redirect
89
- * @return string Context slug
 
90
  */
91
  public function get_context( $location ) {
92
  $context = null;
@@ -115,7 +125,7 @@ class Connector_Editor extends Connector {
115
  * @return string Translated string
116
  */
117
  public function get_message() {
118
- // translators: Placeholders refer to a file name, and a theme / plugin name (e.g. "index.php", "Stream")
119
  return _x(
120
  '"%1$s" in "%2$s" updated',
121
  '1: File name, 2: Theme/plugin name',
@@ -128,8 +138,8 @@ class Connector_Editor extends Connector {
128
  *
129
  * @filter wp_stream_action_links_{connector}
130
  *
131
- * @param array $links Previous links registered
132
- * @param object $record Stream record
133
  *
134
  * @return array Action links
135
  */
@@ -209,7 +219,7 @@ class Connector_Editor extends Connector {
209
  /**
210
  * Retrieve theme data needed for the log message
211
  *
212
- * @param string $slug The theme slug (e.g. twentyfourteen)
213
  *
214
  * @return mixed $output Compacted variables
215
  */
@@ -251,8 +261,8 @@ class Connector_Editor extends Connector {
251
  /**
252
  * Retrieve plugin data needed for the log message
253
  *
254
- * @param string $slug The plugin file base name (e.g. akismet/akismet.php)
255
- * @return mixed $output Compacted variables
256
  */
257
  public function get_plugin_data( $slug ) {
258
  $base = null;
@@ -286,11 +296,15 @@ class Connector_Editor extends Connector {
286
  }
287
 
288
  /**
 
 
289
  * @filter wp_redirect
 
 
290
  */
291
  public function log_changes( $location ) {
292
  if ( ! empty( $this->edited_file ) ) {
293
- // TODO: phpcs fix
294
  if ( md5_file( $this->edited_file['file_path'] ) !== $this->edited_file['file_md5'] ) {
295
  $context = $this->get_context( $location );
296
 
1
  <?php
2
+ /**
3
+ * Connector for Editor
4
+ *
5
+ * @package WP_Stream
6
+ */
7
+
8
  namespace WP_Stream;
9
 
10
+ /**
11
+ * Class - Connector_Editor
12
+ */
13
  class Connector_Editor extends Connector {
14
  /**
15
  * Connector slug
94
  /**
95
  * Get the context based on wp_redirect location
96
  *
97
+ * @param string $location The URL of the redirect.
98
+ *
99
+ * @return string Context slug
100
  */
101
  public function get_context( $location ) {
102
  $context = null;
125
  * @return string Translated string
126
  */
127
  public function get_message() {
128
+ /* translators: %1$s: a file name, %2$s: a theme / plugin name (e.g. "index.php", "Stream") */
129
  return _x(
130
  '"%1$s" in "%2$s" updated',
131
  '1: File name, 2: Theme/plugin name',
138
  *
139
  * @filter wp_stream_action_links_{connector}
140
  *
141
+ * @param array $links Previous links registered.
142
+ * @param object $record Stream record.
143
  *
144
  * @return array Action links
145
  */
219
  /**
220
  * Retrieve theme data needed for the log message
221
  *
222
+ * @param string $slug The theme slug (e.g. twentyfourteen).
223
  *
224
  * @return mixed $output Compacted variables
225
  */
261
  /**
262
  * Retrieve plugin data needed for the log message
263
  *
264
+ * @param string $slug The plugin file base name (e.g. akismet/akismet.php).
265
+ * @return mixed $output Compacted variables.
266
  */
267
  public function get_plugin_data( $slug ) {
268
  $base = null;
296
  }
297
 
298
  /**
299
+ * Logs changes
300
+ *
301
  * @filter wp_redirect
302
+ *
303
+ * @param string $location Location.
304
  */
305
  public function log_changes( $location ) {
306
  if ( ! empty( $this->edited_file ) ) {
307
+ // TODO: phpcs fix.
308
  if ( md5_file( $this->edited_file['file_path'] ) !== $this->edited_file['file_md5'] ) {
309
  $context = $this->get_context( $location );
310
 
connectors/class-connector-gravityforms.php CHANGED
@@ -1,6 +1,15 @@
1
  <?php
 
 
 
 
 
 
2
  namespace WP_Stream;
3
 
 
 
 
4
  class Connector_GravityForms extends Connector {
5
  /**
6
  * Connector slug
@@ -130,8 +139,8 @@ class Connector_GravityForms extends Connector {
130
  *
131
  * @filter wp_stream_action_links_{connector}
132
  *
133
- * @param array $links Previous links registered
134
- * @param object $record Stream record
135
  *
136
  * @return array Action links
137
  */
@@ -176,6 +185,9 @@ class Connector_GravityForms extends Connector {
176
  return $links;
177
  }
178
 
 
 
 
179
  public function register() {
180
  parent::register();
181
 
@@ -205,9 +217,8 @@ class Connector_GravityForms extends Connector {
205
  /**
206
  * Track Create/Update actions on Forms
207
  *
208
- * @param array $form
209
- * @param bool $is_new
210
- * @return void
211
  */
212
  public function callback_gform_after_save_form( $form, $is_new ) {
213
  $title = $form['title'];
@@ -215,7 +226,7 @@ class Connector_GravityForms extends Connector {
215
 
216
  $this->log(
217
  sprintf(
218
- // translators: Placeholders refer to a form title, and a status (e.g. "Contact Form", "created")
219
  __( '"%1$s" form %2$s', 'stream' ),
220
  $title,
221
  $is_new ? esc_html__( 'created', 'stream' ) : esc_html__( 'updated', 'stream' )
@@ -234,10 +245,9 @@ class Connector_GravityForms extends Connector {
234
  /**
235
  * Track saving form confirmations
236
  *
237
- * @param array $confirmation
238
- * @param array $form
239
- * @param bool $is_new
240
- * @return array
241
  */
242
  public function callback_gform_pre_confirmation_save( $confirmation, $form, $is_new = true ) {
243
  if ( ! isset( $is_new ) ) {
@@ -246,7 +256,7 @@ class Connector_GravityForms extends Connector {
246
 
247
  $this->log(
248
  sprintf(
249
- // translators: Placeholders refer to a confirmation name, a status, and a form title (e.g. "Email", "created", "Contact Form")
250
  __( '"%1$s" confirmation %2$s for "%3$s"', 'stream' ),
251
  $confirmation['name'],
252
  $is_new ? esc_html__( 'created', 'stream' ) : esc_html__( 'updated', 'stream' ),
@@ -267,9 +277,9 @@ class Connector_GravityForms extends Connector {
267
  /**
268
  * Track saving form notifications
269
  *
270
- * @param array $notification
271
- * @param array $form
272
- * @param bool $is_new
273
  * @return array
274
  */
275
  public function callback_gform_pre_notification_save( $notification, $form, $is_new = true ) {
@@ -279,7 +289,7 @@ class Connector_GravityForms extends Connector {
279
 
280
  $this->log(
281
  sprintf(
282
- // translators: Placeholders refer to a notification name, a status, and a form title (e.g. "Email", "created", "Contact Form")
283
  __( '"%1$s" notification %2$s for "%3$s"', 'stream' ),
284
  $notification['name'],
285
  $is_new ? esc_html__( 'created', 'stream' ) : esc_html__( 'updated', 'stream' ),
@@ -300,14 +310,13 @@ class Connector_GravityForms extends Connector {
300
  /**
301
  * Track deletion of notifications
302
  *
303
- * @param array $notification
304
- * @param array $form
305
- * @return void
306
  */
307
  public function callback_gform_pre_notification_deleted( $notification, $form ) {
308
  $this->log(
309
  sprintf(
310
- // translators: Placeholders refer to a notification name, and a form title (e.g. "Email", "Contact Form")
311
  __( '"%1$s" notification deleted from "%2$s"', 'stream' ),
312
  $notification['name'],
313
  $form['title']
@@ -325,14 +334,13 @@ class Connector_GravityForms extends Connector {
325
  /**
326
  * Track deletion of confirmations
327
  *
328
- * @param array $confirmation
329
- * @param array $form
330
- * @return void
331
  */
332
  public function callback_gform_pre_confirmation_deleted( $confirmation, $form ) {
333
  $this->log(
334
  sprintf(
335
- // translators: Placeholders refer to a confirmation name, and a form title (e.g. "Email", "Contact Form")
336
  __( '"%1$s" confirmation deleted from "%2$s"', 'stream' ),
337
  $confirmation['name'],
338
  $form['title']
@@ -350,15 +358,14 @@ class Connector_GravityForms extends Connector {
350
  /**
351
  * Track status change of confirmations
352
  *
353
- * @param array $confirmation
354
- * @param array $form
355
- * @param bool $is_active
356
- * @return void
357
  */
358
  public function callback_gform_confirmation_status( $confirmation, $form, $is_active ) {
359
  $this->log(
360
  sprintf(
361
- // translators: Placeholders refer to a confirmation name, a status, and a form title (e.g. "Email", "activated", "Contact Form")
362
  __( '"%1$s" confirmation %2$s from "%3$s"', 'stream' ),
363
  $confirmation['name'],
364
  $is_active ? esc_html__( 'activated', 'stream' ) : esc_html__( 'deactivated', 'stream' ),
@@ -378,15 +385,14 @@ class Connector_GravityForms extends Connector {
378
  /**
379
  * Track status change of notifications
380
  *
381
- * @param array $notification
382
- * @param array $form
383
- * @param bool $is_active
384
- * @return void
385
  */
386
  public function callback_gform_notification_status( $notification, $form, $is_active ) {
387
  $this->log(
388
  sprintf(
389
- // translators: Placeholders refer to a notification name, a status, and a form title (e.g. "Email", "activated", "Contact Form")
390
  __( '"%1$s" notification %2$s from "%3$s"', 'stream' ),
391
  $notification['name'],
392
  $is_active ? esc_html__( 'activated', 'stream' ) : esc_html__( 'deactivated', 'stream' ),
@@ -403,30 +409,73 @@ class Connector_GravityForms extends Connector {
403
  );
404
  }
405
 
 
 
 
 
 
 
 
406
  public function callback_update_option( $option, $old, $new ) {
407
  $this->check( $option, $old, $new );
408
  }
409
 
 
 
 
 
 
 
410
  public function callback_add_option( $option, $val ) {
411
  $this->check( $option, null, $val );
412
  }
413
 
 
 
 
 
 
414
  public function callback_delete_option( $option ) {
415
  $this->check( $option, null, null );
416
  }
417
 
 
 
 
 
 
 
 
418
  public function callback_update_site_option( $option, $old, $new ) {
419
  $this->check( $option, $old, $new );
420
  }
421
 
 
 
 
 
 
 
422
  public function callback_add_site_option( $option, $val ) {
423
  $this->check( $option, null, $val );
424
  }
425
 
 
 
 
 
 
426
  public function callback_delete_site_option( $option ) {
427
  $this->check( $option, null, null );
428
  }
429
 
 
 
 
 
 
 
 
430
  public function check( $option, $old_value, $new_value ) {
431
  if ( ! array_key_exists( $option, $this->options ) ) {
432
  return;
@@ -440,7 +489,7 @@ class Connector_GravityForms extends Connector {
440
  $context = isset( $data['context'] ) ? $data['context'] : 'settings';
441
 
442
  $this->log(
443
- // translators: Placeholder refers to a setting title (e.g. "Language")
444
  __( '"%s" setting updated', 'stream' ),
445
  compact( 'option_title', 'option', 'old_value', 'new_value' ),
446
  null,
@@ -450,13 +499,20 @@ class Connector_GravityForms extends Connector {
450
  }
451
  }
452
 
 
 
 
 
 
 
 
453
  public function check_rg_gforms_key( $old_value, $new_value ) {
454
  $is_update = ( $new_value && strlen( $new_value ) );
455
  $option = 'rg_gforms_key';
456
 
457
  $this->log(
458
  sprintf(
459
- // translators: Placeholder refers to a status (e.g. "updated")
460
  __( 'Gravity Forms license key %s', 'stream' ),
461
  $is_update ? esc_html__( 'updated', 'stream' ) : esc_html__( 'deleted', 'stream' )
462
  ),
@@ -467,10 +523,20 @@ class Connector_GravityForms extends Connector {
467
  );
468
  }
469
 
 
 
 
 
 
 
 
 
 
 
470
  public function callback_gform_post_export_entries( $form, $start_date, $end_date, $fields ) {
471
  unset( $fields );
472
  $this->log(
473
- // translators: Placeholder refers to a form title (e.g. "Contact Form")
474
  __( '"%s" form entries exported', 'stream' ),
475
  array(
476
  'form_title' => $form['title'],
@@ -484,13 +550,20 @@ class Connector_GravityForms extends Connector {
484
  );
485
  }
486
 
 
 
 
 
 
 
 
487
  public function callback_gform_forms_post_import( $forms ) {
488
  $forms_total = count( $forms );
489
  $forms_ids = wp_list_pluck( $forms, 'id' );
490
  $forms_titles = wp_list_pluck( $forms, 'title' );
491
 
492
  $this->log(
493
- // translators: Placeholder refers to a number of forms (e.g. "42")
494
  _n( '%d form imported', '%d forms imported', $forms_total, 'stream' ),
495
  array(
496
  'count' => $forms_total,
@@ -503,11 +576,19 @@ class Connector_GravityForms extends Connector {
503
  );
504
  }
505
 
 
 
 
 
 
 
 
 
506
  public function callback_gform_export_separator( $dummy, $form_id ) {
507
  $form = $this->get_form( $form_id );
508
 
509
  $this->log(
510
- // translators: Placeholder refers to a form title (e.g. "Contact Form")
511
  __( '"%s" form exported', 'stream' ),
512
  array(
513
  'form_title' => $form['title'],
@@ -521,12 +602,18 @@ class Connector_GravityForms extends Connector {
521
  return $dummy;
522
  }
523
 
 
 
 
 
 
 
524
  public function callback_gform_export_options( $dummy, $forms ) {
525
  $ids = wp_list_pluck( $forms, 'id' );
526
  $titles = wp_list_pluck( $forms, 'title' );
527
 
528
  $this->log(
529
- // translators: Placeholder refers to a number of forms (e.g. "42")
530
  _n( 'Export process started for %d form', 'Export process started for %d forms', count( $forms ), 'stream' ),
531
  array(
532
  'count' => count( $forms ),
@@ -541,12 +628,20 @@ class Connector_GravityForms extends Connector {
541
  return $dummy;
542
  }
543
 
 
 
 
 
 
 
 
 
544
  public function callback_gform_delete_lead( $lead_id ) {
545
  $lead = $this->get_lead( $lead_id );
546
  $form = $this->get_form( $lead['form_id'] );
547
 
548
  $this->log(
549
- // translators: Placeholders refer to an ID, and a form title (e.g. "42", "Contact Form")
550
  __( 'Lead #%1$d from "%2$s" deleted', 'stream' ),
551
  array(
552
  'lead_id' => $lead_id,
@@ -559,6 +654,18 @@ class Connector_GravityForms extends Connector {
559
  );
560
  }
561
 
 
 
 
 
 
 
 
 
 
 
 
 
562
  public function callback_gform_post_note_added( $note_id, $lead_id, $user_id, $user_name, $note, $note_type ) {
563
  unset( $user_id );
564
  unset( $user_name );
@@ -569,7 +676,7 @@ class Connector_GravityForms extends Connector {
569
  $form = $this->get_form( $lead['form_id'] );
570
 
571
  $this->log(
572
- // translators: Placeholders refer to an ID, another ID, and a form title (e.g. "42", "7", "Contact Form")
573
  __( 'Note #%1$d added to lead #%2$d on "%3$s" form', 'stream' ),
574
  array(
575
  'note_id' => $note_id,
@@ -583,12 +690,20 @@ class Connector_GravityForms extends Connector {
583
  );
584
  }
585
 
 
 
 
 
 
 
 
 
586
  public function callback_gform_pre_note_deleted( $note_id, $lead_id ) {
587
  $lead = $this->get_lead( $lead_id );
588
  $form = $this->get_form( $lead['form_id'] );
589
 
590
  $this->log(
591
- // translators: Placeholders refer to an ID, another ID, and a form title (e.g. "42", "7", "Contact Form")
592
  __( 'Note #%1$d deleted from lead #%2$d on "%3$s" form', 'stream' ),
593
  array(
594
  'note_id' => $note_id,
@@ -602,6 +717,15 @@ class Connector_GravityForms extends Connector {
602
  );
603
  }
604
 
 
 
 
 
 
 
 
 
 
605
  public function callback_gform_update_status( $lead_id, $status, $prev = '' ) {
606
  $lead = $this->get_lead( $lead_id );
607
  $form = $this->get_form( $lead['form_id'] );
@@ -623,7 +747,7 @@ class Connector_GravityForms extends Connector {
623
 
624
  $this->log(
625
  sprintf(
626
- // translators: Placeholders refer to an ID, a status, and a form title (e.g. "42", "activated", "Contact Form")
627
  __( 'Lead #%1$d %2$s on "%3$s" form', 'stream' ),
628
  $lead_id,
629
  $actions[ $status ],
@@ -645,9 +769,10 @@ class Connector_GravityForms extends Connector {
645
  /**
646
  * Callback fired when an entry is read/unread
647
  *
648
- * @param int $lead_id
649
- * @param int $status
650
- * @return void
 
651
  */
652
  public function callback_gform_update_is_read( $lead_id, $status ) {
653
  $lead = $this->get_lead( $lead_id );
@@ -656,7 +781,7 @@ class Connector_GravityForms extends Connector {
656
 
657
  $this->log(
658
  sprintf(
659
- // translators: Placeholders refer to an ID, a status, and a form title (e.g. "42", "unread", "Contact Form")
660
  __( 'Entry #%1$d marked as %2$s on form #%3$d ("%4$s")', 'stream' ),
661
  $lead_id,
662
  $status,
@@ -678,9 +803,10 @@ class Connector_GravityForms extends Connector {
678
  /**
679
  * Callback fired when an entry is starred/unstarred
680
  *
681
- * @param int $lead_id
682
- * @param int $status
683
- * @return void
 
684
  */
685
  public function callback_gform_update_is_starred( $lead_id, $status ) {
686
  $lead = $this->get_lead( $lead_id );
@@ -690,7 +816,7 @@ class Connector_GravityForms extends Connector {
690
 
691
  $this->log(
692
  sprintf(
693
- // translators: Placeholders refer to an ID, a status, and a form title (e.g. "42", "starred", "Contact Form")
694
  __( 'Entry #%1$d %2$s on form #%3$d ("%4$s")', 'stream' ),
695
  $lead_id,
696
  $status,
@@ -712,8 +838,9 @@ class Connector_GravityForms extends Connector {
712
  /**
713
  * Callback fired when a form is deleted
714
  *
715
- * @param int $form_id Form ID
716
- * @return void
 
717
  */
718
  public function callback_gform_before_delete_form( $form_id ) {
719
  $this->log_form_action( $form_id, 'deleted' );
@@ -722,8 +849,9 @@ class Connector_GravityForms extends Connector {
722
  /**
723
  * Callback fired when a form is trashed
724
  *
725
- * @param int $form_id Form ID
726
- * @return void
 
727
  */
728
  public function callback_gform_post_form_trashed( $form_id ) {
729
  $this->log_form_action( $form_id, 'trashed' );
@@ -732,8 +860,9 @@ class Connector_GravityForms extends Connector {
732
  /**
733
  * Callback fired when a form is restored
734
  *
735
- * @param int $form_id Form ID
736
- * @return void
 
737
  */
738
  public function callback_gform_post_form_restored( $form_id ) {
739
  $this->log_form_action( $form_id, 'untrashed' );
@@ -742,8 +871,9 @@ class Connector_GravityForms extends Connector {
742
  /**
743
  * Callback fired when a form is activated
744
  *
745
- * @param int $form_id Form ID
746
- * @return void
 
747
  */
748
  public function callback_gform_post_form_activated( $form_id ) {
749
  $this->log_form_action( $form_id, 'activated' );
@@ -752,8 +882,9 @@ class Connector_GravityForms extends Connector {
752
  /**
753
  * Callback fired when a form is deactivated
754
  *
755
- * @param int $form_id Form ID
756
- * @return void
 
757
  */
758
  public function callback_gform_post_form_deactivated( $form_id ) {
759
  $this->log_form_action( $form_id, 'deactivated' );
@@ -762,8 +893,9 @@ class Connector_GravityForms extends Connector {
762
  /**
763
  * Callback fired when a form is duplicated
764
  *
765
- * @param int $form_id Form ID
766
- * @return void
 
767
  */
768
  public function callback_gform_post_form_duplicated( $form_id ) {
769
  $this->log_form_action( $form_id, 'duplicated' );
@@ -772,8 +904,9 @@ class Connector_GravityForms extends Connector {
772
  /**
773
  * Callback fired when a form's views are reset
774
  *
775
- * @param int $form_id Form ID
776
- * @return void
 
777
  */
778
  public function callback_gform_post_form_views_deleted( $form_id ) {
779
  $this->log_form_action( $form_id, 'views_deleted' );
@@ -782,9 +915,8 @@ class Connector_GravityForms extends Connector {
782
  /**
783
  * Track status change of forms
784
  *
785
- * @param int $form_id
786
- * @param string $action
787
- * @return void
788
  */
789
  public function log_form_action( $form_id, $action ) {
790
  $form = $this->get_form( $form_id );
@@ -805,7 +937,7 @@ class Connector_GravityForms extends Connector {
805
 
806
  $this->log(
807
  sprintf(
808
- // translators: Placeholders refer to an ID, a form title, and a status (e.g. "42", "Contact Form", "Activated")
809
  __( 'Form #%1$d ("%2$s") %3$s', 'stream' ),
810
  $form_id,
811
  $form['title'],
@@ -825,8 +957,7 @@ class Connector_GravityForms extends Connector {
825
  /**
826
  * Helper function to get a single entry
827
  *
828
- * @param int $lead_id Lead ID
829
- * @return array
830
  */
831
  private function get_lead( $lead_id ) {
832
  return \GFFormsModel::get_lead( $lead_id );
@@ -835,8 +966,7 @@ class Connector_GravityForms extends Connector {
835
  /**
836
  * Helper function to get a single form
837
  *
838
- * @param int $form_id Form ID
839
- * @return array
840
  */
841
  private function get_form( $form_id ) {
842
  return \GFFormsModel::get_form_meta( $form_id );
1
  <?php
2
+ /**
3
+ * Connector for Gravity Forms
4
+ *
5
+ * @package WP_Stream
6
+ */
7
+
8
  namespace WP_Stream;
9
 
10
+ /**
11
+ * Class - Connector_GravityForms
12
+ */
13
  class Connector_GravityForms extends Connector {
14
  /**
15
  * Connector slug
139
  *
140
  * @filter wp_stream_action_links_{connector}
141
  *
142
+ * @param array $links Previous links registered.
143
+ * @param object $record Stream record.
144
  *
145
  * @return array Action links
146
  */
185
  return $links;
186
  }
187
 
188
+ /**
189
+ * Register all context hooks
190
+ */
191
  public function register() {
192
  parent::register();
193
 
217
  /**
218
  * Track Create/Update actions on Forms
219
  *
220
+ * @param array $form Form data.
221
+ * @param bool $is_new Is this a new form?.
 
222
  */
223
  public function callback_gform_after_save_form( $form, $is_new ) {
224
  $title = $form['title'];
226
 
227
  $this->log(
228
  sprintf(
229
+ /* translators: %1$s a form title, %2$s a status (e.g. "Contact Form", "created") */
230
  __( '"%1$s" form %2$s', 'stream' ),
231
  $title,
232
  $is_new ? esc_html__( 'created', 'stream' ) : esc_html__( 'updated', 'stream' )
245
  /**
246
  * Track saving form confirmations
247
  *
248
+ * @param array $confirmation Confirmation data.
249
+ * @param array $form Form data.
250
+ * @param bool $is_new Is this a new form?.
 
251
  */
252
  public function callback_gform_pre_confirmation_save( $confirmation, $form, $is_new = true ) {
253
  if ( ! isset( $is_new ) ) {
256
 
257
  $this->log(
258
  sprintf(
259
+ /* translators: %1$s: a confirmation name, %2$s: a status, %3$s: a form title (e.g. "Email", "created", "Contact Form") */
260
  __( '"%1$s" confirmation %2$s for "%3$s"', 'stream' ),
261
  $confirmation['name'],
262
  $is_new ? esc_html__( 'created', 'stream' ) : esc_html__( 'updated', 'stream' ),
277
  /**
278
  * Track saving form notifications
279
  *
280
+ * @param array $notification Notification data.
281
+ * @param array $form Form data.
282
+ * @param bool $is_new Is this a new form?.
283
  * @return array
284
  */
285
  public function callback_gform_pre_notification_save( $notification, $form, $is_new = true ) {
289
 
290
  $this->log(
291
  sprintf(
292
+ /* translators: %1$s: a notification name, %2$s: a status, %3$s: a form title (e.g. "Email", "created", "Contact Form") */
293
  __( '"%1$s" notification %2$s for "%3$s"', 'stream' ),
294
  $notification['name'],
295
  $is_new ? esc_html__( 'created', 'stream' ) : esc_html__( 'updated', 'stream' ),
310
  /**
311
  * Track deletion of notifications
312
  *
313
+ * @param array $notification Notification data.
314
+ * @param array $form Form data.
 
315
  */
316
  public function callback_gform_pre_notification_deleted( $notification, $form ) {
317
  $this->log(
318
  sprintf(
319
+ /* translators: %1$s: a notification name, %2$s: a form title (e.g. "Email", "Contact Form") */
320
  __( '"%1$s" notification deleted from "%2$s"', 'stream' ),
321
  $notification['name'],
322
  $form['title']
334
  /**
335
  * Track deletion of confirmations
336
  *
337
+ * @param array $confirmation Confirmation data.
338
+ * @param array $form Form data.
 
339
  */
340
  public function callback_gform_pre_confirmation_deleted( $confirmation, $form ) {
341
  $this->log(
342
  sprintf(
343
+ /* translators: %1$s: a confirmation name, %2$s: a form title (e.g. "Email", "Contact Form") */
344
  __( '"%1$s" confirmation deleted from "%2$s"', 'stream' ),
345
  $confirmation['name'],
346
  $form['title']
358
  /**
359
  * Track status change of confirmations
360
  *
361
+ * @param array $confirmation Confirmation data.
362
+ * @param array $form Form data.
363
+ * @param bool $is_active Is this form active?.
 
364
  */
365
  public function callback_gform_confirmation_status( $confirmation, $form, $is_active ) {
366
  $this->log(
367
  sprintf(
368
+ /* translators: %1$s: a confirmation name, %2$s: a status, %3$s: a form title (e.g. "Email", "activated", "Contact Form") */
369
  __( '"%1$s" confirmation %2$s from "%3$s"', 'stream' ),
370
  $confirmation['name'],
371
  $is_active ? esc_html__( 'activated', 'stream' ) : esc_html__( 'deactivated', 'stream' ),
385
  /**
386
  * Track status change of notifications
387
  *
388
+ * @param array $notification Notification data.
389
+ * @param array $form Form data.
390
+ * @param bool $is_active Is this form active?.
 
391
  */
392
  public function callback_gform_notification_status( $notification, $form, $is_active ) {
393
  $this->log(
394
  sprintf(
395
+ /* translators: %1$s: a notification name, %2$s: a status, %3$s: a form title (e.g. "Email", "activated", "Contact Form") */
396
  __( '"%1$s" notification %2$s from "%3$s"', 'stream' ),
397
  $notification['name'],
398
  $is_active ? esc_html__( 'activated', 'stream' ) : esc_html__( 'deactivated', 'stream' ),
409
  );
410
  }
411
 
412
+ /**
413
+ * Track GravityForms-specific option changes.
414
+ *
415
+ * @param string $option Option key.
416
+ * @param string $old Old value.
417
+ * @param string $new New value.
418
+ */
419
  public function callback_update_option( $option, $old, $new ) {
420
  $this->check( $option, $old, $new );
421
  }
422
 
423
+ /**
424
+ * Track GravityForms-specific option creations.
425
+ *
426
+ * @param string $option Option key.
427
+ * @param string $val Value.
428
+ */
429
  public function callback_add_option( $option, $val ) {
430
  $this->check( $option, null, $val );
431
  }
432
 
433
+ /**
434
+ * Track GravityForms-specific option deletions.
435
+ *
436
+ * @param string $option Option key.
437
+ */
438
  public function callback_delete_option( $option ) {
439
  $this->check( $option, null, null );
440
  }
441
 
442
+ /**
443
+ * Track GravityForms-specific site option changes
444
+ *
445
+ * @param string $option Option key.
446
+ * @param string $old Old value.
447
+ * @param string $new New value.
448
+ */
449
  public function callback_update_site_option( $option, $old, $new ) {
450
  $this->check( $option, $old, $new );
451
  }
452
 
453
+ /**
454
+ * Track GravityForms-specific site option creations.
455
+ *
456
+ * @param string $option Option key.
457
+ * @param string $val Value.
458
+ */
459
  public function callback_add_site_option( $option, $val ) {
460
  $this->check( $option, null, $val );
461
  }
462
 
463
+ /**
464
+ * Track GravityForms-specific site option deletions.
465
+ *
466
+ * @param string $option Option key.
467
+ */
468
  public function callback_delete_site_option( $option ) {
469
  $this->check( $option, null, null );
470
  }
471
 
472
+ /**
473
+ * Logs GravityForms-specific (site) option activity.
474
+ *
475
+ * @param string $option Option key.
476
+ * @param string $old_value Old value.
477
+ * @param string $new_value New value.
478
+ */
479
  public function check( $option, $old_value, $new_value ) {
480
  if ( ! array_key_exists( $option, $this->options ) ) {
481
  return;
489
  $context = isset( $data['context'] ) ? $data['context'] : 'settings';
490
 
491
  $this->log(
492
+ /* translators: %s: a setting title (e.g. "Language") */
493
  __( '"%s" setting updated', 'stream' ),
494
  compact( 'option_title', 'option', 'old_value', 'new_value' ),
495
  null,
499
  }
500
  }
501
 
502
+ /**
503
+ * Log GravityForm license key changes
504
+ *
505
+ * @param string $old_value Old license key.
506
+ * @param string $new_value New license key.
507
+ * @return void
508
+ */
509
  public function check_rg_gforms_key( $old_value, $new_value ) {
510
  $is_update = ( $new_value && strlen( $new_value ) );
511
  $option = 'rg_gforms_key';
512
 
513
  $this->log(
514
  sprintf(
515
+ /* translators: %s: a status (e.g. "updated") */
516
  __( 'Gravity Forms license key %s', 'stream' ),
517
  $is_update ? esc_html__( 'updated', 'stream' ) : esc_html__( 'deleted', 'stream' )
518
  ),
523
  );
524
  }
525
 
526
+ /**
527
+ * Logs form entry exports.
528
+ *
529
+ * @action gform_post_export_entries
530
+ *
531
+ * @param object $form Form data.
532
+ * @param string $start_date Form start date.
533
+ * @param string $end_date Form completion date.
534
+ * @param array $fields Form fields data.
535
+ */
536
  public function callback_gform_post_export_entries( $form, $start_date, $end_date, $fields ) {
537
  unset( $fields );
538
  $this->log(
539
+ /* translators: %s: a form title (e.g. "Contact Form") */
540
  __( '"%s" form entries exported', 'stream' ),
541
  array(
542
  'form_title' => $form['title'],
550
  );
551
  }
552
 
553
+ /**
554
+ * Logs form imports.
555
+ *
556
+ * @action gform_forms_post_import
557
+ *
558
+ * @param array $forms List of form data.
559
+ */
560
  public function callback_gform_forms_post_import( $forms ) {
561
  $forms_total = count( $forms );
562
  $forms_ids = wp_list_pluck( $forms, 'id' );
563
  $forms_titles = wp_list_pluck( $forms, 'title' );
564
 
565
  $this->log(
566
+ /* translators: %d: a number of forms (e.g. "42") */
567
  _n( '%d form imported', '%d forms imported', $forms_total, 'stream' ),
568
  array(
569
  'count' => $forms_total,
576
  );
577
  }
578
 
579
+ /**
580
+ * Logs form exports
581
+ *
582
+ * @action gform_export_separator
583
+ *
584
+ * @param string $dummy Unused.
585
+ * @param int $form_id Form ID.
586
+ */
587
  public function callback_gform_export_separator( $dummy, $form_id ) {
588
  $form = $this->get_form( $form_id );
589
 
590
  $this->log(
591
+ /* translators: %s: a form title (e.g. "Contact Form") */
592
  __( '"%s" form exported', 'stream' ),
593
  array(
594
  'form_title' => $form['title'],
602
  return $dummy;
603
  }
604
 
605
+ /**
606
+ * Log bulk form exports
607
+ *
608
+ * @param string $dummy Unused.
609
+ * @param array $forms Form data.
610
+ */
611
  public function callback_gform_export_options( $dummy, $forms ) {
612
  $ids = wp_list_pluck( $forms, 'id' );
613
  $titles = wp_list_pluck( $forms, 'title' );
614
 
615
  $this->log(
616
+ /* translators: %d: a number of forms (e.g. "42") */
617
  _n( 'Export process started for %d form', 'Export process started for %d forms', count( $forms ), 'stream' ),
618
  array(
619
  'count' => count( $forms ),
628
  return $dummy;
629
  }
630
 
631
+ /**
632
+ * Logs lead deletions.
633
+ *
634
+ * @action gform_delete_lead
635
+ *
636
+ * @param int $lead_id Lead ID.
637
+ * @return void
638
+ */
639
  public function callback_gform_delete_lead( $lead_id ) {
640
  $lead = $this->get_lead( $lead_id );
641
  $form = $this->get_form( $lead['form_id'] );
642
 
643
  $this->log(
644
+ /* translators: %1$d: to an ID, %2$s: a form title (e.g. "42", "Contact Form") */
645
  __( 'Lead #%1$d from "%2$s" deleted', 'stream' ),
646
  array(
647
  'lead_id' => $lead_id,
654
  );
655
  }
656
 
657
+ /**
658
+ * Logs note creation on lead.
659
+ *
660
+ * @action gform_post_note_added
661
+ *
662
+ * @param int $note_id Note ID.
663
+ * @param int $lead_id Lead ID.
664
+ * @param int $user_id User ID of note author.
665
+ * @param string $user_name Username of note author.
666
+ * @param string $note Note object.
667
+ * @param string $note_type Note type.
668
+ */
669
  public function callback_gform_post_note_added( $note_id, $lead_id, $user_id, $user_name, $note, $note_type ) {
670
  unset( $user_id );
671
  unset( $user_name );
676
  $form = $this->get_form( $lead['form_id'] );
677
 
678
  $this->log(
679
+ /* translators: %1$d: an ID, %2$d: another ID, %3$s: a form title (e.g. "42", "7", "Contact Form") */
680
  __( 'Note #%1$d added to lead #%2$d on "%3$s" form', 'stream' ),
681
  array(
682
  'note_id' => $note_id,
690
  );
691
  }
692
 
693
+ /**
694
+ * Logs note deletion
695
+ *
696
+ * @action gform_pre_note_deleted
697
+ *
698
+ * @param int $note_id Note ID.
699
+ * @param int $lead_id Lead ID.
700
+ */
701
  public function callback_gform_pre_note_deleted( $note_id, $lead_id ) {
702
  $lead = $this->get_lead( $lead_id );
703
  $form = $this->get_form( $lead['form_id'] );
704
 
705
  $this->log(
706
+ /* translators: %2$d an ID, another ID, and a form title (e.g. "42", "7", "Contact Form") */
707
  __( 'Note #%1$d deleted from lead #%2$d on "%3$s" form', 'stream' ),
708
  array(
709
  'note_id' => $note_id,
717
  );
718
  }
719
 
720
+ /**
721
+ * Logs form status updates.
722
+ *
723
+ * @action gform_update_status
724
+ *
725
+ * @param int $lead_id Lead ID.
726
+ * @param string $status New form status.
727
+ * @param string $prev Old form status.
728
+ */
729
  public function callback_gform_update_status( $lead_id, $status, $prev = '' ) {
730
  $lead = $this->get_lead( $lead_id );
731
  $form = $this->get_form( $lead['form_id'] );
747
 
748
  $this->log(
749
  sprintf(
750
+ /* translators: %1$d: an ID, %2$s: a status, %3$s: a form title (e.g. "42", "activated", "Contact Form") */
751
  __( 'Lead #%1$d %2$s on "%3$s" form', 'stream' ),
752
  $lead_id,
753
  $actions[ $status ],
769
  /**
770
  * Callback fired when an entry is read/unread
771
  *
772
+ * @action update_is_read
773
+ *
774
+ * @param int $lead_id Lead ID.
775
+ * @param string $status Status.
776
  */
777
  public function callback_gform_update_is_read( $lead_id, $status ) {
778
  $lead = $this->get_lead( $lead_id );
781
 
782
  $this->log(
783
  sprintf(
784
+ /* translators: %1$d: a lead ID, %2$s: a status, %3$s: a form ID, %4$s: a form title (e.g. "42", "unread", "Contact Form") */
785
  __( 'Entry #%1$d marked as %2$s on form #%3$d ("%4$s")', 'stream' ),
786
  $lead_id,
787
  $status,
803
  /**
804
  * Callback fired when an entry is starred/unstarred
805
  *
806
+ * @action gform_update_is_starred
807
+ *
808
+ * @param int $lead_id Lead ID.
809
+ * @param int $status Status.
810
  */
811
  public function callback_gform_update_is_starred( $lead_id, $status ) {
812
  $lead = $this->get_lead( $lead_id );
816
 
817
  $this->log(
818
  sprintf(
819
+ /* translators: %1$d: an ID, %2$s: a status, %3$d: a form title (e.g. "42", "starred", "Contact Form") */
820
  __( 'Entry #%1$d %2$s on form #%3$d ("%4$s")', 'stream' ),
821
  $lead_id,
822
  $status,
838
  /**
839
  * Callback fired when a form is deleted
840
  *
841
+ * @action gform_before_delete_form
842
+ *
843
+ * @param int $form_id Form ID.
844
  */
845
  public function callback_gform_before_delete_form( $form_id ) {
846
  $this->log_form_action( $form_id, 'deleted' );
849
  /**
850
  * Callback fired when a form is trashed
851
  *
852
+ * @action gform_post_form_trashed
853
+ *
854
+ * @param int $form_id Form ID.
855
  */
856
  public function callback_gform_post_form_trashed( $form_id ) {
857
  $this->log_form_action( $form_id, 'trashed' );
860
  /**
861
  * Callback fired when a form is restored
862
  *
863
+ * @action gform_post_form_restored
864
+ *
865
+ * @param int $form_id Form ID.
866
  */
867
  public function callback_gform_post_form_restored( $form_id ) {
868
  $this->log_form_action( $form_id, 'untrashed' );
871
  /**
872
  * Callback fired when a form is activated
873
  *
874
+ * @action gform_post_form_activated
875
+ *
876
+ * @param int $form_id Form ID.
877
  */
878
  public function callback_gform_post_form_activated( $form_id ) {
879
  $this->log_form_action( $form_id, 'activated' );
882
  /**
883
  * Callback fired when a form is deactivated
884
  *
885
+ * @action gform_post_form_deactivated
886
+ *
887
+ * @param int $form_id Form ID.
888
  */
889
  public function callback_gform_post_form_deactivated( $form_id ) {
890
  $this->log_form_action( $form_id, 'deactivated' );
893
  /**
894
  * Callback fired when a form is duplicated
895
  *
896
+ * @action gform_post_form_duplicated
897
+ *
898
+ * @param int $form_id Form ID.
899
  */
900
  public function callback_gform_post_form_duplicated( $form_id ) {
901
  $this->log_form_action( $form_id, 'duplicated' );
904
  /**
905
  * Callback fired when a form's views are reset
906
  *
907
+ * @action gform_post_form_views_deleted
908
+ *
909
+ * @param int $form_id Form ID.
910
  */
911
  public function callback_gform_post_form_views_deleted( $form_id ) {
912
  $this->log_form_action( $form_id, 'views_deleted' );
915
  /**
916
  * Track status change of forms
917
  *
918
+ * @param int $form_id Form ID.
919
+ * @param string $action Action.
 
920
  */
921
  public function log_form_action( $form_id, $action ) {
922
  $form = $this->get_form( $form_id );
937
 
938
  $this->log(
939
  sprintf(
940
+ /* translators: %1$d: an ID, %2$s: a form title, %3$s: a status (e.g. "42", "Contact Form", "Activated") */
941
  __( 'Form #%1$d ("%2$s") %3$s', 'stream' ),
942
  $form_id,
943
  $form['title'],
957
  /**
958
  * Helper function to get a single entry
959
  *
960
+ * @param int $lead_id Lead ID.
 
961
  */
962
  private function get_lead( $lead_id ) {
963
  return \GFFormsModel::get_lead( $lead_id );
966
  /**
967
  * Helper function to get a single form
968
  *
969
+ * @param int $form_id Form ID.
 
970
  */
971
  private function get_form( $form_id ) {
972
  return \GFFormsModel::get_form_meta( $form_id );
connectors/class-connector-installer.php CHANGED
@@ -1,6 +1,15 @@
1
  <?php
 
 
 
 
 
 
2
  namespace WP_Stream;
3
 
 
 
 
4
  class Connector_Installer extends Connector {
5
 
6
  /**
@@ -16,12 +25,12 @@ class Connector_Installer extends Connector {
16
  * @var array
17
  */
18
  public $actions = array(
19
- 'upgrader_process_complete', // plugins::installed | themes::installed
20
- 'activate_plugin', // plugins::activated
21
- 'deactivate_plugin', // plugins::deactivated
22
- 'switch_theme', // themes::activated
23
- 'delete_site_transient_update_themes', // themes::deleted
24
- 'pre_option_uninstall_plugins', // plugins::deleted
25
  'pre_set_site_transient_update_plugins',
26
  '_core_updated_successfully',
27
  );
@@ -75,8 +84,8 @@ class Connector_Installer extends Connector {
75
  *
76
  * @filter wp_stream_action_links_{connector}
77
  *
78
- * @param array $links Previous links registered
79
- * @param object $record Stream record
80
  *
81
  * @return array Action links
82
  */
@@ -112,10 +121,10 @@ class Connector_Installer extends Connector {
112
  /**
113
  * Log plugin installations
114
  *
115
- * @action transition_post_status
116
  *
117
- * @param \WP_Upgrader $upgrader
118
- * @param array $extra
119
  *
120
  * @return bool
121
  */
@@ -130,7 +139,7 @@ class Connector_Installer extends Connector {
130
  list( $error ) = reset( $errors );
131
  }
132
 
133
- // This would have failed down the road anyway
134
  if ( ! isset( $extra['type'] ) ) {
135
  return false;
136
  }
@@ -154,7 +163,7 @@ class Connector_Installer extends Connector {
154
  $slug = $upgrader->result['destination_name'];
155
  $name = $data['Name'];
156
  $version = $data['Version'];
157
- } else { // theme
158
  $slug = $upgrader->theme_info();
159
 
160
  if ( ! $slug ) {
@@ -169,7 +178,7 @@ class Connector_Installer extends Connector {
169
  }
170
 
171
  $action = 'installed';
172
- // translators: Placeholders refer to a plugin/theme type, a plugin/theme name, and a plugin/theme version (e.g. "plugin", "Stream", "4.2")
173
  $message = _x(
174
  'Installed %1$s: %2$s %3$s',
175
  'Plugin/theme installation. 1: Type (plugin/theme), 2: Plugin/theme name, 3: Plugin/theme version',
@@ -179,7 +188,7 @@ class Connector_Installer extends Connector {
179
  $logs[] = compact( 'slug', 'name', 'version', 'message', 'action' );
180
  } elseif ( 'update' === $action ) {
181
  $action = 'updated';
182
- // translators: Placeholders refer to a plugin/theme type, a plugin/theme name, and a plugin/theme version (e.g. "plugin", "Stream", "4.2")
183
  $message = _x(
184
  'Updated %1$s: %2$s %3$s',
185
  'Plugin/theme update. 1: Type (plugin/theme), 2: Plugin/theme name, 3: Plugin/theme version',
@@ -203,7 +212,7 @@ class Connector_Installer extends Connector {
203
 
204
  $logs[] = compact( 'slug', 'name', 'old_version', 'version', 'message', 'action' );
205
  }
206
- } else { // theme
207
  if ( isset( $extra['bulk'] ) && true === $extra['bulk'] ) {
208
  $slugs = $extra['themes'];
209
  } else {
@@ -252,13 +261,21 @@ class Connector_Installer extends Connector {
252
  return true;
253
  }
254
 
 
 
 
 
 
 
 
 
255
  public function callback_activate_plugin( $slug, $network_wide ) {
256
  $_plugins = $this->get_plugins();
257
  $name = $_plugins[ $slug ]['Name'];
258
  $network_wide = $network_wide ? esc_html__( 'network wide', 'stream' ) : null;
259
 
260
  $this->log(
261
- // translators: Placeholders refer to a plugin name, and whether it is on a single site or network wide (e.g. "Stream", "network wide") (a single site results in a blank string)
262
  _x(
263
  '"%1$s" plugin activated %2$s',
264
  '1: Plugin name, 2: Single site or network wide',
@@ -271,13 +288,21 @@ class Connector_Installer extends Connector {
271
  );
272
  }
273
 
 
 
 
 
 
 
 
 
274
  public function callback_deactivate_plugin( $slug, $network_wide ) {
275
  $_plugins = $this->get_plugins();
276
  $name = $_plugins[ $slug ]['Name'];
277
  $network_wide = $network_wide ? esc_html__( 'network wide', 'stream' ) : null;
278
 
279
  $this->log(
280
- // translators: Placeholders refer to a plugin name, and whether it is on a single site or network wide (e.g. "Stream", "network wide") (a single site results in a blank string)
281
  _x(
282
  '"%1$s" plugin deactivated %2$s',
283
  '1: Plugin name, 2: Single site or network wide',
@@ -290,10 +315,16 @@ class Connector_Installer extends Connector {
290
  );
291
  }
292
 
 
 
 
 
 
 
293
  public function callback_switch_theme( $name, $theme ) {
294
  unset( $theme );
295
  $this->log(
296
- // translators: Placeholder refers to a theme name (e.g. "Twenty Seventeen")
297
  __( '"%s" theme activated', 'stream' ),
298
  compact( 'name' ),
299
  null,
@@ -303,10 +334,17 @@ class Connector_Installer extends Connector {
303
  }
304
 
305
  /**
 
 
 
 
306
  * @todo Core needs a delete_theme hook
307
  */
308
  public function callback_delete_site_transient_update_themes() {
309
- $backtrace = debug_backtrace(); // @codingStandardsIgnoreLine This is used as a hack to determine a theme was deleted.
 
 
 
310
  $delete_theme_call = null;
311
 
312
  foreach ( $backtrace as $call ) {
@@ -321,10 +359,10 @@ class Connector_Installer extends Connector {
321
  }
322
 
323
  $name = $delete_theme_call['args'][0];
324
- // @todo Can we get the name of the theme? Or has it already been eliminated
325
 
326
  $this->log(
327
- // translators: Placeholder refers to a theme name (e.g. "Twenty Seventeen")
328
  __( '"%s" theme deleted', 'stream' ),
329
  compact( 'name' ),
330
  null,
@@ -334,6 +372,10 @@ class Connector_Installer extends Connector {
334
  }
335
 
336
  /**
 
 
 
 
337
  * @todo Core needs an uninstall_plugin hook
338
  * @todo This does not work in WP-CLI
339
  */
@@ -365,7 +407,11 @@ class Connector_Installer extends Connector {
365
  }
366
 
367
  /**
368
- * @param mixed $value
 
 
 
 
369
  *
370
  * @return mixed
371
  * @todo Core needs a delete_plugin hook
@@ -382,7 +428,7 @@ class Connector_Installer extends Connector {
382
  $network_wide = $data['Network'] ? esc_html__( 'network wide', 'stream' ) : '';
383
 
384
  $this->log(
385
- // translators: Placeholder refers to a plugin name (e.g. "Stream")
386
  __( '"%s" plugin deleted', 'stream' ),
387
  compact( 'name', 'plugin', 'network_wide' ),
388
  null,
@@ -396,6 +442,14 @@ class Connector_Installer extends Connector {
396
  return $value;
397
  }
398
 
 
 
 
 
 
 
 
 
399
  public function callback__core_updated_successfully( $new_version ) {
400
  global $pagenow, $wp_version;
401
 
@@ -403,10 +457,10 @@ class Connector_Installer extends Connector {
403
  $auto_updated = ( 'update-core.php' !== $pagenow );
404
 
405
  if ( $auto_updated ) {
406
- // translators: Placeholder refers to a version number (e.g. "4.2")
407
  $message = esc_html__( 'WordPress auto-updated to %s', 'stream' );
408
  } else {
409
- // translators: Placeholder refers to a version number (e.g. "4.2")
410
  $message = esc_html__( 'WordPress updated to %s', 'stream' );
411
  }
412
 
1
  <?php
2
+ /**
3
+ * Connector for installer
4
+ *
5
+ * @package WP_Stream
6
+ */
7
+
8
  namespace WP_Stream;
9
 
10
+ /**
11
+ * Class - Connector_Installer
12
+ */
13
  class Connector_Installer extends Connector {
14
 
15
  /**
25
  * @var array
26
  */
27
  public $actions = array(
28
+ 'upgrader_process_complete', // plugins::installed | themes::installed.
29
+ 'activate_plugin', // plugins::activated.
30
+ 'deactivate_plugin', // plugins::deactivated.
31
+ 'switch_theme', // themes::activated.
32
+ 'delete_site_transient_update_themes', // themes::deleted.
33
+ 'pre_option_uninstall_plugins', // plugins::deleted.
34
  'pre_set_site_transient_update_plugins',
35
  '_core_updated_successfully',
36
  );
84
  *
85
  * @filter wp_stream_action_links_{connector}
86
  *
87
+ * @param array $links Previous links registered.
88
+ * @param object $record Stream record.
89
  *
90
  * @return array Action links
91
  */
121
  /**
122
  * Log plugin installations
123
  *
124
+ * @action upgrader_process_complete
125
  *
126
+ * @param \WP_Upgrader $upgrader Upgrader object.
127
+ * @param array $extra Extra plugin data.
128
  *
129
  * @return bool
130
  */
139
  list( $error ) = reset( $errors );
140
  }
141
 
142
+ // This would have failed down the road anyway.
143
  if ( ! isset( $extra['type'] ) ) {
144
  return false;
145
  }
163
  $slug = $upgrader->result['destination_name'];
164
  $name = $data['Name'];
165
  $version = $data['Version'];
166
+ } else { // theme.
167
  $slug = $upgrader->theme_info();
168
 
169
  if ( ! $slug ) {
178
  }
179
 
180
  $action = 'installed';
181
+ /* translators: %1$s: a plugin/theme type, %2$s: a plugin/theme name, %3$s: a plugin/theme version (e.g. "plugin", "Stream", "4.2") */
182
  $message = _x(
183
  'Installed %1$s: %2$s %3$s',
184
  'Plugin/theme installation. 1: Type (plugin/theme), 2: Plugin/theme name, 3: Plugin/theme version',
188
  $logs[] = compact( 'slug', 'name', 'version', 'message', 'action' );
189
  } elseif ( 'update' === $action ) {
190
  $action = 'updated';
191
+ /* translators: %1$s: a plugin/theme type, %2$s: a plugin/theme name, %3$s: a plugin/theme version (e.g. "plugin", "Stream", "4.2") */
192
  $message = _x(
193
  'Updated %1$s: %2$s %3$s',
194
  'Plugin/theme update. 1: Type (plugin/theme), 2: Plugin/theme name, 3: Plugin/theme version',
212
 
213
  $logs[] = compact( 'slug', 'name', 'old_version', 'version', 'message', 'action' );
214
  }
215
+ } else { // theme.
216
  if ( isset( $extra['bulk'] ) && true === $extra['bulk'] ) {
217
  $slugs = $extra['themes'];
218
  } else {
261
  return true;
262
  }
263
 
264
+ /**
265
+ * Logs plugin activations
266
+ *
267
+ * @action activate_plugin
268
+ *
269
+ * @param string $slug Plugin slug name.
270
+ * @param bool $network_wide Activated across the multi-site?.
271
+ */
272
  public function callback_activate_plugin( $slug, $network_wide ) {
273
  $_plugins = $this->get_plugins();
274
  $name = $_plugins[ $slug ]['Name'];
275
  $network_wide = $network_wide ? esc_html__( 'network wide', 'stream' ) : null;
276
 
277
  $this->log(
278
+ /* translators: %1$s: a plugin name, %2$s: whether it is on a single site or network wide (e.g. "Stream", "network wide") (a single site results in a blank string) */
279
  _x(
280
  '"%1$s" plugin activated %2$s',
281
  '1: Plugin name, 2: Single site or network wide',
288
  );
289
  }
290
 
291
+ /**
292
+ * Logs plugin deactivations
293
+ *
294
+ * @action deactivate_plugin
295
+ *
296
+ * @param string $slug Plugin slug name.
297
+ * @param bool $network_wide Deactivated across the multi-site?.
298
+ */
299
  public function callback_deactivate_plugin( $slug, $network_wide ) {
300
  $_plugins = $this->get_plugins();
301
  $name = $_plugins[ $slug ]['Name'];
302
  $network_wide = $network_wide ? esc_html__( 'network wide', 'stream' ) : null;
303
 
304
  $this->log(
305
+ /* translators: %1$s: a plugin name, %2$s: whether it is on a single site or network wide (e.g. "Stream", "network wide") (a single site results in a blank string) */
306
  _x(
307
  '"%1$s" plugin deactivated %2$s',
308
  '1: Plugin name, 2: Single site or network wide',
315
  );
316
  }
317
 
318
+ /**
319
+ * Logs theme activations.
320
+ *
321
+ * @param string $name Theme name.
322
+ * @param string $theme Unused.
323
+ */
324
  public function callback_switch_theme( $name, $theme ) {
325
  unset( $theme );
326
  $this->log(
327
+ /* translators: %s: a theme name (e.g. "Twenty Seventeen") */
328
  __( '"%s" theme activated', 'stream' ),
329
  compact( 'name' ),
330
  null,
334
  }
335
 
336
  /**
337
+ * Logs theme deletion.
338
+ *
339
+ * @action delete_site_transient_update_themes
340
+ *
341
  * @todo Core needs a delete_theme hook
342
  */
343
  public function callback_delete_site_transient_update_themes() {
344
+ /**
345
+ * This is used as a hack to determine a theme was deleted.
346
+ */
347
+ $backtrace = debug_backtrace(); // @codingStandardsIgnoreLine
348
  $delete_theme_call = null;
349
 
350
  foreach ( $backtrace as $call ) {
359
  }
360
 
361
  $name = $delete_theme_call['args'][0];
362
+ // @todo Can we get the name of the theme? Or has it already been eliminated.
363
 
364
  $this->log(
365
+ /* translators: Placeholder refers to a theme name (e.g. "Twenty Seventeen") */
366
  __( '"%s" theme deleted', 'stream' ),
367
  compact( 'name' ),
368
  null,
372
  }
373
 
374
  /**
375
+ * Logs plugins uninstallations.
376
+ *
377
+ * @action pre_option_uninstall_plugins
378
+ *
379
  * @todo Core needs an uninstall_plugin hook
380
  * @todo This does not work in WP-CLI
381
  */
407
  }
408
 
409
  /**
410
+ * Logs bulk plugin deletions.
411
+ *
412
+ * @filter pre_set_site_transient_update_plugins
413
+ *
414
+ * @param mixed $value Unused.
415
  *
416
  * @return mixed
417
  * @todo Core needs a delete_plugin hook
428
  $network_wide = $data['Network'] ? esc_html__( 'network wide', 'stream' ) : '';
429
 
430
  $this->log(
431
+ /* translators: %s a plugin name (e.g. "Stream") */
432
  __( '"%s" plugin deleted', 'stream' ),
433
  compact( 'name', 'plugin', 'network_wide' ),
434
  null,
442
  return $value;
443
  }
444
 
445
+ /**
446
+ * Logs WordPress core upgrades
447
+ *
448
+ * @action _core_updated_successfully
449
+ *
450
+ * @param string $new_version Version WordPress core has be upgraded to.
451
+ * @return void
452
+ */
453
  public function callback__core_updated_successfully( $new_version ) {
454
  global $pagenow, $wp_version;
455
 
457
  $auto_updated = ( 'update-core.php' !== $pagenow );
458
 
459
  if ( $auto_updated ) {
460
+ /* translators: %s: a version number (e.g. "4.2") */
461
  $message = esc_html__( 'WordPress auto-updated to %s', 'stream' );
462
  } else {
463
+ /* translators: %s: a version number (e.g. "4.2") */
464
  $message = esc_html__( 'WordPress updated to %s', 'stream' );
465
  }
466
 
connectors/class-connector-jetpack.php CHANGED
@@ -1,6 +1,15 @@
1
  <?php
 
 
 
 
 
 
2
  namespace WP_Stream;
3
 
 
 
 
4
  class Connector_Jetpack extends Connector {
5
  /**
6
  * Connector slug
@@ -133,8 +142,8 @@ class Connector_Jetpack extends Connector {
133
  *
134
  * @filter wp_stream_action_links_{connector}
135
  *
136
- * @param array $links Previous links registered
137
- * @param object $record Stream record
138
  *
139
  * @return array Action links
140
  */
@@ -176,7 +185,7 @@ class Connector_Jetpack extends Connector {
176
  );
177
  }
178
  } elseif ( \Jetpack::is_module_active( str_replace( 'jetpack-', '', $record->context ) ) ) {
179
- $slug = str_replace( 'jetpack-', '', $record->context ); // handling jetpack-comment anomaly
180
 
181
  if ( apply_filters( 'jetpack_module_configurable_' . $slug, false ) ) {
182
  $links[ esc_html__( 'Configure module', 'stream' ) ] = \Jetpack::module_configuration_url( $slug );
@@ -187,6 +196,9 @@ class Connector_Jetpack extends Connector {
187
  return $links;
188
  }
189
 
 
 
 
190
  public function register() {
191
  parent::register();
192
 
@@ -194,7 +206,7 @@ class Connector_Jetpack extends Connector {
194
 
195
  $this->options = array(
196
  'jetpack_options' => null,
197
- // Sharing module
198
  'hide_gplus' => null,
199
  'gplus_authors' => null,
200
  'sharing-options' => array(
@@ -206,22 +218,22 @@ class Connector_Jetpack extends Connector {
206
  'label' => esc_html__( 'Twitter site tag', 'stream' ),
207
  'context' => 'sharedaddy',
208
  ),
209
- // Stats module
210
  'stats_options' => array(
211
  'label' => esc_html__( 'WordPress.com Stats', 'stream' ),
212
  'context' => 'stats',
213
  ),
214
- // Comments
215
  'jetpack_comment_form_color_scheme' => array(
216
  'label' => esc_html__( 'Color Scheme', 'stream' ),
217
  'context' => 'jetpack-comments',
218
  ),
219
- // Likes
220
  'disabled_likes' => array(
221
  'label' => esc_html__( 'WP.com Site-wide Likes', 'stream' ),
222
  'context' => 'likes',
223
  ),
224
- // Mobile
225
  'wp_mobile_excerpt' => array(
226
  'label' => esc_html__( 'Excerpts appearance', 'stream' ),
227
  'context' => 'minileven',
@@ -233,7 +245,7 @@ class Connector_Jetpack extends Connector {
233
  );
234
 
235
  $this->options_override = array(
236
- // Carousel Module
237
  'carousel_background_color' => array(
238
  'label' => esc_html__( 'Background color', 'stream' ),
239
  'context' => 'carousel',
@@ -242,7 +254,7 @@ class Connector_Jetpack extends Connector {
242
  'label' => esc_html__( 'Metadata', 'stream' ),
243
  'context' => 'carousel',
244
  ),
245
- // Subscriptions
246
  'stb_enabled' => array(
247
  'label' => esc_html__( 'Follow blog comment form button', 'stream' ),
248
  'context' => 'subscriptions',
@@ -251,22 +263,22 @@ class Connector_Jetpack extends Connector {
251
  'label' => esc_html__( 'Follow comments form button', 'stream' ),
252
  'context' => 'subscriptions',
253
  ),
254
- // Jetpack comments
255
  'highlander_comment_form_prompt' => array(
256
  'label' => esc_html__( 'Greeting Text', 'stream' ),
257
  'context' => 'jetpack-comments',
258
  ),
259
- // Infinite Scroll
260
  'infinite_scroll_google_analytics' => array(
261
  'label' => esc_html__( 'Infinite Scroll Google Analytics', 'stream' ),
262
  'context' => 'infinite-scroll',
263
  ),
264
- // Protect
265
  'jetpack_protect_blocked_attempts' => array(
266
  'label' => esc_html__( 'Blocked Attempts', 'stream' ),
267
  'context' => 'protect',
268
  ),
269
- // SSO
270
  'jetpack_sso_require_two_step' => array(
271
  'label' => esc_html__( 'Require Two-Step Authentication', 'stream' ),
272
  'context' => 'sso',
@@ -275,7 +287,7 @@ class Connector_Jetpack extends Connector {
275
  'label' => esc_html__( 'Match by Email', 'stream' ),
276
  'context' => 'sso',
277
  ),
278
- // Related posts
279
  'jetpack_relatedposts' => array(
280
  'show_headline' => array(
281
  'label' => esc_html__( 'Show Related Posts Headline', 'stream' ),
@@ -286,7 +298,7 @@ class Connector_Jetpack extends Connector {
286
  'context' => 'related-posts',
287
  ),
288
  ),
289
- // Site verification
290
  'verification_services_codes' => array(
291
  'google' => array(
292
  'label' => esc_html__( 'Google Webmaster Tools Token', 'stream' ),
@@ -301,7 +313,7 @@ class Connector_Jetpack extends Connector {
301
  'context' => 'verification-tools',
302
  ),
303
  ),
304
- // Tiled galleries
305
  'tiled_galleries' => array(
306
  'label' => esc_html__( 'Tiled Galleries', 'stream' ),
307
  'context' => 'tiled-gallery',
@@ -316,7 +328,7 @@ class Connector_Jetpack extends Connector {
316
  * - Registration/Disconnection of blogs
317
  * - Authorization/unlinking of users
318
  *
319
- * @param array $entry
320
  */
321
  public function callback_jetpack_log_entry( array $entry ) {
322
  if ( isset( $entry['code'] ) ) {
@@ -343,7 +355,7 @@ class Connector_Jetpack extends Connector {
343
  $action = $method . 'd';
344
  $meta = compact( 'module_slug' );
345
  $message = sprintf(
346
- // translators: Placeholders refer to a module name, and a status (e.g. "Photon", "activated")
347
  __( '%1$s module %2$s', 'stream' ),
348
  $module_name,
349
  ( 'activated' === $action ) ? esc_html__( 'activated', 'stream' ) : esc_html__( 'deactivated', 'stream' )
@@ -362,7 +374,7 @@ class Connector_Jetpack extends Connector {
362
  $action = $method;
363
  $meta = compact( 'user_id', 'user_email', 'user_login' );
364
  $message = sprintf(
365
- // translators: Placeholders refer to a user display name, a status, and the connection either "from" or "to" (e.g. "Jane Doe", "unlinked", "from")
366
  __( '%1$s\'s account %2$s %3$s Jetpack', 'stream' ),
367
  $user->display_name,
368
  ( 'unlink' === $action ) ? esc_html__( 'unlinked', 'stream' ) : esc_html__( 'linked', 'stream' ),
@@ -372,7 +384,8 @@ class Connector_Jetpack extends Connector {
372
  $context = 'blogs';
373
  $action = str_replace( 'subsite', '', $method );
374
  $is_multisite = ( 0 === strpos( $method, 'subsite' ) );
375
- $blog_id = $is_multisite ? ( isset( $_GET['site_id'] ) ? intval( wp_unslash( $_GET['site_id'] ) ) : null ) : get_current_blog_id(); // phpcs: input var okay, CSRF okay
 
376
 
377
  if ( empty( $blog_id ) ) {
378
  return;
@@ -380,7 +393,7 @@ class Connector_Jetpack extends Connector {
380
 
381
  if ( ! $is_multisite ) {
382
  $message = sprintf(
383
- // translators: Placeholder refers to a connection status. Either "connected to" or "disconnected from".
384
  __( 'Site %s Jetpack', 'stream' ),
385
  ( 'register' === $action ) ? esc_html__( 'connected to', 'stream' ) : esc_html__( 'disconnected from', 'stream' )
386
  );
@@ -394,7 +407,7 @@ class Connector_Jetpack extends Connector {
394
  $meta += compact( 'blog_id', 'blog_name' );
395
 
396
  $message = sprintf(
397
- // translators: Placeholder refers to a connection status. Either "connected to" or "disconnected from".
398
  __( '"%1$s" blog %2$s Jetpack', 'stream' ),
399
  $blog_name,
400
  ( 'register' === $action ) ? esc_html__( 'connected to', 'stream' ) : esc_html__( 'disconnected from', 'stream' )
@@ -418,7 +431,7 @@ class Connector_Jetpack extends Connector {
418
  /**
419
  * Track visible/enabled sharing services ( buttons )
420
  *
421
- * @param string $state
422
  */
423
  public function callback_sharing_get_services_state( $state ) {
424
  $this->log(
@@ -430,14 +443,32 @@ class Connector_Jetpack extends Connector {
430
  );
431
  }
432
 
 
 
 
 
 
 
 
433
  public function callback_update_option( $option, $old, $new ) {
434
  $this->check( $option, $old, $new );
435
  }
436
 
 
 
 
 
 
 
437
  public function callback_add_option( $option, $val ) {
438
  $this->check( $option, null, $val );
439
  }
440
 
 
 
 
 
 
441
  public function callback_delete_option( $option ) {
442
  $this->check( $option, null, null );
443
  }
@@ -453,7 +484,7 @@ class Connector_Jetpack extends Connector {
453
  }
454
 
455
  $this->log(
456
- // translators: Placeholder refers to a status (e.g. "activated")
457
  __( 'Monitor notifications %s', 'stream' ),
458
  array(
459
  'status' => $active ? esc_html__( 'activated', 'stream' ) : esc_html__( 'deactivated', 'stream' ),
@@ -467,18 +498,39 @@ class Connector_Jetpack extends Connector {
467
  );
468
  }
469
 
 
 
 
 
 
470
  public function callback_wp_ajax_jetpack_post_by_email_enable() {
471
  $this->track_post_by_email( true );
472
  }
473
 
 
 
 
 
 
474
  public function callback_wp_ajax_jetpack_post_by_email_regenerate() {
475
  $this->track_post_by_email( null );
476
  }
477
 
 
 
 
 
 
478
  public function callback_wp_ajax_jetpack_post_by_email_disable() {
479
  $this->track_post_by_email( false );
480
  }
481
 
 
 
 
 
 
 
482
  public function track_post_by_email( $status ) {
483
  if ( true === $status ) {
484
  $action = esc_html__( 'enabled', 'stream' );
@@ -491,7 +543,7 @@ class Connector_Jetpack extends Connector {
491
  $user = wp_get_current_user();
492
 
493
  $this->log(
494
- // translators: Placeholders refer to a user display name, and a status (e.g. "Jane Doe", "enabled")
495
  __( '%1$s %2$s Post by Email', 'stream' ),
496
  array(
497
  'user_displayname' => $user->display_name,
@@ -504,6 +556,13 @@ class Connector_Jetpack extends Connector {
504
  );
505
  }
506
 
 
 
 
 
 
 
 
507
  public function check( $option, $old_value, $new_value ) {
508
  if ( ! array_key_exists( $option, $this->options ) ) {
509
  return;
@@ -516,7 +575,7 @@ class Connector_Jetpack extends Connector {
516
  $option_title = $data['label'];
517
 
518
  $this->log(
519
- // translators: Placeholder refers to a setting name (e.g. "Language")
520
  __( '"%s" setting updated', 'stream' ),
521
  compact( 'option_title', 'option', 'old_value', 'new_value' ),
522
  null,
@@ -526,6 +585,12 @@ class Connector_Jetpack extends Connector {
526
  }
527
  }
528
 
 
 
 
 
 
 
529
  public function check_jetpack_options( $old_value, $new_value ) {
530
  $options = array();
531
 
@@ -544,7 +609,7 @@ class Connector_Jetpack extends Connector {
544
  continue;
545
  }
546
 
547
- if ( 0 === $option_value ) { // Skip updated array with updated members, we'll be logging those instead
548
  continue;
549
  }
550
 
@@ -564,6 +629,13 @@ class Connector_Jetpack extends Connector {
564
  }
565
  }
566
 
 
 
 
 
 
 
 
567
  public function check_hide_gplus( $old_value, $new_value ) {
568
  $status = ! is_null( $new_value );
569
 
@@ -572,7 +644,7 @@ class Connector_Jetpack extends Connector {
572
  }
573
 
574
  $this->log(
575
- // translators: Placeholder refers to a status (e.g. "enabled")
576
  __( 'G+ profile display %s', 'stream' ),
577
  array(
578
  'action' => $status ? esc_html__( 'enabled', 'stream' ) : esc_html__( 'disabled', 'stream' ),
@@ -583,6 +655,13 @@ class Connector_Jetpack extends Connector {
583
  );
584
  }
585
 
 
 
 
 
 
 
 
586
  public function check_gplus_authors( $old_value, $new_value ) {
587
  unset( $old_value );
588
 
@@ -590,7 +669,7 @@ class Connector_Jetpack extends Connector {
590
  $connected = is_array( $new_value ) && array_key_exists( $user->ID, $new_value );
591
 
592
  $this->log(
593
- // translators: Placeholders refer to a user display name, and a status (e.g. "Jane Doe", "connected")
594
  __( '%1$s\'s Google+ account %2$s', 'stream' ),
595
  array(
596
  'display_name' => $user->display_name,
@@ -603,15 +682,22 @@ class Connector_Jetpack extends Connector {
603
  );
604
  }
605
 
 
 
 
 
 
 
 
606
  public function check_sharedaddy_disable_resources( $old_value, $new_value ) {
607
  if ( $old_value === $new_value ) {
608
  return;
609
  }
610
 
611
- $status = ! $new_value ? 'enabled' : 'disabled'; // disabled = 1
612
 
613
  $this->log(
614
- // translators: Placeholder refers to a status (e.g. "enabled")
615
  __( 'Sharing CSS/JS %s', 'stream' ),
616
  compact( 'status', 'old_value', 'new_value' ),
617
  null,
@@ -623,7 +709,7 @@ class Connector_Jetpack extends Connector {
623
  /**
624
  * Override connector log for our own Settings / Actions
625
  *
626
- * @param array $data
627
  *
628
  * @return array|bool
629
  */
@@ -632,7 +718,7 @@ class Connector_Jetpack extends Connector {
632
  return $data;
633
  }
634
 
635
- // Handling our Settings
636
  if ( 'settings' === $data['connector'] && isset( $this->options_override[ $data['args']['option'] ] ) ) {
637
  if ( isset( $data['args']['option_key'] ) ) {
638
  $overrides = $this->options_override[ $data['args']['option'] ][ $data['args']['option_key'] ];
@@ -663,15 +749,21 @@ class Connector_Jetpack extends Connector {
663
  return $data;
664
  }
665
 
 
 
 
 
 
 
666
  private function get_settings_def( $key, $value = null ) {
667
- // Sharing
668
  if ( 0 === strpos( $key, 'publicize_connections::' ) ) {
669
  global $publicize_ui;
670
 
671
  $name = str_replace( 'publicize_connections::', '', $key );
672
 
673
  return array(
674
- // translators: Placeholders refer to a service, and a status (e.g. "Facebook", "added")
675
  'message' => esc_html__( '%1$s connection %2$s', 'stream' ),
676
  'meta' => array(
677
  'connection' => $publicize_ui->publicize->get_service_label( $name ),
@@ -696,7 +788,7 @@ class Connector_Jetpack extends Connector {
696
  }
697
 
698
  return array(
699
- // translators: Placeholder refers to a setting name (e.g. "Language")
700
  'message' => esc_html__( '"%s" setting updated', 'stream' ),
701
  'meta' => array(
702
  'option_name' => $options[ $name ],
1
  <?php
2
+ /**
3
+ * Connector for Jetpack
4
+ *
5
+ * @package WP_Stream
6
+ */
7
+
8
  namespace WP_Stream;
9
 
10
+ /**
11
+ * Class - Connector_Jetpack
12
+ */
13
  class Connector_Jetpack extends Connector {
14
  /**
15
  * Connector slug
142
  *
143
  * @filter wp_stream_action_links_{connector}
144
  *
145
+ * @param array $links Previous links registered.
146
+ * @param object $record Stream record.
147
  *
148
  * @return array Action links
149
  */
185
  );
186
  }
187
  } elseif ( \Jetpack::is_module_active( str_replace( 'jetpack-', '', $record->context ) ) ) {
188
+ $slug = str_replace( 'jetpack-', '', $record->context ); // handling jetpack-comment anomaly.
189
 
190
  if ( apply_filters( 'jetpack_module_configurable_' . $slug, false ) ) {
191
  $links[ esc_html__( 'Configure module', 'stream' ) ] = \Jetpack::module_configuration_url( $slug );
196
  return $links;
197
  }
198
 
199
+ /**
200
+ * Register all context hooks
201
+ */
202
  public function register() {
203
  parent::register();
204
 
206
 
207
  $this->options = array(
208
  'jetpack_options' => null,
209
+ // Sharing module.
210
  'hide_gplus' => null,
211
  'gplus_authors' => null,
212
  'sharing-options' => array(
218
  'label' => esc_html__( 'Twitter site tag', 'stream' ),
219
  'context' => 'sharedaddy',
220
  ),
221
+ // Stats module.
222
  'stats_options' => array(
223
  'label' => esc_html__( 'WordPress.com Stats', 'stream' ),
224
  'context' => 'stats',
225
  ),
226
+ // Comments.
227
  'jetpack_comment_form_color_scheme' => array(
228
  'label' => esc_html__( 'Color Scheme', 'stream' ),
229
  'context' => 'jetpack-comments',
230
  ),
231
+ // Likes.
232
  'disabled_likes' => array(
233
  'label' => esc_html__( 'WP.com Site-wide Likes', 'stream' ),
234
  'context' => 'likes',
235
  ),
236
+ // Mobile.
237
  'wp_mobile_excerpt' => array(
238
  'label' => esc_html__( 'Excerpts appearance', 'stream' ),
239
  'context' => 'minileven',
245
  );
246
 
247
  $this->options_override = array(
248
+ // Carousel Module.
249
  'carousel_background_color' => array(
250
  'label' => esc_html__( 'Background color', 'stream' ),
251
  'context' => 'carousel',
254
  'label' => esc_html__( 'Metadata', 'stream' ),
255
  'context' => 'carousel',
256
  ),
257
+ // Subscriptions.
258
  'stb_enabled' => array(
259
  'label' => esc_html__( 'Follow blog comment form button', 'stream' ),
260
  'context' => 'subscriptions',
263
  'label' => esc_html__( 'Follow comments form button', 'stream' ),
264
  'context' => 'subscriptions',
265
  ),
266
+ // Jetpack comments.
267
  'highlander_comment_form_prompt' => array(
268
  'label' => esc_html__( 'Greeting Text', 'stream' ),
269
  'context' => 'jetpack-comments',
270
  ),
271
+ // Infinite Scroll.
272
  'infinite_scroll_google_analytics' => array(
273
  'label' => esc_html__( 'Infinite Scroll Google Analytics', 'stream' ),
274
  'context' => 'infinite-scroll',
275
  ),
276
+ // Protect.
277
  'jetpack_protect_blocked_attempts' => array(
278
  'label' => esc_html__( 'Blocked Attempts', 'stream' ),
279
  'context' => 'protect',
280
  ),
281
+ // SSO.
282
  'jetpack_sso_require_two_step' => array(
283
  'label' => esc_html__( 'Require Two-Step Authentication', 'stream' ),
284
  'context' => 'sso',
287
  'label' => esc_html__( 'Match by Email', 'stream' ),
288
  'context' => 'sso',
289
  ),
290
+ // Related posts.
291
  'jetpack_relatedposts' => array(
292
  'show_headline' => array(
293
  'label' => esc_html__( 'Show Related Posts Headline', 'stream' ),
298
  'context' => 'related-posts',
299
  ),
300
  ),
301
+ // Site verification.
302
  'verification_services_codes' => array(
303
  'google' => array(
304
  'label' => esc_html__( 'Google Webmaster Tools Token', 'stream' ),
313
  'context' => 'verification-tools',
314
  ),
315
  ),
316
+ // Tiled galleries.
317
  'tiled_galleries' => array(
318
  'label' => esc_html__( 'Tiled Galleries', 'stream' ),
319
  'context' => 'tiled-gallery',
328
  * - Registration/Disconnection of blogs
329
  * - Authorization/unlinking of users
330
  *
331
+ * @param array $entry Entry data.
332
  */
333
  public function callback_jetpack_log_entry( array $entry ) {
334
  if ( isset( $entry['code'] ) ) {
355
  $action = $method . 'd';
356
  $meta = compact( 'module_slug' );
357
  $message = sprintf(
358
+ /* translators: %1$s: a module name, %2$s a status (e.g. "Photon", "activated") */
359
  __( '%1$s module %2$s', 'stream' ),
360
  $module_name,
361
  ( 'activated' === $action ) ? esc_html__( 'activated', 'stream' ) : esc_html__( 'deactivated', 'stream' )
374
  $action = $method;
375
  $meta = compact( 'user_id', 'user_email', 'user_login' );
376
  $message = sprintf(
377
+ /* translators: %1$s: a user display name, %2$s: a status, %3$s: the connection either "from" or "to" (e.g. "Jane Doe", "unlinked", "from") */
378
  __( '%1$s\'s account %2$s %3$s Jetpack', 'stream' ),
379
  $user->display_name,
380
  ( 'unlink' === $action ) ? esc_html__( 'unlinked', 'stream' ) : esc_html__( 'linked', 'stream' ),
384
  $context = 'blogs';
385
  $action = str_replace( 'subsite', '', $method );
386
  $is_multisite = ( 0 === strpos( $method, 'subsite' ) );
387
+ // @codingStandardsIgnoreLine
388
+ $blog_id = $is_multisite ? ( isset( $_GET['site_id'] ) ? intval( wp_unslash( $_GET['site_id'] ) ) : null ) : get_current_blog_id();
389
 
390
  if ( empty( $blog_id ) ) {
391
  return;
393
 
394
  if ( ! $is_multisite ) {
395
  $message = sprintf(
396
+ /* translators: %s: a connection status. Either "connected to" or "disconnected from". */
397
  __( 'Site %s Jetpack', 'stream' ),
398
  ( 'register' === $action ) ? esc_html__( 'connected to', 'stream' ) : esc_html__( 'disconnected from', 'stream' )
399
  );
407
  $meta += compact( 'blog_id', 'blog_name' );
408
 
409
  $message = sprintf(
410
+ /* translators: %1$s: Blog name, %2$s: a connection status. Either "connected to" or "disconnected from". */
411
  __( '"%1$s" blog %2$s Jetpack', 'stream' ),
412
  $blog_name,
413
  ( 'register' === $action ) ? esc_html__( 'connected to', 'stream' ) : esc_html__( 'disconnected from', 'stream' )
431
  /**
432
  * Track visible/enabled sharing services ( buttons )
433
  *
434
+ * @param string $state Service state.
435
  */
436
  public function callback_sharing_get_services_state( $state ) {
437
  $this->log(
443
  );
444
  }
445
 
446
+ /**
447
+ * Track Jetpack-specific option changes.
448
+ *
449
+ * @param string $option Option key.
450
+ * @param string $old Old value.
451
+ * @param string $new New value.
452
+ */
453
  public function callback_update_option( $option, $old, $new ) {
454
  $this->check( $option, $old, $new );
455
  }
456
 
457
+ /**
458
+ * Track Jetpack-specific option creations.
459
+ *
460
+ * @param string $option Option key.
461
+ * @param string $val Value.
462
+ */
463
  public function callback_add_option( $option, $val ) {
464
  $this->check( $option, null, $val );
465
  }
466
 
467
+ /**
468
+ * Track Jetpack-specific option deletions.
469
+ *
470
+ * @param string $option Option key.
471
+ */
472
  public function callback_delete_option( $option ) {
473
  $this->check( $option, null, null );
474
  }
484
  }
485
 
486
  $this->log(
487
+ /* translators: %s: a status (e.g. "activated") */
488
  __( 'Monitor notifications %s', 'stream' ),
489
  array(
490
  'status' => $active ? esc_html__( 'activated', 'stream' ) : esc_html__( 'deactivated', 'stream' ),
498
  );
499
  }
500
 
501
+ /**
502
+ * Logs when user enables "post_by_email"
503
+ *
504
+ * @action wp_ajax_jetpack_post_by_email_enable
505
+ */
506
  public function callback_wp_ajax_jetpack_post_by_email_enable() {
507
  $this->track_post_by_email( true );
508
  }
509
 
510
+ /**
511
+ * Logs when user regenerates "post_by_email"
512
+ *
513
+ * @action wp_ajax_jetpack_post_by_email_regenerate
514
+ */
515
  public function callback_wp_ajax_jetpack_post_by_email_regenerate() {
516
  $this->track_post_by_email( null );
517
  }
518
 
519
+ /**
520
+ * Logs when user disables "post_by_email"
521
+ *
522
+ * @action wp_ajax_jetpack_post_by_email_disable
523
+ */
524
  public function callback_wp_ajax_jetpack_post_by_email_disable() {
525
  $this->track_post_by_email( false );
526
  }
527
 
528
+ /**
529
+ * Tracks changes a user post by email status
530
+ *
531
+ * @param string $status Status.
532
+ * @return void
533
+ */
534
  public function track_post_by_email( $status ) {
535
  if ( true === $status ) {
536
  $action = esc_html__( 'enabled', 'stream' );
543
  $user = wp_get_current_user();
544
 
545
  $this->log(
546
+ /* translators: %1$s: a user display name, %2$s: a status (e.g. "Jane Doe", "enabled") */
547
  __( '%1$s %2$s Post by Email', 'stream' ),
548
  array(
549
  'user_displayname' => $user->display_name,
556
  );
557
  }
558
 
559
+ /**
560
+ * Tracks Jetpack-specific option activity.
561
+ *
562
+ * @param string $option Option key.
563
+ * @param string $old_value Old value.
564
+ * @param string $new_value New value.
565
+ */
566
  public function check( $option, $old_value, $new_value ) {
567
  if ( ! array_key_exists( $option, $this->options ) ) {
568
  return;
575
  $option_title = $data['label'];
576
 
577
  $this->log(
578
+ /* translators: %s: a setting name (e.g. "Language") */
579
  __( '"%s" setting updated', 'stream' ),
580
  compact( 'option_title', 'option', 'old_value', 'new_value' ),
581
  null,
585
  }
586
  }
587
 
588
+ /**
589
+ * Track Jetpack-specific option activity.
590
+ *
591
+ * @param string $old_value Old value.
592
+ * @param string $new_value New value.
593
+ */
594
  public function check_jetpack_options( $old_value, $new_value ) {
595
  $options = array();
596
 
609
  continue;
610
  }
611
 
612
+ if ( 0 === $option_value ) { // Skip updated array with updated members, we'll be logging those instead.
613
  continue;
614
  }
615
 
629
  }
630
  }
631
 
632
+ /**
633
+ * Logs Google+ profile display status
634
+ *
635
+ * @param string $old_value Old status.
636
+ * @param string $new_value New status.
637
+ * @return null|bool
638
+ */
639
  public function check_hide_gplus( $old_value, $new_value ) {
640
  $status = ! is_null( $new_value );
641
 
644
  }
645
 
646
  $this->log(
647
+ /* translators: Placeholder refers to a status (e.g. "enabled") */
648
  __( 'G+ profile display %s', 'stream' ),
649
  array(
650
  'action' => $status ? esc_html__( 'enabled', 'stream' ) : esc_html__( 'disabled', 'stream' ),
655
  );
656
  }
657
 
658
+ /**
659
+ * Logs if current user's Google+ account connection status
660
+ *
661
+ * @param string $old_value Old status.
662
+ * @param string $new_value New status.
663
+ * @return void
664
+ */
665
  public function check_gplus_authors( $old_value, $new_value ) {
666
  unset( $old_value );
667
 
669
  $connected = is_array( $new_value ) && array_key_exists( $user->ID, $new_value );
670
 
671
  $this->log(
672
+ /* translators: %1$s: a user display name, %2$s: a status (e.g. "Jane Doe", "connected") */
673
  __( '%1$s\'s Google+ account %2$s', 'stream' ),
674
  array(
675
  'display_name' => $user->display_name,
682
  );
683
  }
684
 
685
+ /**
686
+ * Logs sharedaddy resource status.
687
+ *
688
+ * @param string $old_value Old status.
689
+ * @param string $new_value New status.
690
+ * @return void
691
+ */
692
  public function check_sharedaddy_disable_resources( $old_value, $new_value ) {
693
  if ( $old_value === $new_value ) {
694
  return;
695
  }
696
 
697
+ $status = ! $new_value ? 'enabled' : 'disabled'; // disabled = 1.
698
 
699
  $this->log(
700
+ /* translators: %s: a status (e.g. "enabled") */
701
  __( 'Sharing CSS/JS %s', 'stream' ),
702
  compact( 'status', 'old_value', 'new_value' ),
703
  null,
709
  /**
710
  * Override connector log for our own Settings / Actions
711
  *
712
+ * @param array $data Record data.
713
  *
714
  * @return array|bool
715
  */
718
  return $data;
719
  }
720
 
721
+ // Handling our Settings.
722
  if ( 'settings' === $data['connector'] && isset( $this->options_override[ $data['args']['option'] ] ) ) {
723
  if ( isset( $data['args']['option_key'] ) ) {
724
  $overrides = $this->options_override[ $data['args']['option'] ][ $data['args']['option_key'] ];
749
  return $data;
750
  }
751
 
752
+ /**
753
+ * Returns an option's status
754
+ *
755
+ * @param string $key Option key.
756
+ * @param string $value Option value.
757
+ */
758
  private function get_settings_def( $key, $value = null ) {
759
+ // Sharing.
760
  if ( 0 === strpos( $key, 'publicize_connections::' ) ) {
761
  global $publicize_ui;
762
 
763
  $name = str_replace( 'publicize_connections::', '', $key );
764
 
765
  return array(
766
+ /* translators: %1$s: a service, %2$s: a status (e.g. "Facebook", "added") */
767
  'message' => esc_html__( '%1$s connection %2$s', 'stream' ),
768
  'meta' => array(
769
  'connection' => $publicize_ui->publicize->get_service_label( $name ),
788
  }
789
 
790
  return array(
791
+ /* translators: %s: a setting name (e.g. "Language") */
792
  'message' => esc_html__( '"%s" setting updated', 'stream' ),
793
  'meta' => array(
794
  'option_name' => $options[ $name ],
connectors/class-connector-media.php CHANGED
@@ -1,6 +1,15 @@
1
  <?php
 
 
 
 
 
 
2
  namespace WP_Stream;
3
 
 
 
 
4
  class Connector_Media extends Connector {
5
  /**
6
  * Connector slug
@@ -71,7 +80,7 @@ class Connector_Media extends Connector {
71
  /**
72
  * Return the file type for an attachment which corresponds with a context label
73
  *
74
- * @param object $file_uri URI of the attachment
75
  *
76
  * @return string A file type which corresponds with a context label
77
  */
@@ -97,8 +106,8 @@ class Connector_Media extends Connector {
97
  *
98
  * @filter wp_stream_action_links_{connector}
99
  *
100
- * @param array $links Previous links registered
101
- * @param object $record Stream record
102
  *
103
  * @return array Action links
104
  */
@@ -122,19 +131,19 @@ class Connector_Media extends Connector {
122
  *
123
  * @action add_attachment
124
  *
125
- * @param int $post_id
126
  */
127
  public function callback_add_attachment( $post_id ) {
128
  $post = get_post( $post_id );
129
  if ( $post->post_parent ) {
130
- // translators: Placeholders refer to an attachment title, and a post title (e.g. "PIC001", "Hello World")
131
  $message = _x(
132
  'Attached "%1$s" to "%2$s"',
133
  '1: Attachment title, 2: Parent post title',
134
  'stream'
135
  );
136
  } else {
137
- // translators: Placeholder refers to an attachment title (e.g. "PIC001")
138
  $message = esc_html__( 'Added "%s" to Media library', 'stream' );
139
  }
140
 
@@ -159,14 +168,14 @@ class Connector_Media extends Connector {
159
  *
160
  * @action edit_attachment
161
  *
162
- * @param int $post_id
163
  */
164
  public function callback_edit_attachment( $post_id ) {
165
  $post = get_post( $post_id );
166
  $name = $post->post_title;
167
  $attachment_type = $this->get_attachment_type( $post->guid );
168
 
169
- // translators: Placeholder refers to an attachment title (e.g. "PIC001")
170
  $message = esc_html__( 'Updated "%s"', 'stream' );
171
 
172
  $this->log(
@@ -183,7 +192,7 @@ class Connector_Media extends Connector {
183
  *
184
  * @action delete_attachment
185
  *
186
- * @param int $post_id
187
  */
188
  public function callback_delete_attachment( $post_id ) {
189
  $post = get_post( $post_id );
@@ -193,7 +202,7 @@ class Connector_Media extends Connector {
193
  $url = $post->guid;
194
  $attachment_type = $this->get_attachment_type( $post->guid );
195
 
196
- // translators: Placeholder refers to an attachment title (e.g. "PIC001")
197
  $message = esc_html__( 'Deleted "%s"', 'stream' );
198
 
199
  $this->log(
@@ -210,11 +219,11 @@ class Connector_Media extends Connector {
210
  *
211
  * @action delete_attachment
212
  *
213
- * @param string $dummy
214
- * @param string $filename
215
- * @param string $image
216
- * @param string $mime_type
217
- * @param int $post_id
218
  */
219
  public function callback_wp_save_image_editor_file( $dummy, $filename, $image, $mime_type, $post_id ) {
220
  unset( $dummy );
@@ -227,7 +236,7 @@ class Connector_Media extends Connector {
227
  $attachment_type = $this->get_attachment_type( $post->guid );
228
 
229
  $this->log(
230
- // translators: Placeholder refers to an attachment title (e.g. "PIC001")
231
  __( 'Edited image "%s"', 'stream' ),
232
  compact( 'name', 'filename', 'post_id' ),
233
  $post_id,
@@ -236,6 +245,17 @@ class Connector_Media extends Connector {
236
  );
237
  }
238
 
 
 
 
 
 
 
 
 
 
 
 
239
  public function callback_wp_save_image_file( $dummy, $filename, $image, $mime_type, $post_id ) {
240
  return $this->callback_wp_save_image_editor_file( $dummy, $filename, $image, $mime_type, $post_id );
241
  }
1
  <?php
2
+ /**
3
+ * Connector for Media files
4
+ *
5
+ * @package WP_Stream
6
+ */
7
+
8
  namespace WP_Stream;
9
 
10
+ /**
11
+ * Class - Connector_Media
12
+ */
13
  class Connector_Media extends Connector {
14
  /**
15
  * Connector slug
80
  /**
81
  * Return the file type for an attachment which corresponds with a context label
82
  *
83
+ * @param object $file_uri URI of the attachment.
84
  *
85
  * @return string A file type which corresponds with a context label
86
  */
106
  *
107
  * @filter wp_stream_action_links_{connector}
108
  *
109
+ * @param array $links Previous links registered.
110
+ * @param object $record Stream record.
111
  *
112
  * @return array Action links
113
  */
131
  *
132
  * @action add_attachment
133
  *
134
+ * @param int $post_id Post ID.
135
  */
136
  public function callback_add_attachment( $post_id ) {
137
  $post = get_post( $post_id );
138
  if ( $post->post_parent ) {
139
+ /* translators: %1$s: an attachment title, %2$s: a post title (e.g. "PIC001", "Hello World") */
140
  $message = _x(
141
  'Attached "%1$s" to "%2$s"',
142
  '1: Attachment title, 2: Parent post title',
143
  'stream'
144
  );
145
  } else {
146
+ /* translators: %s: an attachment title (e.g. "PIC001") */
147
  $message = esc_html__( 'Added "%s" to Media library', 'stream' );
148
  }
149
 
168
  *
169
  * @action edit_attachment
170
  *
171
+ * @param int $post_id Post ID.
172
  */
173
  public function callback_edit_attachment( $post_id ) {
174
  $post = get_post( $post_id );
175
  $name = $post->post_title;
176
  $attachment_type = $this->get_attachment_type( $post->guid );
177
 
178
+ /* translators: %s: an attachment title (e.g. "PIC001") */
179
  $message = esc_html__( 'Updated "%s"', 'stream' );
180
 
181
  $this->log(
192
  *
193
  * @action delete_attachment
194
  *
195
+ * @param int $post_id Post ID.
196
  */
197
  public function callback_delete_attachment( $post_id ) {
198
  $post = get_post( $post_id );
202
  $url = $post->guid;
203
  $attachment_type = $this->get_attachment_type( $post->guid );
204
 
205
+ /* translators: %s: an attachment title (e.g. "PIC001") */
206
  $message = esc_html__( 'Deleted "%s"', 'stream' );
207
 
208
  $this->log(
219
  *
220
  * @action delete_attachment
221
  *
222
+ * @param string $dummy Unused.
223
+ * @param string $filename Filename.
224
+ * @param string $image Unused.
225
+ * @param string $mime_type Unused.
226
+ * @param int $post_id Post ID.
227
  */
228
  public function callback_wp_save_image_editor_file( $dummy, $filename, $image, $mime_type, $post_id ) {
229
  unset( $dummy );
236
  $attachment_type = $this->get_attachment_type( $post->guid );
237
 
238
  $this->log(
239
+ /* translators: Placeholder refers to an attachment title (e.g. "PIC001") */
240
  __( 'Edited image "%s"', 'stream' ),
241
  compact( 'name', 'filename', 'post_id' ),
242
  $post_id,
245
  );
246
  }
247
 
248
+ /**
249
+ * Logs updates made in the image editor upon saving
250
+ *
251
+ * @action delete_attachment
252
+ *
253
+ * @param string $dummy Unused.
254
+ * @param string $filename Filename.
255
+ * @param string $image Unused.
256
+ * @param string $mime_type Unused.
257
+ * @param int $post_id Post ID.
258
+ */
259
  public function callback_wp_save_image_file( $dummy, $filename, $image, $mime_type, $post_id ) {
260
  return $this->callback_wp_save_image_editor_file( $dummy, $filename, $image, $mime_type, $post_id );
261
  }
connectors/class-connector-menus.php CHANGED
@@ -1,6 +1,15 @@
1
  <?php
 
 
 
 
 
 
2
  namespace WP_Stream;
3
 
 
 
 
4
  class Connector_Menus extends Connector {
5
  /**
6
  * Connector slug
@@ -73,6 +82,9 @@ class Connector_Menus extends Connector {
73
  return $labels;
74
  }
75
 
 
 
 
76
  public function register() {
77
  parent::register();
78
 
@@ -84,8 +96,8 @@ class Connector_Menus extends Connector {
84
  *
85
  * @filter wp_stream_action_links_{connector}
86
  *
87
- * @param array $links Previous links registered
88
- * @param object $record Stream record
89
  *
90
  * @return array Action links
91
  */
@@ -107,14 +119,14 @@ class Connector_Menus extends Connector {
107
  *
108
  * @action wp_create_nav_menu
109
  *
110
- * @param int $menu_id
111
- * @param array $menu_data
112
  */
113
  public function callback_wp_create_nav_menu( $menu_id, $menu_data ) {
114
  $name = $menu_data['menu-name'];
115
 
116
  $this->log(
117
- // translators: Placeholder refers to a menu name (e.g. "Primary Menu")
118
  __( 'Created new menu "%s"', 'stream' ),
119
  compact( 'name', 'menu_id' ),
120
  $menu_id,
@@ -128,8 +140,8 @@ class Connector_Menus extends Connector {
128
  *
129
  * @action wp_update_nav_menu
130
  *
131
- * @param int $menu_id
132
- * @param array $menu_data
133
  */
134
  public function callback_wp_update_nav_menu( $menu_id, $menu_data = array() ) {
135
  if ( empty( $menu_data ) ) {
@@ -139,7 +151,7 @@ class Connector_Menus extends Connector {
139
  $name = $menu_data['menu-name'];
140
 
141
  $this->log(
142
- // translators: Placeholder refers to a menu name (e.g. "Primary Menu")
143
  _x( 'Updated menu "%s"', 'Menu name', 'stream' ),
144
  compact( 'name', 'menu_id', 'menu_data' ),
145
  $menu_id,
@@ -153,9 +165,9 @@ class Connector_Menus extends Connector {
153
  *
154
  * @action delete_nav_menu
155
  *
156
- * @param object $term
157
- * @param int $tt_id
158
- * @param object $deleted_term
159
  */
160
  public function callback_delete_nav_menu( $term, $tt_id, $deleted_term ) {
161
  unset( $tt_id );
@@ -164,7 +176,7 @@ class Connector_Menus extends Connector {
164
  $menu_id = $term->term_id;
165
 
166
  $this->log(
167
- // translators: Placeholder refers to a menu name (e.g. "Primary Menu")
168
  _x( 'Deleted "%s"', 'Menu name', 'stream' ),
169
  compact( 'name', 'menu_id' ),
170
  $menu_id,
@@ -178,11 +190,11 @@ class Connector_Menus extends Connector {
178
  *
179
  * @action update_option_theme_mods_{$stylesheet}
180
  *
181
- * @param array $old
182
- * @param array $new
183
  */
184
  public function callback_update_option_theme_mods( $old, $new ) {
185
- // Disable if we're switching themes
186
  if ( did_action( 'after_switch_theme' ) ) {
187
  return;
188
  }
@@ -190,7 +202,7 @@ class Connector_Menus extends Connector {
190
  $key = 'nav_menu_locations';
191
 
192
  if ( ! isset( $new[ $key ] ) ) {
193
- return; // Switching themes ?
194
  }
195
 
196
  if ( $old[ $key ] === $new[ $key ] ) {
@@ -212,7 +224,7 @@ class Connector_Menus extends Connector {
212
  if ( empty( $new[ $key ][ $location_id ] ) ) {
213
  $action = 'unassigned';
214
  $menu_id = isset( $old[ $key ][ $location_id ] ) ? $old[ $key ][ $location_id ] : 0;
215
- // translators: Placeholders refer to a menu name, and a theme location (e.g. "Primary Menu", "primary_nav")
216
  $message = _x(
217
  '"%1$s" has been unassigned from "%2$s"',
218
  '1: Menu name, 2: Theme location',
@@ -221,7 +233,7 @@ class Connector_Menus extends Connector {
221
  } else {
222
  $action = 'assigned';
223
  $menu_id = isset( $new[ $key ][ $location_id ] ) ? $new[ $key ][ $location_id ] : 0;
224
- // translators: Placeholders refer to a menu name, and a theme location (e.g. "Primary Menu", "primary_nav")
225
  $message = _x(
226
  '"%1$s" has been assigned to "%2$s"',
227
  '1: Menu name, 2: Theme location',
@@ -232,7 +244,7 @@ class Connector_Menus extends Connector {
232
  $menu = get_term( $menu_id, 'nav_menu' );
233
 
234
  if ( ! $menu || is_wp_error( $menu ) ) {
235
- continue; // This is a deleted menu
236
  }
237
 
238
  $name = $menu->name;
1
  <?php
2
+ /**
3
+ * Connector for Menus
4
+ *
5
+ * @package WP_Stream
6
+ */
7
+
8
  namespace WP_Stream;
9
 
10
+ /**
11
+ * Class - Connector_Menus
12
+ */
13
  class Connector_Menus extends Connector {
14
  /**
15
  * Connector slug
82
  return $labels;
83
  }
84
 
85
+ /**
86
+ * Registers connection.
87
+ */
88
  public function register() {
89
  parent::register();
90
 
96
  *
97
  * @filter wp_stream_action_links_{connector}
98
  *
99
+ * @param array $links Previous links registered.
100
+ * @param object $record Stream record.
101
  *
102
  * @return array Action links
103
  */
119
  *
120
  * @action wp_create_nav_menu
121
  *
122
+ * @param int $menu_id Menu ID.
123
+ * @param array $menu_data Menu data.
124
  */
125
  public function callback_wp_create_nav_menu( $menu_id, $menu_data ) {
126
  $name = $menu_data['menu-name'];
127
 
128
  $this->log(
129
+ /* translators: %s: a menu name (e.g. "Primary Menu") */
130
  __( 'Created new menu "%s"', 'stream' ),
131
  compact( 'name', 'menu_id' ),
132
  $menu_id,
140
  *
141
  * @action wp_update_nav_menu
142
  *
143
+ * @param int $menu_id Menu ID.
144
+ * @param array $menu_data Menu data.
145
  */
146
  public function callback_wp_update_nav_menu( $menu_id, $menu_data = array() ) {
147
  if ( empty( $menu_data ) ) {
151
  $name = $menu_data['menu-name'];
152
 
153
  $this->log(
154
+ /* translators: %s: a menu name (e.g. "Primary Menu") */
155
  _x( 'Updated menu "%s"', 'Menu name', 'stream' ),
156
  compact( 'name', 'menu_id', 'menu_data' ),
157
  $menu_id,
165
  *
166
  * @action delete_nav_menu
167
  *
168
+ * @param object $term Term.
169
+ * @param int $tt_id Term ID.
170
+ * @param object $deleted_term Deleted term.
171
  */
172
  public function callback_delete_nav_menu( $term, $tt_id, $deleted_term ) {
173
  unset( $tt_id );
176
  $menu_id = $term->term_id;
177
 
178
  $this->log(
179
+ /* translators: %s: a menu name (e.g. "Primary Menu") */
180
  _x( 'Deleted "%s"', 'Menu name', 'stream' ),
181
  compact( 'name', 'menu_id' ),
182
  $menu_id,
190
  *
191
  * @action update_option_theme_mods_{$stylesheet}
192
  *
193
+ * @param array $old Old theme data.
194
+ * @param array $new New theme data.
195
  */
196
  public function callback_update_option_theme_mods( $old, $new ) {
197
+ // Disable if we're switching themes.
198
  if ( did_action( 'after_switch_theme' ) ) {
199
  return;
200
  }
202
  $key = 'nav_menu_locations';
203
 
204
  if ( ! isset( $new[ $key ] ) ) {
205
+ return; // Switching themes ?.
206
  }
207
 
208
  if ( $old[ $key ] === $new[ $key ] ) {
224
  if ( empty( $new[ $key ][ $location_id ] ) ) {
225
  $action = 'unassigned';
226
  $menu_id = isset( $old[ $key ][ $location_id ] ) ? $old[ $key ][ $location_id ] : 0;
227
+ /* translators: %1$s: a menu name, %2$s: a theme location (e.g. "Primary Menu", "primary_nav") */
228
  $message = _x(
229
  '"%1$s" has been unassigned from "%2$s"',
230
  '1: Menu name, 2: Theme location',
233
  } else {
234
  $action = 'assigned';
235
  $menu_id = isset( $new[ $key ][ $location_id ] ) ? $new[ $key ][ $location_id ] : 0;
236
+ /* translators: %1$s: a menu name, %2$s a theme location (e.g. "Primary Menu", "primary_nav") */
237
  $message = _x(
238
  '"%1$s" has been assigned to "%2$s"',
239
  '1: Menu name, 2: Theme location',
244
  $menu = get_term( $menu_id, 'nav_menu' );
245
 
246
  if ( ! $menu || is_wp_error( $menu ) ) {
247
+ continue; // This is a deleted menu.
248
  }
249
 
250
  $name = $menu->name;
connectors/class-connector-mercator.php CHANGED
@@ -1,7 +1,15 @@
1
  <?php
 
 
 
 
 
2
 
3
  namespace WP_Stream;
4
 
 
 
 
5
  class Connector_Mercator extends Connector {
6
  /**
7
  * Connector slug
@@ -65,7 +73,7 @@ class Connector_Mercator extends Connector {
65
 
66
  foreach ( $blogs as $blog ) {
67
  $blog_details = get_site( $blog->blog_id );
68
- $key = sanitize_key( $blog_details->blogname );
69
  $labels[ $key ] = $blog_details->blogname;
70
  }
71
  }
@@ -78,8 +86,8 @@ class Connector_Mercator extends Connector {
78
  *
79
  * @filter wp_stream_action_links_{connector}
80
  *
81
- * @param array $links
82
- * @param Record $record
83
  *
84
  * @return array
85
  */
@@ -112,14 +120,14 @@ class Connector_Mercator extends Connector {
112
  /**
113
  * Log if domain is made primary.
114
  *
115
- * @param $mapping
116
  */
117
  public function callback_mercator_mapping_made_primary( $mapping ) {
118
  $blog_id = $mapping->get_site_id();
119
  $blog = get_site( $blog_id );
120
 
121
  $this->log(
122
- // translators: Placeholder refers to site name (e.g. "FooBar Blog")
123
  _x(
124
  '"%1$s" domain alias was make primary for "%2$s"',
125
  '1. Domain alias 2. Site name',
@@ -138,8 +146,8 @@ class Connector_Mercator extends Connector {
138
  /**
139
  * Log if domain alias is updated.
140
  *
141
- * @param $mapping
142
- * @param $old_mapping
143
  */
144
  public function callback_mercator_mapping_updated( $mapping, $old_mapping ) {
145
 
@@ -147,7 +155,7 @@ class Connector_Mercator extends Connector {
147
  $blog = get_site( $blog_id );
148
 
149
  $this->log(
150
- // translators: Placeholder refers to site name (e.g. "FooBar Blog")
151
  _x(
152
  'The domain alias "%1$s" was updated to "%2$s" for site "%3$s"',
153
  '1. Old Domain alias 2. Domain alias 2. Site name',
@@ -168,7 +176,7 @@ class Connector_Mercator extends Connector {
168
  /**
169
  * Log if domain alias is deleted.
170
  *
171
- * @param $mapping
172
  */
173
  public function callback_mercator_mapping_deleted( $mapping ) {
174
 
@@ -176,7 +184,7 @@ class Connector_Mercator extends Connector {
176
  $blog = get_site( $blog_id );
177
 
178
  $this->log(
179
- // translators: Placeholder refers to site name (e.g. "FooBar Blog")
180
  _x(
181
  '"%1$s" domain alias was deleted for "%2$s"',
182
  '1. Domain alias 2. Site name',
@@ -196,14 +204,14 @@ class Connector_Mercator extends Connector {
196
  /**
197
  * Log if domain alias is created.
198
  *
199
- * @param $mapping
200
  */
201
  public function callback_mercator_mapping_created( $mapping ) {
202
  $blog_id = $mapping->get_site_id();
203
  $blog = get_site( $blog_id );
204
 
205
  $this->log(
206
- // translators: Placeholder refers to site name (e.g. "FooBar Blog")
207
  _x(
208
  '"%1$s" domain alias was created for "%2$s"',
209
  '1. Domain alias 2. Site name',
1
  <?php
2
+ /**
3
+ * Connector for Mercator
4
+ *
5
+ * @package WP_Stream
6
+ */
7
 
8
  namespace WP_Stream;
9
 
10
+ /**
11
+ * Class - Connector_Mercator
12
+ */
13
  class Connector_Mercator extends Connector {
14
  /**
15
  * Connector slug
73
 
74
  foreach ( $blogs as $blog ) {
75
  $blog_details = get_site( $blog->blog_id );
76
+ $key = sprintf( 'blog-%d', $blog->blog_id );
77
  $labels[ $key ] = $blog_details->blogname;
78
  }
79
  }
86
  *
87
  * @filter wp_stream_action_links_{connector}
88
  *
89
+ * @param array $links Previous links registered.
90
+ * @param object $record Stream record.
91
  *
92
  * @return array
93
  */
120
  /**
121
  * Log if domain is made primary.
122
  *
123
+ * @param object $mapping Mapping object.
124
  */
125
  public function callback_mercator_mapping_made_primary( $mapping ) {
126
  $blog_id = $mapping->get_site_id();
127
  $blog = get_site( $blog_id );
128
 
129
  $this->log(
130
+ /* translators: %1$s: domain alias, %2$s: site name (e.g. "FooBar Blog") */
131
  _x(
132
  '"%1$s" domain alias was make primary for "%2$s"',
133
  '1. Domain alias 2. Site name',
146
  /**
147
  * Log if domain alias is updated.
148
  *
149
+ * @param object $mapping Mapping object.
150
+ * @param object $old_mapping Old mapping object from before update.
151
  */
152
  public function callback_mercator_mapping_updated( $mapping, $old_mapping ) {
153
 
155
  $blog = get_site( $blog_id );
156
 
157
  $this->log(
158
+ /* translators: %1$s: domain alias, %2$s: site name (e.g. "FooBar Blog") */
159
  _x(
160
  'The domain alias "%1$s" was updated to "%2$s" for site "%3$s"',
161
  '1. Old Domain alias 2. Domain alias 2. Site name',
176
  /**
177
  * Log if domain alias is deleted.
178
  *
179
+ * @param object $mapping Mapping of deleted alias.
180
  */
181
  public function callback_mercator_mapping_deleted( $mapping ) {
182
 
184
  $blog = get_site( $blog_id );
185
 
186
  $this->log(
187
+ /* translators: %1$s: domain alias, %2$s: site name (e.g. "FooBar Blog") */
188
  _x(
189
  '"%1$s" domain alias was deleted for "%2$s"',
190
  '1. Domain alias 2. Site name',
204
  /**
205
  * Log if domain alias is created.
206
  *
207
+ * @param object $mapping Mapping object.
208
  */
209
  public function callback_mercator_mapping_created( $mapping ) {
210
  $blog_id = $mapping->get_site_id();
211
  $blog = get_site( $blog_id );
212
 
213
  $this->log(
214
+ /* translators: %1$s: domain alias, %2$s: site name (e.g. "FooBar Blog") */
215
  _x(
216
  '"%1$s" domain alias was created for "%2$s"',
217
  '1. Domain alias 2. Site name',
connectors/class-connector-posts.php CHANGED
@@ -1,6 +1,15 @@
1
  <?php
 
 
 
 
 
 
2
  namespace WP_Stream;
3
 
 
 
 
4
  class Connector_Posts extends Connector {
5
  /**
6
  * Connector slug
@@ -71,8 +80,8 @@ class Connector_Posts extends Connector {
71
  *
72
  * @filter wp_stream_action_links_{connector}
73
  *
74
- * @param array $links Previous links registered
75
- * @param Record $record Stream record
76
  *
77
  * @return array Action links
78
  */
@@ -105,12 +114,12 @@ class Connector_Posts extends Connector {
105
  sprintf( 'delete-post_%d', $post->ID )
106
  );
107
 
108
- // translators: Placeholder refers to a post type singular name (e.g. "Post")
109
  $links[ sprintf( esc_html_x( 'Restore %s', 'Post type singular name', 'stream' ), $post_type_name ) ] = $untrash;
110
- // translators: Placeholder refers to a post type singular name (e.g. "Post")
111
  $links[ sprintf( esc_html_x( 'Delete %s Permenantly', 'Post type singular name', 'stream' ), $post_type_name ) ] = $delete;
112
  } else {
113
- // translators: Placeholder refers to a post type singular name (e.g. "Post")
114
  $links[ sprintf( esc_html_x( 'Edit %s', 'Post type singular name', 'stream' ), $post_type_name ) ] = get_edit_post_link( $post->ID );
115
 
116
  $view_link = get_permalink( $post->ID );
@@ -135,8 +144,8 @@ class Connector_Posts extends Connector {
135
  *
136
  * @action registered_post_type
137
  *
138
- * @param string $post_type Post type slug
139
- * @param array $args Arguments used to register the post type
140
  */
141
  public function registered_post_type( $post_type, $args ) {
142
  unset( $args );
@@ -152,9 +161,9 @@ class Connector_Posts extends Connector {
152
  *
153
  * @action transition_post_status
154
  *
155
- * @param mixed $new
156
- * @param mixed $old
157
- * @param \WP_Post $post
158
  */
159
  public function callback_transition_post_status( $new, $old, $post ) {
160
  if ( in_array( $post->post_type, $this->get_excluded_post_types(), true ) ) {
@@ -166,14 +175,14 @@ class Connector_Posts extends Connector {
166
  } elseif ( defined( 'DOING_AUTOSAVE' ) && DOING_AUTOSAVE ) {
167
  return;
168
  } elseif ( 'draft' === $new && 'publish' === $old ) {
169
- // translators: Placeholders refer to a post title, and a post type singular name (e.g. "Hello World", "Post")
170
  $summary = _x(
171
  '"%1$s" %2$s unpublished',
172
  '1: Post title, 2: Post type singular name',
173
  'stream'
174
  );
175
  } elseif ( 'trash' === $old && 'trash' !== $new ) {
176
- // translators: Placeholders refer to a post title, and a post type singular name (e.g. "Hello World", "Post")
177
  $summary = _x(
178
  '"%1$s" %2$s restored from trash',
179
  '1: Post title, 2: Post type singular name',
@@ -181,56 +190,56 @@ class Connector_Posts extends Connector {
181
  );
182
  $action = 'untrashed';
183
  } elseif ( 'draft' === $new && 'draft' === $old ) {
184
- // translators: Placeholders refer to a post title, and a post type singular name (e.g. "Hello World", "Post")
185
  $summary = _x(
186
  '"%1$s" %2$s draft saved',
187
  '1: Post title, 2: Post type singular name',
188
  'stream'
189
  );
190
  } elseif ( 'publish' === $new && 'draft' === $old ) {
191
- // translators: Placeholders refer to a post title, and a post type singular name (e.g. "Hello World", "Post")
192
  $summary = _x(
193
  '"%1$s" %2$s published',
194
  '1: Post title, 2: Post type singular name',
195
  'stream'
196
  );
197
  } elseif ( 'draft' === $new ) {
198
- // translators: Placeholders refer to a post title, and a post type singular name (e.g. "Hello World", "Post")
199
  $summary = _x(
200
  '"%1$s" %2$s drafted',
201
  '1: Post title, 2: Post type singular name',
202
  'stream'
203
  );
204
  } elseif ( 'pending' === $new ) {
205
- // translators: Placeholders refer to a post title, and a post type singular name (e.g. "Hello World", "Post")
206
  $summary = _x(
207
  '"%1$s" %2$s pending review',
208
  '1: Post title, 2: Post type singular name',
209
  'stream'
210
  );
211
  } elseif ( 'future' === $new ) {
212
- // translators: Placeholders refer to a post title, and a post type singular name (e.g. "Hello World", "Post")
213
  $summary = _x(
214
  '"%1$s" %2$s scheduled for %3$s',
215
  '1: Post title, 2: Post type singular name, 3: Scheduled post date',
216
  'stream'
217
  );
218
  } elseif ( 'future' === $old && 'publish' === $new ) {
219
- // translators: Placeholders refer to a post title, and a post type singular name (e.g. "Hello World", "Post")
220
  $summary = _x(
221
  '"%1$s" scheduled %2$s published',
222
  '1: Post title, 2: Post type singular name',
223
  'stream'
224
  );
225
  } elseif ( 'private' === $new ) {
226
- // translators: Placeholders refer to a post title, and a post type singular name (e.g. "Hello World", "Post")
227
  $summary = _x(
228
  '"%1$s" %2$s privately published',
229
  '1: Post title, 2: Post type singular name',
230
  'stream'
231
  );
232
  } elseif ( 'trash' === $new ) {
233
- // translators: Placeholders refer to a post title, and a post type singular name (e.g. "Hello World", "Post")
234
  $summary = _x(
235
  '"%1$s" %2$s trashed',
236
  '1: Post title, 2: Post type singular name',
@@ -238,7 +247,7 @@ class Connector_Posts extends Connector {
238
  );
239
  $action = 'trashed';
240
  } else {
241
- // translators: Placeholders refer to a post title, and a post type singular name (e.g. "Hello World", "Post")
242
  $summary = _x(
243
  '"%1$s" %2$s updated',
244
  '1: Post title, 2: Post type singular name',
@@ -262,7 +271,7 @@ class Connector_Posts extends Connector {
262
  'post_type' => 'revision',
263
  'post_status' => 'inherit',
264
  'post_parent' => $post->ID,
265
- 'posts_per_page' => 1, // VIP safe
266
  'orderby' => 'post_date',
267
  'order' => 'DESC',
268
  )
@@ -298,17 +307,17 @@ class Connector_Posts extends Connector {
298
  *
299
  * @action deleted_post
300
  *
301
- * $param integer $post_id
302
  */
303
  public function callback_deleted_post( $post_id ) {
304
  $post = get_post( $post_id );
305
 
306
- // We check if post is an instance of WP_Post as it doesn't always resolve in unit testing
307
  if ( ! ( $post instanceof \WP_Post ) || in_array( $post->post_type, $this->get_excluded_post_types(), true ) ) {
308
  return;
309
  }
310
 
311
- // Ignore auto-drafts that are deleted by the system, see issue-293
312
  if ( 'auto-draft' === $post->post_status ) {
313
  return;
314
  }
@@ -316,7 +325,7 @@ class Connector_Posts extends Connector {
316
  $post_type_name = strtolower( $this->get_post_type_name( $post->post_type ) );
317
 
318
  $this->log(
319
- // translators: Placeholders refer to a post title, and a post type singular name (e.g. "Hello World", "Post")
320
  _x(
321
  '"%1$s" %2$s deleted from trash',
322
  '1: Post title, 2: Post type singular name',
@@ -351,12 +360,12 @@ class Connector_Posts extends Connector {
351
  /**
352
  * Gets the singular post type label
353
  *
354
- * @param string $post_type_slug
355
  *
356
  * @return string Post type label
357
  */
358
  public function get_post_type_name( $post_type_slug ) {
359
- $name = esc_html__( 'Post', 'stream' ); // Default
360
 
361
  if ( post_type_exists( $post_type_slug ) ) {
362
  $post_type = get_post_type_object( $post_type_slug );
@@ -369,8 +378,8 @@ class Connector_Posts extends Connector {
369
  /**
370
  * Get an adjacent post revision ID
371
  *
372
- * @param int $revision_id
373
- * @param bool $previous
374
  *
375
  * @return int $revision_id
376
  */
1
  <?php
2
+ /**
3
+ * Connector for Posts
4
+ *
5
+ * @package WP_Stream
6
+ */
7
+
8
  namespace WP_Stream;
9
 
10
+ /**
11
+ * Class - Connector_Posts
12
+ */
13
  class Connector_Posts extends Connector {
14
  /**
15
  * Connector slug
80
  *
81
  * @filter wp_stream_action_links_{connector}
82
  *
83
+ * @param array $links Previous links registered.
84
+ * @param Record $record Stream record.
85
  *
86
  * @return array Action links
87
  */
114
  sprintf( 'delete-post_%d', $post->ID )
115
  );
116
 
117
+ /* translators: %s: a post type singular name (e.g. "Post") */
118
  $links[ sprintf( esc_html_x( 'Restore %s', 'Post type singular name', 'stream' ), $post_type_name ) ] = $untrash;
119
+ /* translators: %s: a post type singular name (e.g. "Post") */
120
  $links[ sprintf( esc_html_x( 'Delete %s Permenantly', 'Post type singular name', 'stream' ), $post_type_name ) ] = $delete;
121
  } else {
122
+ /* translators: %s a post type singular name (e.g. "Post") */
123
  $links[ sprintf( esc_html_x( 'Edit %s', 'Post type singular name', 'stream' ), $post_type_name ) ] = get_edit_post_link( $post->ID );
124
 
125
  $view_link = get_permalink( $post->ID );
144
  *
145
  * @action registered_post_type
146
  *
147
+ * @param string $post_type Post type slug.
148
+ * @param array $args Arguments used to register the post type.
149
  */
150
  public function registered_post_type( $post_type, $args ) {
151
  unset( $args );
161
  *
162
  * @action transition_post_status
163
  *
164
+ * @param mixed $new New status.
165
+ * @param mixed $old Old status.
166
+ * @param \WP_Post $post Post object.
167
  */
168
  public function callback_transition_post_status( $new, $old, $post ) {
169
  if ( in_array( $post->post_type, $this->get_excluded_post_types(), true ) ) {
175
  } elseif ( defined( 'DOING_AUTOSAVE' ) && DOING_AUTOSAVE ) {
176
  return;
177
  } elseif ( 'draft' === $new && 'publish' === $old ) {
178
+ /* translators: %1$s: a post title, %2$s: a post type singular name (e.g. "Hello World", "Post") */
179
  $summary = _x(
180
  '"%1$s" %2$s unpublished',
181
  '1: Post title, 2: Post type singular name',
182
  'stream'
183
  );
184
  } elseif ( 'trash' === $old && 'trash' !== $new ) {
185
+ /* translators: %1$s: a post title, %2$s: a post type singular name (e.g. "Hello World", "Post") */
186
  $summary = _x(
187
  '"%1$s" %2$s restored from trash',
188
  '1: Post title, 2: Post type singular name',
190
  );
191
  $action = 'untrashed';
192
  } elseif ( 'draft' === $new && 'draft' === $old ) {
193
+ /* translators: %1$s: a post title, %2$s: a post type singular name (e.g. "Hello World", "Post") */
194
  $summary = _x(
195
  '"%1$s" %2$s draft saved',
196
  '1: Post title, 2: Post type singular name',
197
  'stream'
198
  );
199
  } elseif ( 'publish' === $new && 'draft' === $old ) {
200
+ /* translators: %1$s: a post title, %2$s: a post type singular name (e.g. "Hello World", "Post") */
201
  $summary = _x(
202
  '"%1$s" %2$s published',
203
  '1: Post title, 2: Post type singular name',
204
  'stream'
205
  );
206
  } elseif ( 'draft' === $new ) {
207
+ /* translators: %1$s: a post title, %2$s a post type singular name (e.g. "Hello World", "Post") */
208
  $summary = _x(
209
  '"%1$s" %2$s drafted',
210
  '1: Post title, 2: Post type singular name',
211
  'stream'
212
  );
213
  } elseif ( 'pending' === $new ) {
214
+ /* translators: %1$s: a post title, %2$s: a post type singular name (e.g. "Hello World", "Post") */
215
  $summary = _x(
216
  '"%1$s" %2$s pending review',
217
  '1: Post title, 2: Post type singular name',
218
  'stream'
219
  );
220
  } elseif ( 'future' === $new ) {
221
+ /* translators: %1$s: a post title, %2$s: a post type singular name (e.g. "Hello World", "Post") */
222
  $summary = _x(
223
  '"%1$s" %2$s scheduled for %3$s',
224
  '1: Post title, 2: Post type singular name, 3: Scheduled post date',
225
  'stream'
226
  );
227
  } elseif ( 'future' === $old && 'publish' === $new ) {
228
+ /* translators: %1$s: a post title, %2$s: a post type singular name (e.g. "Hello World", "Post") */
229
  $summary = _x(
230
  '"%1$s" scheduled %2$s published',
231
  '1: Post title, 2: Post type singular name',
232
  'stream'
233
  );
234
  } elseif ( 'private' === $new ) {
235
+ /* translators: %1$s: a post title, %2$s: a post type singular name (e.g. "Hello World", "Post") */
236
  $summary = _x(
237
  '"%1$s" %2$s privately published',
238
  '1: Post title, 2: Post type singular name',
239
  'stream'
240
  );
241
  } elseif ( 'trash' === $new ) {
242
+ /* translators: %1$s: a post title, %2$s: a post type singular name (e.g. "Hello World", "Post") */
243
  $summary = _x(
244
  '"%1$s" %2$s trashed',
245
  '1: Post title, 2: Post type singular name',
247
  );
248
  $action = 'trashed';
249
  } else {
250
+ /* translators: %1$s: a post title, %2$s: a post type singular name (e.g. "Hello World", "Post") */
251
  $summary = _x(
252
  '"%1$s" %2$s updated',
253
  '1: Post title, 2: Post type singular name',
271
  'post_type' => 'revision',
272
  'post_status' => 'inherit',
273
  'post_parent' => $post->ID,
274
+ 'posts_per_page' => 1, // VIP safe.
275
  'orderby' => 'post_date',
276
  'order' => 'DESC',
277
  )
307
  *
308
  * @action deleted_post
309
  *
310
+ * @param integer $post_id Post ID.
311
  */
312
  public function callback_deleted_post( $post_id ) {
313
  $post = get_post( $post_id );
314
 
315
+ // We check if post is an instance of WP_Post as it doesn't always resolve in unit testing.
316
  if ( ! ( $post instanceof \WP_Post ) || in_array( $post->post_type, $this->get_excluded_post_types(), true ) ) {
317
  return;
318
  }
319
 
320
+ // Ignore auto-drafts that are deleted by the system, see issue-293.
321
  if ( 'auto-draft' === $post->post_status ) {
322
  return;
323
  }
325
  $post_type_name = strtolower( $this->get_post_type_name( $post->post_type ) );
326
 
327
  $this->log(
328
+ /* translators: %1$s: a post title, %2$s: a post type singular name (e.g. "Hello World", "Post") */
329
  _x(
330
  '"%1$s" %2$s deleted from trash',
331
  '1: Post title, 2: Post type singular name',
360
  /**
361
  * Gets the singular post type label
362
  *
363
+ * @param string $post_type_slug Post type slug.
364
  *
365
  * @return string Post type label
366
  */
367
  public function get_post_type_name( $post_type_slug ) {
368
+ $name = esc_html__( 'Post', 'stream' ); // Default.
369
 
370
  if ( post_type_exists( $post_type_slug ) ) {
371
  $post_type = get_post_type_object( $post_type_slug );
378
  /**
379
  * Get an adjacent post revision ID
380
  *
381
+ * @param int $revision_id Revision ID.
382
+ * @param bool $previous Has there been any revision before this one?.
383
  *
384
  * @return int $revision_id
385
  */
connectors/class-connector-settings.php CHANGED
@@ -1,6 +1,15 @@
1
  <?php
 
 
 
 
 
 
2
  namespace WP_Stream;
3
 
 
 
 
4
  class Connector_Settings extends Connector {
5
  /**
6
  * Prefix for the highlight URL hash
@@ -97,7 +106,7 @@ class Connector_Settings extends Connector {
97
  parent::register();
98
 
99
  $this->labels = array(
100
- // General
101
  'blogname' => esc_html__( 'Site Title', 'stream' ),
102
  'blogdescription' => esc_html__( 'Tagline', 'stream' ),
103
  'gmt_offset' => esc_html__( 'Timezone', 'stream' ),
@@ -111,7 +120,7 @@ class Connector_Settings extends Connector {
111
  'date_format' => esc_html__( 'Date Format', 'stream' ),
112
  'time_format' => esc_html__( 'Time Format', 'stream' ),
113
  'start_of_week' => esc_html__( 'Week Starts On', 'stream' ),
114
- // Writing
115
  'use_smilies' => esc_html__( 'Formatting', 'stream' ),
116
  'use_balanceTags' => esc_html__( 'Formatting', 'stream' ),
117
  'default_category' => esc_html__( 'Default Post Category', 'stream' ),
@@ -122,7 +131,7 @@ class Connector_Settings extends Connector {
122
  'default_email_category' => esc_html__( 'Default Mail Category', 'stream' ),
123
  'default_link_category' => esc_html__( 'Default Link Category', 'stream' ),
124
  'ping_sites' => esc_html__( 'Update Services', 'stream' ),
125
- // Reading
126
  'show_on_front' => esc_html__( 'Front page displays', 'stream' ),
127
  'page_on_front' => esc_html__( 'Front page displays', 'stream' ),
128
  'page_for_posts' => esc_html__( 'Front page displays', 'stream' ),
@@ -130,7 +139,7 @@ class Connector_Settings extends Connector {
130
  'posts_per_rss' => esc_html__( 'Syndication feeds show the most recent', 'stream' ),
131
  'rss_use_excerpt' => esc_html__( 'For each article in a feed, show', 'stream' ),
132
  'blog_public' => esc_html__( 'Search Engine Visibility', 'stream' ),
133
- // Discussion
134
  'default_pingback_flag' => esc_html__( 'Default article settings', 'stream' ),
135
  'default_ping_status' => esc_html__( 'Default article settings', 'stream' ),
136
  'default_comment_status' => esc_html__( 'Default article settings', 'stream' ),
@@ -154,7 +163,7 @@ class Connector_Settings extends Connector {
154
  'show_avatars' => esc_html__( 'Show Avatars', 'stream' ),
155
  'avatar_rating' => esc_html__( 'Maximum Rating', 'stream' ),
156
  'avatar_default' => esc_html__( 'Default Avatar', 'stream' ),
157
- // Media
158
  'thumbnail_size_w' => esc_html__( 'Thumbnail size', 'stream' ),
159
  'thumbnail_size_h' => esc_html__( 'Thumbnail size', 'stream' ),
160
  'thumbnail_crop' => esc_html__( 'Thumbnail size', 'stream' ),
@@ -163,11 +172,11 @@ class Connector_Settings extends Connector {
163
  'large_size_w' => esc_html__( 'Large size', 'stream' ),
164
  'large_size_h' => esc_html__( 'Large size', 'stream' ),
165
  'uploads_use_yearmonth_folders' => esc_html__( 'Uploading Files', 'stream' ),
166
- // Permalinks
167
  'permalink_structure' => esc_html__( 'Permalink Settings', 'stream' ),
168
  'category_base' => esc_html__( 'Category base', 'stream' ),
169
  'tag_base' => esc_html__( 'Tag base', 'stream' ),
170
- // Network
171
  'registrationnotification' => esc_html__( 'Registration notification', 'stream' ),
172
  'registration' => esc_html__( 'Allow new registrations', 'stream' ),
173
  'add_new_users' => esc_html__( 'Add New Users', 'stream' ),
@@ -191,11 +200,11 @@ class Connector_Settings extends Connector {
191
  'WPLANG' => esc_html__( 'Network Language', 'stream' ),
192
  'blog_count' => esc_html__( 'Blog Count', 'stream' ),
193
  'user_count' => esc_html__( 'User Count', 'stream' ),
194
- // Other
195
  'wp_stream_db' => esc_html__( 'Stream Database Version', 'stream' ),
196
  );
197
 
198
- // These option labels are special and need to change based on multisite context
199
  if ( is_network_admin() ) {
200
  $this->labels['admin_email'] = esc_html__( 'Network Admin Email', 'stream' );
201
  $this->labels['new_admin_email'] = esc_html__( 'Network Admin Email', 'stream' );
@@ -207,10 +216,12 @@ class Connector_Settings extends Connector {
207
  }
208
 
209
  /**
 
 
210
  * @action update_option_theme_mods_{name}
211
  *
212
- * @param mixed $old_value
213
- * @param mixed $new_value
214
  */
215
  public function log_theme_modification( $old_value, $new_value ) {
216
  $this->callback_updated_option( 'theme_mods', $old_value, $new_value );
@@ -272,8 +283,8 @@ class Connector_Settings extends Connector {
272
  /**
273
  * Return context by option name and key
274
  *
275
- * @param string $option_name
276
- * @param string $key
277
  *
278
  * @return string Context slug
279
  */
@@ -308,8 +319,8 @@ class Connector_Settings extends Connector {
308
  /**
309
  * Find out if the option key should be ignored and not logged
310
  *
311
- * @param string $option_name
312
- * @param string $key
313
  *
314
  * @return bool Whether option key is ignored or not
315
  */
@@ -331,7 +342,7 @@ class Connector_Settings extends Connector {
331
  /**
332
  * Find out if the option should be ignored and not logged
333
  *
334
- * @param string $option_name
335
  *
336
  * @return bool Whether the option is ignored or not
337
  */
@@ -344,19 +355,33 @@ class Connector_Settings extends Connector {
344
  return true;
345
  }
346
 
347
- $ignored = array(
348
  'image_default_link_type',
349
  'medium_large_size_w',
350
  'medium_large_size_h',
351
  );
352
 
353
- return in_array( $option_name, $ignored, true );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
354
  }
355
 
356
  /**
357
  * Find out if array keys in the option should be logged separately
358
  *
359
- * @param mixed $value
360
  *
361
  * @return bool Whether the option should be treated as a group
362
  */
@@ -375,7 +400,7 @@ class Connector_Settings extends Connector {
375
  /**
376
  * Return translated labels for all default Settings fields found in WordPress.
377
  *
378
- * @param string $field_key
379
  *
380
  * @return array Field label translations
381
  */
@@ -400,29 +425,29 @@ class Connector_Settings extends Connector {
400
  /**
401
  * Return translated labels for all serialized Settings found in WordPress.
402
  *
403
- * @param string $option_name
404
- * @param string $field_key
405
  *
406
  * @return string Field key translation or key itself if not found
407
  */
408
  public function get_serialized_field_label( $option_name, $field_key ) {
409
  $labels = array(
410
  'theme_mods' => array(
411
- // Custom Background
412
  'background_image' => esc_html__( 'Background Image', 'stream' ),
413
  'background_position_x' => esc_html__( 'Background Position', 'stream' ),
414
  'background_repeat' => esc_html__( 'Background Repeat', 'stream' ),
415
  'background_attachment' => esc_html__( 'Background Attachment', 'stream' ),
416
  'background_color' => esc_html__( 'Background Color', 'stream' ),
417
- // Custom Header
418
  'header_image' => esc_html__( 'Header Image', 'stream' ),
419
  'header_textcolor' => esc_html__( 'Text Color', 'stream' ),
420
  'header_background_color' => esc_html__( 'Header and Sidebar Background Color', 'stream' ),
421
- // Featured Content
422
  'featured_content_layout' => esc_html__( 'Layout', 'stream' ),
423
- // Custom Sidebar
424
  'sidebar_textcolor' => esc_html__( 'Header and Sidebar Text Color', 'stream' ),
425
- // Custom Colors
426
  'color_scheme' => esc_html__( 'Color Scheme', 'stream' ),
427
  'main_text_color' => esc_html__( 'Main Text Color', 'stream' ),
428
  'secondary_text_color' => esc_html__( 'Secondary Text Color', 'stream' ),
@@ -451,8 +476,8 @@ class Connector_Settings extends Connector {
451
  *
452
  * @filter wp_stream_action_links_{connector}
453
  *
454
- * @param array $links Previous links registered
455
- * @param Record $record Stream record
456
  *
457
  * @return array Action links
458
  */
@@ -544,7 +569,7 @@ class Connector_Settings extends Connector {
544
  );
545
 
546
  if ( ! empty( $applicable_rules ) ) {
547
- // The first applicable rule wins
548
  $rule = array_shift( $applicable_rules );
549
  $menu_slug = $rule['menu_slug'];
550
  $submenu_slug = ( is_object( $rule['submenu_slug'] ) && $rule['submenu_slug'] instanceof Closure ? $rule['submenu_slug']( $record ) : $rule['submenu_slug'] );
@@ -567,7 +592,7 @@ class Connector_Settings extends Connector {
567
  $url = apply_filters( 'wp_stream_action_link_url', $url, $record );
568
  $field_name = $record->get_meta( 'option_key', true );
569
 
570
- // translators: Placeholder refers to a context (e.g. "Editor")
571
  $text = sprintf( esc_html__( 'Edit %s Settings', 'stream' ), $context_labels[ $record->context ] );
572
 
573
  if ( '' === $field_name ) {
@@ -592,9 +617,9 @@ class Connector_Settings extends Connector {
592
  *
593
  * @action update_option
594
  *
595
- * @param string $option
596
- * @param mixed $old_value
597
- * @param mixed $value
598
  */
599
  public function callback_update_option( $option, $value, $old_value ) {
600
  if ( ( defined( '\WP_CLI' ) && \WP_CLI || did_action( 'customize_save' ) ) && array_key_exists( $option, $this->labels ) ) {
@@ -607,7 +632,7 @@ class Connector_Settings extends Connector {
607
  *
608
  * @action whitelist_options
609
  *
610
- * @param array $options
611
  *
612
  * @return array
613
  */
@@ -622,8 +647,8 @@ class Connector_Settings extends Connector {
622
  *
623
  * @action update_option_permalink_structure
624
  *
625
- * @param mixed $old_value
626
- * @param mixed $value
627
  */
628
  public function callback_update_option_permalink_structure( $old_value, $value ) {
629
  $this->callback_updated_option( 'permalink_structure', $old_value, $value );
@@ -634,9 +659,9 @@ class Connector_Settings extends Connector {
634
  *
635
  * @action update_site_option
636
  *
637
- * @param string $option
638
- * @param mixed $old_value
639
- * @param mixed $value
640
  */
641
  public function callback_update_site_option( $option, $value, $old_value ) {
642
  $this->callback_updated_option( $option, $value, $old_value );
@@ -647,8 +672,8 @@ class Connector_Settings extends Connector {
647
  *
648
  * @action update_option_category_base
649
  *
650
- * @param mixed $old_value
651
- * @param mixed $value
652
  */
653
  public function callback_update_option_category_base( $old_value, $value ) {
654
  $this->callback_updated_option( 'category_base', $old_value, $value );
@@ -659,8 +684,8 @@ class Connector_Settings extends Connector {
659
  *
660
  * @action update_option_tag_base
661
  *
662
- * @param mixed $old_value
663
- * @param mixed $value
664
  */
665
  public function callback_update_option_tag_base( $old_value, $value ) {
666
  $this->callback_updated_option( 'tag_base', $old_value, $value );
@@ -671,9 +696,9 @@ class Connector_Settings extends Connector {
671
  *
672
  * @action updated_option
673
  *
674
- * @param string $option
675
- * @param mixed $old_value
676
- * @param mixed $value
677
  */
678
  public function callback_updated_option( $option, $old_value, $value ) {
679
  global $whitelist_options, $new_whitelist_options;
@@ -732,7 +757,7 @@ class Connector_Settings extends Connector {
732
 
733
  foreach ( $changed_options as $properties ) {
734
  $this->log(
735
- // translators: Placeholder refers to a setting name (e.g. "Language")
736
  __( '"%s" setting was updated', 'stream' ),
737
  $properties,
738
  null,
@@ -752,7 +777,7 @@ class Connector_Settings extends Connector {
752
  <script>
753
  (function ($) {
754
  $(function () {
755
- var hashPrefix = <?php echo wp_stream_json_encode( self::HIGHLIGHT_FIELD_URL_HASH_PREFIX ); // xss ok ?>,
756
  hashFieldName = "",
757
  fieldNames = [],
758
  $select2Choices = {},
@@ -818,9 +843,9 @@ class Connector_Settings extends Connector {
818
  * @deprecated Use is_option_group()
819
  * @see is_option_group()
820
  *
821
- * @param string $key
822
- * @param mixed $old_value
823
- * @param mixed $value
824
  *
825
  * @return bool Whether the option should be treated as a group
826
  */
@@ -832,7 +857,7 @@ class Connector_Settings extends Connector {
832
  /**
833
  * Sanitize values, so that we don't store complex data, such as arrays or objects
834
  *
835
- * @param mixed $value
836
  * @return string
837
  */
838
  public function sanitize_value( $value ) {
1
  <?php
2
+ /**
3
+ * Connector for Settings
4
+ *
5
+ * @package WP_Stream
6
+ */
7
+
8
  namespace WP_Stream;
9
 
10
+ /**
11
+ * Class - Connector_Settings
12
+ */
13
  class Connector_Settings extends Connector {
14
  /**
15
  * Prefix for the highlight URL hash
106
  parent::register();
107
 
108
  $this->labels = array(
109
+ // General.
110
  'blogname' => esc_html__( 'Site Title', 'stream' ),
111
  'blogdescription' => esc_html__( 'Tagline', 'stream' ),
112
  'gmt_offset' => esc_html__( 'Timezone', 'stream' ),
120
  'date_format' => esc_html__( 'Date Format', 'stream' ),
121
  'time_format' => esc_html__( 'Time Format', 'stream' ),
122
  'start_of_week' => esc_html__( 'Week Starts On', 'stream' ),
123
+ // Writing.
124
  'use_smilies' => esc_html__( 'Formatting', 'stream' ),
125
  'use_balanceTags' => esc_html__( 'Formatting', 'stream' ),
126
  'default_category' => esc_html__( 'Default Post Category', 'stream' ),
131
  'default_email_category' => esc_html__( 'Default Mail Category', 'stream' ),
132
  'default_link_category' => esc_html__( 'Default Link Category', 'stream' ),
133
  'ping_sites' => esc_html__( 'Update Services', 'stream' ),
134
+ // Reading.
135
  'show_on_front' => esc_html__( 'Front page displays', 'stream' ),
136
  'page_on_front' => esc_html__( 'Front page displays', 'stream' ),
137
  'page_for_posts' => esc_html__( 'Front page displays', 'stream' ),
139
  'posts_per_rss' => esc_html__( 'Syndication feeds show the most recent', 'stream' ),
140
  'rss_use_excerpt' => esc_html__( 'For each article in a feed, show', 'stream' ),
141
  'blog_public' => esc_html__( 'Search Engine Visibility', 'stream' ),
142
+ // Discussion.
143
  'default_pingback_flag' => esc_html__( 'Default article settings', 'stream' ),
144
  'default_ping_status' => esc_html__( 'Default article settings', 'stream' ),
145
  'default_comment_status' => esc_html__( 'Default article settings', 'stream' ),
163
  'show_avatars' => esc_html__( 'Show Avatars', 'stream' ),
164
  'avatar_rating' => esc_html__( 'Maximum Rating', 'stream' ),
165
  'avatar_default' => esc_html__( 'Default Avatar', 'stream' ),
166
+ // Media.
167
  'thumbnail_size_w' => esc_html__( 'Thumbnail size', 'stream' ),
168
  'thumbnail_size_h' => esc_html__( 'Thumbnail size', 'stream' ),
169
  'thumbnail_crop' => esc_html__( 'Thumbnail size', 'stream' ),
172
  'large_size_w' => esc_html__( 'Large size', 'stream' ),
173
  'large_size_h' => esc_html__( 'Large size', 'stream' ),
174
  'uploads_use_yearmonth_folders' => esc_html__( 'Uploading Files', 'stream' ),
175
+ // Permalinks.
176
  'permalink_structure' => esc_html__( 'Permalink Settings', 'stream' ),
177
  'category_base' => esc_html__( 'Category base', 'stream' ),
178
  'tag_base' => esc_html__( 'Tag base', 'stream' ),
179
+ // Network.
180
  'registrationnotification' => esc_html__( 'Registration notification', 'stream' ),
181
  'registration' => esc_html__( 'Allow new registrations', 'stream' ),
182
  'add_new_users' => esc_html__( 'Add New Users', 'stream' ),
200
  'WPLANG' => esc_html__( 'Network Language', 'stream' ),
201
  'blog_count' => esc_html__( 'Blog Count', 'stream' ),
202
  'user_count' => esc_html__( 'User Count', 'stream' ),
203
+ // Other.
204
  'wp_stream_db' => esc_html__( 'Stream Database Version', 'stream' ),
205
  );
206
 
207
+ // These option labels are special and need to change based on multisite context.
208
  if ( is_network_admin() ) {
209
  $this->labels['admin_email'] = esc_html__( 'Network Admin Email', 'stream' );
210
  $this->labels['new_admin_email'] = esc_html__( 'Network Admin Email', 'stream' );
216
  }
217
 
218
  /**
219
+ * Logs changes to the theme modifications.
220
+ *
221
  * @action update_option_theme_mods_{name}
222
  *
223
+ * @param mixed $old_value Old setting value.
224
+ * @param mixed $new_value New setting value.
225
  */
226
  public function log_theme_modification( $old_value, $new_value ) {
227
  $this->callback_updated_option( 'theme_mods', $old_value, $new_value );
283
  /**
284
  * Return context by option name and key
285
  *
286
+ * @param string $option_name Option name.
287
+ * @param string $key Option key.
288
  *
289
  * @return string Context slug
290
  */
319
  /**
320
  * Find out if the option key should be ignored and not logged
321
  *
322
+ * @param string $option_name Option name.
323
+ * @param string $key Option key.
324
  *
325
  * @return bool Whether option key is ignored or not
326
  */
342
  /**
343
  * Find out if the option should be ignored and not logged
344
  *
345
+ * @param string $option_name Option name.
346
  *
347
  * @return bool Whether the option is ignored or not
348
  */
355
  return true;
356
  }
357
 
358
+ $default_ignored = array(
359
  'image_default_link_type',
360
  'medium_large_size_w',
361
  'medium_large_size_h',
362
  );
363
 
364
+ /**
365
+ * Filters the boolean output for is_option_ignored().
366
+ *
367
+ * @param boolean $is_ignored True if ignored, otherwise false.
368
+ * @param string $option_name Current option name.
369
+ * @param array $default_ignored Default options for Stream to ignore.
370
+ *
371
+ * @return boolean
372
+ */
373
+ return apply_filters(
374
+ 'wp_stream_is_option_ignored',
375
+ in_array( $option_name, $default_ignored, true ),
376
+ $option_name,
377
+ $default_ignored
378
+ );
379
  }
380
 
381
  /**
382
  * Find out if array keys in the option should be logged separately
383
  *
384
+ * @param mixed $value Option value.
385
  *
386
  * @return bool Whether the option should be treated as a group
387
  */
400
  /**
401
  * Return translated labels for all default Settings fields found in WordPress.
402
  *
403
+ * @param string $field_key Field key.
404
  *
405
  * @return array Field label translations
406
  */
425
  /**
426
  * Return translated labels for all serialized Settings found in WordPress.
427
  *
428
+ * @param string $option_name Option name.
429
+ * @param string $field_key Field key.
430
  *
431
  * @return string Field key translation or key itself if not found
432
  */
433
  public function get_serialized_field_label( $option_name, $field_key ) {
434
  $labels = array(
435
  'theme_mods' => array(
436
+ // Custom Background.
437
  'background_image' => esc_html__( 'Background Image', 'stream' ),
438
  'background_position_x' => esc_html__( 'Background Position', 'stream' ),
439
  'background_repeat' => esc_html__( 'Background Repeat', 'stream' ),
440
  'background_attachment' => esc_html__( 'Background Attachment', 'stream' ),
441
  'background_color' => esc_html__( 'Background Color', 'stream' ),
442
+ // Custom Header.
443
  'header_image' => esc_html__( 'Header Image', 'stream' ),
444
  'header_textcolor' => esc_html__( 'Text Color', 'stream' ),
445
  'header_background_color' => esc_html__( 'Header and Sidebar Background Color', 'stream' ),
446
+ // Featured Content.
447
  'featured_content_layout' => esc_html__( 'Layout', 'stream' ),
448
+ // Custom Sidebar.
449
  'sidebar_textcolor' => esc_html__( 'Header and Sidebar Text Color', 'stream' ),
450
+ // Custom Colors.
451
  'color_scheme' => esc_html__( 'Color Scheme', 'stream' ),
452
  'main_text_color' => esc_html__( 'Main Text Color', 'stream' ),
453
  'secondary_text_color' => esc_html__( 'Secondary Text Color', 'stream' ),
476
  *
477
  * @filter wp_stream_action_links_{connector}
478
  *
479
+ * @param array $links Previous links registered.
480
+ * @param Record $record Stream record.
481
  *
482
  * @return array Action links
483
  */
569
  );
570
 
571
  if ( ! empty( $applicable_rules ) ) {
572
+ // The first applicable rule wins.
573
  $rule = array_shift( $applicable_rules );
574
  $menu_slug = $rule['menu_slug'];
575
  $submenu_slug = ( is_object( $rule['submenu_slug'] ) && $rule['submenu_slug'] instanceof Closure ? $rule['submenu_slug']( $record ) : $rule['submenu_slug'] );
592
  $url = apply_filters( 'wp_stream_action_link_url', $url, $record );
593
  $field_name = $record->get_meta( 'option_key', true );
594
 
595
+ /* translators: %s: a context (e.g. "Editor") */
596
  $text = sprintf( esc_html__( 'Edit %s Settings', 'stream' ), $context_labels[ $record->context ] );
597
 
598
  if ( '' === $field_name ) {
617
  *
618
  * @action update_option
619
  *
620
+ * @param string $option Option name.
621
+ * @param mixed $value Option new value.
622
+ * @param mixed $old_value Option old value.
623
  */
624
  public function callback_update_option( $option, $value, $old_value ) {
625
  if ( ( defined( '\WP_CLI' ) && \WP_CLI || did_action( 'customize_save' ) ) && array_key_exists( $option, $this->labels ) ) {
632
  *
633
  * @action whitelist_options
634
  *
635
+ * @param array $options Options.
636
  *
637
  * @return array
638
  */
647
  *
648
  * @action update_option_permalink_structure
649
  *
650
+ * @param mixed $old_value Option old value.
651
+ * @param mixed $value Option new value.
652
  */
653
  public function callback_update_option_permalink_structure( $old_value, $value ) {
654
  $this->callback_updated_option( 'permalink_structure', $old_value, $value );
659
  *
660
  * @action update_site_option
661
  *
662
+ * @param string $option Option name.
663
+ * @param mixed $value Option new value.
664
+ * @param mixed $old_value Option old value.
665
  */
666
  public function callback_update_site_option( $option, $value, $old_value ) {
667
  $this->callback_updated_option( $option, $value, $old_value );
672
  *
673
  * @action update_option_category_base
674
  *
675
+ * @param mixed $old_value Option old value.
676
+ * @param mixed $value Option new value.
677
  */
678
  public function callback_update_option_category_base( $old_value, $value ) {
679
  $this->callback_updated_option( 'category_base', $old_value, $value );
684
  *
685
  * @action update_option_tag_base
686
  *
687
+ * @param mixed $old_value Option old value.
688
+ * @param mixed $value Option new value.
689
  */
690
  public function callback_update_option_tag_base( $old_value, $value ) {
691
  $this->callback_updated_option( 'tag_base', $old_value, $value );
696
  *
697
  * @action updated_option
698
  *
699
+ * @param string $option Option name.
700
+ * @param mixed $old_value Option old value.
701
+ * @param mixed $value Option new value.
702
  */
703
  public function callback_updated_option( $option, $old_value, $value ) {
704
  global $whitelist_options, $new_whitelist_options;
757
 
758
  foreach ( $changed_options as $properties ) {
759
  $this->log(
760
+ /* translators: %s: a setting name (e.g. "Language") */
761
  __( '"%s" setting was updated', 'stream' ),
762
  $properties,
763
  null,
777
  <script>
778
  (function ($) {
779
  $(function () {
780
+ var hashPrefix = <?php echo wp_stream_json_encode( self::HIGHLIGHT_FIELD_URL_HASH_PREFIX ); // xss ok. ?>,
781
  hashFieldName = "",
782
  fieldNames = [],
783
  $select2Choices = {},
843
  * @deprecated Use is_option_group()
844
  * @see is_option_group()
845
  *
846
+ * @param string $key Key.
847
+ * @param mixed $old_value Old value.
848
+ * @param mixed $value New value.
849
  *
850
  * @return bool Whether the option should be treated as a group
851
  */
857
  /**
858
  * Sanitize values, so that we don't store complex data, such as arrays or objects
859
  *
860
+ * @param mixed $value Raw input value.
861
  * @return string
862
  */
863
  public function sanitize_value( $value ) {
connectors/class-connector-taxonomies.php CHANGED
@@ -1,6 +1,15 @@
1
  <?php
 
 
 
 
 
 
2
  namespace WP_Stream;
3
 
 
 
 
4
  class Connector_Taxonomies extends Connector {
5
  /**
6
  * Connector slug
@@ -86,13 +95,14 @@ class Connector_Taxonomies extends Connector {
86
  *
87
  * @filter wp_stream_action_links_{connector}
88
  *
89
- * @param array $links Previous links registered
90
- * @param Record $record Stream record
91
  *
92
  * @return array Action links
93
  */
94
  public function action_links( $links, $record ) {
95
- $term = get_term_by( 'term_taxonomy_id', $record->object_id, $record->context ); // wpcom_vip_get_term_by() does not indicate support for `term_taxonomy_id`
 
96
  if ( $record->object_id && 'deleted' !== $record->action && $term ) {
97
  if ( ! is_wp_error( $term ) ) {
98
  $tax_obj = get_taxonomy( $term->taxonomy );
@@ -104,7 +114,7 @@ class Connector_Taxonomies extends Connector {
104
 
105
  $term_id = empty( $term_id ) ? $term->term_id : $term_id;
106
 
107
- // translators: Placeholder refers to a term singular name (e.g. "Tag")
108
  $links[ sprintf( _x( 'Edit %s', 'Term singular name', 'stream' ), $tax_label ) ] = get_edit_term_link( $term_id, $term->taxonomy );
109
  $links[ esc_html__( 'View', 'stream' ) ] = wp_stream_is_vip() ? \wpcom_vip_get_term_link( $term_id, $term->taxonomy ) : get_term_link( $term_id, $term->taxonomy );
110
  }
@@ -118,9 +128,9 @@ class Connector_Taxonomies extends Connector {
118
  *
119
  * @action registered_taxonomy
120
  *
121
- * @param string $taxonomy Taxonomy slug
122
- * @param array|string $object_type Object type or array of object types
123
- * @param array|string $args Array or string of taxonomy registration arguments
124
  */
125
  public function registered_taxonomy( $taxonomy, $object_type, $args ) {
126
  unset( $object_type );
@@ -138,9 +148,9 @@ class Connector_Taxonomies extends Connector {
138
  *
139
  * @action created_term
140
  *
141
- * @param integer $term_id
142
- * @param integer $tt_id
143
- * @param string $taxonomy
144
  */
145
  public function callback_created_term( $term_id, $tt_id, $taxonomy ) {
146
  if ( in_array( $taxonomy, $this->get_excluded_taxonomies(), true ) ) {
@@ -153,7 +163,7 @@ class Connector_Taxonomies extends Connector {
153
  $term_parent = $term->parent;
154
 
155
  $this->log(
156
- // translators: Placeholders refer to a term name, and a taxonomy singular label (e.g. "Tags", "Genre")
157
  _x(
158
  '"%1$s" %2$s created',
159
  '1: Term name, 2: Taxonomy singular label',
@@ -171,10 +181,10 @@ class Connector_Taxonomies extends Connector {
171
  *
172
  * @action delete_term
173
  *
174
- * @param integer $term_id
175
- * @param integer $tt_id
176
- * @param string $taxonomy
177
- * @param object $deleted_term
178
  */
179
  public function callback_delete_term( $term_id, $tt_id, $taxonomy, $deleted_term ) {
180
  if ( in_array( $taxonomy, $this->get_excluded_taxonomies(), true ) ) {
@@ -186,7 +196,7 @@ class Connector_Taxonomies extends Connector {
186
  $taxonomy_label = strtolower( $this->context_labels[ $taxonomy ] );
187
 
188
  $this->log(
189
- // translators: Placeholders refer to a term name, and a taxonomy singular label (e.g. "Tags", "Genre")
190
  _x(
191
  '"%1$s" %2$s deleted',
192
  '1: Term name, 2: Taxonomy singular label',
@@ -204,15 +214,24 @@ class Connector_Taxonomies extends Connector {
204
  *
205
  * @action edit_term
206
  *
207
- * @param integer $term_id
208
- * @param integer $tt_id
209
- * @param string $taxonomy
210
  */
211
  public function callback_edit_term( $term_id, $tt_id, $taxonomy ) {
212
  unset( $tt_id );
213
  $this->cached_term_before_update = get_term( $term_id, $taxonomy );
214
  }
215
 
 
 
 
 
 
 
 
 
 
216
  public function callback_edited_term( $term_id, $tt_id, $taxonomy ) {
217
  if ( in_array( $taxonomy, $this->get_excluded_taxonomies(), true ) ) {
218
  return;
@@ -229,7 +248,7 @@ class Connector_Taxonomies extends Connector {
229
  $term_parent = $term->parent;
230
 
231
  $this->log(
232
- // translators: Placeholders refer to a term name, and a taxonomy singular label (e.g. "Tags", "Genre")
233
  _x(
234
  '"%1$s" %2$s updated',
235
  '1: Term name, 2: Taxonomy singular label',
1
  <?php
2
+ /**
3
+ * Connector for Taxonomies
4
+ *
5
+ * @package WP_Stream
6
+ */
7
+
8
  namespace WP_Stream;
9
 
10
+ /**
11
+ * Class - Connector_Taxonomies
12
+ */
13
  class Connector_Taxonomies extends Connector {
14
  /**
15
  * Connector slug
95
  *
96
  * @filter wp_stream_action_links_{connector}
97
  *
98
+ * @param array $links Previous links registered.
99
+ * @param Record $record Stream record.
100
  *
101
  * @return array Action links
102
  */
103
  public function action_links( $links, $record ) {
104
+ // wpcom_vip_get_term_by() does not indicate support for `term_taxonomy_id`.
105
+ $term = get_term_by( 'term_taxonomy_id', $record->object_id, $record->context );
106
  if ( $record->object_id && 'deleted' !== $record->action && $term ) {
107
  if ( ! is_wp_error( $term ) ) {
108
  $tax_obj = get_taxonomy( $term->taxonomy );
114
 
115
  $term_id = empty( $term_id ) ? $term->term_id : $term_id;
116
 
117
+ /* translators: %s a term singular name (e.g. "Tag") */
118
  $links[ sprintf( _x( 'Edit %s', 'Term singular name', 'stream' ), $tax_label ) ] = get_edit_term_link( $term_id, $term->taxonomy );
119
  $links[ esc_html__( 'View', 'stream' ) ] = wp_stream_is_vip() ? \wpcom_vip_get_term_link( $term_id, $term->taxonomy ) : get_term_link( $term_id, $term->taxonomy );
120
  }
128
  *
129
  * @action registered_taxonomy
130
  *
131
+ * @param string $taxonomy Taxonomy slug.
132
+ * @param array|string $object_type Object type or array of object types.
133
+ * @param array|string $args Array or string of taxonomy registration arguments.
134
  */
135
  public function registered_taxonomy( $taxonomy, $object_type, $args ) {
136
  unset( $object_type );
148
  *
149
  * @action created_term
150
  *
151
+ * @param integer $term_id Term ID.
152
+ * @param integer $tt_id Taxonomy term ID.
153
+ * @param string $taxonomy Taxonomy name.
154
  */
155
  public function callback_created_term( $term_id, $tt_id, $taxonomy ) {
156
  if ( in_array( $taxonomy, $this->get_excluded_taxonomies(), true ) ) {
163
  $term_parent = $term->parent;
164
 
165
  $this->log(
166
+ /* translators: %1$s: a term name, %2$s: a taxonomy singular label (e.g. "Tags", "Genre") */
167
  _x(
168
  '"%1$s" %2$s created',
169
  '1: Term name, 2: Taxonomy singular label',
181
  *
182
  * @action delete_term
183
  *
184
+ * @param integer $term_id Term ID.
185
+ * @param integer $tt_id Taxonomy term ID.
186
+ * @param string $taxonomy Taxonomy name.
187
+ * @param object $deleted_term Deleted term object.
188
  */
189
  public function callback_delete_term( $term_id, $tt_id, $taxonomy, $deleted_term ) {
190
  if ( in_array( $taxonomy, $this->get_excluded_taxonomies(), true ) ) {
196
  $taxonomy_label = strtolower( $this->context_labels[ $taxonomy ] );
197
 
198
  $this->log(
199
+ /* translators: %1$s: a term name, %2$s: a taxonomy singular label (e.g. "Tags", "Genre") */
200
  _x(
201
  '"%1$s" %2$s deleted',
202
  '1: Term name, 2: Taxonomy singular label',
214
  *
215
  * @action edit_term
216
  *
217
+ * @param integer $term_id Term ID.
218
+ * @param integer $tt_id Taxonomy term ID.
219
+ * @param string $taxonomy Taxonomy name.
220
  */
221
  public function callback_edit_term( $term_id, $tt_id, $taxonomy ) {
222
  unset( $tt_id );
223
  $this->cached_term_before_update = get_term( $term_id, $taxonomy );
224
  }
225
 
226
+ /**
227
+ * Tracks updated of taxonomy terms
228
+ *
229
+ * @action edited_term
230
+ *
231
+ * @param integer $term_id Term ID.
232
+ * @param integer $tt_id Taxonomy term ID.
233
+ * @param string $taxonomy Taxonomy name.
234
+ */
235
  public function callback_edited_term( $term_id, $tt_id, $taxonomy ) {
236
  if ( in_array( $taxonomy, $this->get_excluded_taxonomies(), true ) ) {
237
  return;
248
  $term_parent = $term->parent;
249
 
250
  $this->log(
251
+ /* translators: %1$s: a term name, %2$s: a taxonomy singular label (e.g. "Tags", "Genre") */
252
  _x(
253
  '"%1$s" %2$s updated',
254
  '1: Term name, 2: Taxonomy singular label',
connectors/class-connector-user-switching.php CHANGED
@@ -1,6 +1,15 @@
1
  <?php
 
 
 
 
 
 
2
  namespace WP_Stream;
3
 
 
 
 
4
  class Connector_User_Switching extends Connector {
5
 
6
  /**
@@ -100,11 +109,15 @@ class Connector_User_Switching extends Connector {
100
  * This unhooks the Users connector's login and logout actions so they don't appear when a user switches
101
  * user with the User Switching plugin.
102
  *
103
- * @param array $labels All registered connector labels
104
- * @param Connectors $connectors The Connectors object instance
105
  */
106
  public function callback_wp_stream_after_connectors_registration( array $labels, Connectors $connectors ) {
107
- $action = wp_stream_filter_input( INPUT_GET, 'action' ) ?: wp_stream_filter_input( INPUT_POST, 'action' );
 
 
 
 
108
 
109
  if ( ! $action ) {
110
  return;
@@ -140,7 +153,7 @@ class Connector_User_Switching extends Connector {
140
 
141
  $user = get_userdata( $user_id );
142
  $old_user = get_userdata( $old_user_id );
143
- // translators: Placeholders refer to a user display name, and a username (e.g. "Jane Doe", "administrator")
144
  $message = _x(
145
  'Switched user to %1$s (%2$s)',
146
  '1: User display name, 2: User login',
@@ -171,7 +184,7 @@ class Connector_User_Switching extends Connector {
171
  public function callback_switch_back_user( $user_id, $old_user_id ) {
172
 
173
  $user = get_userdata( $user_id );
174
- // translators: Placeholders refer to a user display name, and a username (e.g. "Jane Doe", "administrator")
175
  $message = _x(
176
  'Switched back to %1$s (%2$s)',
177
  '1: User display name, 2: User login',
@@ -225,8 +238,8 @@ class Connector_User_Switching extends Connector {
225
  /**
226
  * Unhook the requested action from the Users connector.
227
  *
228
- * @param Connectors $connectors The Connectors instance
229
- * @param string $action The name of the action to unhook
230
  */
231
  protected function unhook_user_action( Connectors $connectors, $action ) {
232
  foreach ( $connectors->connectors as $connector ) {
1
  <?php
2
+ /**
3
+ * Connector for User-Switching
4
+ *
5
+ * @package WP_Stream
6
+ */
7
+
8
  namespace WP_Stream;
9
 
10
+ /**
11
+ * Class - Connector_User_Switching
12
+ */
13
  class Connector_User_Switching extends Connector {
14
 
15
  /**
109
  * This unhooks the Users connector's login and logout actions so they don't appear when a user switches
110
  * user with the User Switching plugin.
111
  *
112
+ * @param array $labels All registered connector labels.
113
+ * @param Connectors $connectors The Connectors object instance.
114
  */
115
  public function callback_wp_stream_after_connectors_registration( array $labels, Connectors $connectors ) {
116
+ $action = wp_stream_filter_input( INPUT_GET, 'action' );
117
+
118
+ if ( ! $action ) {
119
+ $action = wp_stream_filter_input( INPUT_POST, 'action' );
120
+ }
121
 
122
  if ( ! $action ) {
123
  return;
153
 
154
  $user = get_userdata( $user_id );
155
  $old_user = get_userdata( $old_user_id );
156
+ /* translators: %1$s: a user display name, %2$s: a username (e.g. "Jane Doe", "administrator") */
157
  $message = _x(
158
  'Switched user to %1$s (%2$s)',
159
  '1: User display name, 2: User login',
184
  public function callback_switch_back_user( $user_id, $old_user_id ) {
185
 
186
  $user = get_userdata( $user_id );
187
+ /* translators: Placeholders refer to a user display name, and a username (e.g. "Jane Doe", "administrator") */
188
  $message = _x(
189
  'Switched back to %1$s (%2$s)',
190
  '1: User display name, 2: User login',
238
  /**
239
  * Unhook the requested action from the Users connector.
240
  *
241
+ * @param Connectors $connectors The Connectors instance.
242
+ * @param string $action The name of the action to unhook.
243
  */
244
  protected function unhook_user_action( Connectors $connectors, $action ) {
245
  foreach ( $connectors->connectors as $connector ) {
connectors/class-connector-users.php CHANGED
@@ -1,6 +1,15 @@
1
  <?php
 
 
 
 
 
 
2
  namespace WP_Stream;
3
 
 
 
 
4
  class Connector_Users extends Connector {
5
 
6
  /**
@@ -12,8 +21,10 @@ class Connector_Users extends Connector {
12
 
13
  /**
14
  * Stores users object before the user being deleted.
 
 
15
  */
16
- protected $_users_object_pre_deleted = array();
17
 
18
  /**
19
  * Actions registered for this connector
@@ -79,8 +90,8 @@ class Connector_Users extends Connector {
79
  *
80
  * @filter wp_stream_action_links_{connector}
81
  *
82
- * @param array $links Previous links registered
83
- * @param Record $record Stream record
84
  *
85
  * @return array Action links
86
  */
@@ -98,7 +109,7 @@ class Connector_Users extends Connector {
98
  /**
99
  * Get an array of role lables assigned to a specific user.
100
  *
101
- * @param object|int $user User object or user ID to get roles for
102
  *
103
  * @return array $labels An array of role labels
104
  */
@@ -130,17 +141,17 @@ class Connector_Users extends Connector {
130
  *
131
  * @action user_register
132
  *
133
- * @param int $user_id Newly registered user ID
134
  */
135
  public function callback_user_register( $user_id ) {
136
  $current_user = wp_get_current_user();
137
  $registered_user = get_user_by( 'id', $user_id );
138
 
139
- if ( ! $current_user->ID ) { // Non logged-in user registered themselves
140
  $message = esc_html__( 'New user registration', 'stream' );
141
  $user_to_log = $registered_user->ID;
142
- } else { // Current logged-in user created a new user
143
- // translators: Placeholders refer to a user display name, and a user role (e.g. "Jane Doe", "subscriber")
144
  $message = _x(
145
  'New user account created for %1$s (%2$s)',
146
  '1: User display name, 2: User role',
@@ -167,14 +178,14 @@ class Connector_Users extends Connector {
167
  *
168
  * @action profile_update
169
  *
170
- * @param int $user_id registered user ID
171
- * @param \WP_User $user registered user object
172
  */
173
  public function callback_profile_update( $user_id, $user ) {
174
  unset( $user_id );
175
 
176
  $this->log(
177
- // translators: Placeholder refers to a user display name (e.g. "Jane Doe")
178
  __( '%s\'s profile was updated', 'stream' ),
179
  array(
180
  'display_name' => $user->display_name,
@@ -190,9 +201,9 @@ class Connector_Users extends Connector {
190
  *
191
  * @action set_user_role
192
  *
193
- * @param int $user_id
194
- * @param string $new_role
195
- * @param array $old_roles
196
  */
197
  public function callback_set_user_role( $user_id, $new_role, $old_roles ) {
198
  if ( empty( $old_roles ) ) {
@@ -202,7 +213,7 @@ class Connector_Users extends Connector {
202
  global $wp_roles;
203
 
204
  $this->log(
205
- // translators: Placeholders refer to a user display name, a user role, and another user role (e.g. "Jane Doe", "editor", "subscriber")
206
  _x(
207
  '%1$s\'s role was changed from %2$s to %3$s',
208
  '1: User display name, 2: Old role, 3: New role',
@@ -224,11 +235,11 @@ class Connector_Users extends Connector {
224
  *
225
  * @action password_reset
226
  *
227
- * @param \WP_User $user
228
  */
229
  public function callback_password_reset( $user ) {
230
  $this->log(
231
- // translators: Placeholder refers to a user display name (e.g. "Jane Doe")
232
  __( '%s\'s password was reset', 'stream' ),
233
  array(
234
  'email' => $user->display_name,
@@ -245,7 +256,7 @@ class Connector_Users extends Connector {
245
  *
246
  * @action retrieve_password
247
  *
248
- * @param string $user_login
249
  */
250
  public function callback_retrieve_password( $user_login ) {
251
  if ( wp_stream_filter_var( $user_login, FILTER_VALIDATE_EMAIL ) ) {
@@ -255,7 +266,7 @@ class Connector_Users extends Connector {
255
  }
256
 
257
  $this->log(
258
- // translators: Placeholder refers to a user display name (e.g. "Jane Doe")
259
  __( '%s\'s password was requested to be reset', 'stream' ),
260
  array(
261
  'display_name' => $user->display_name,
@@ -272,10 +283,10 @@ class Connector_Users extends Connector {
272
  *
273
  * @action set_logged_in_cookie
274
  *
275
- * @param string $logged_in_cookie
276
- * @param int $expire
277
- * @param int $expiration
278
- * @param int $user_id
279
  */
280
  public function callback_set_logged_in_cookie( $logged_in_cookie, $expire, $expiration, $user_id ) {
281
  unset( $logged_in_cookie );
@@ -284,7 +295,7 @@ class Connector_Users extends Connector {
284
  $user = get_user_by( 'id', $user_id );
285
 
286
  $this->log(
287
- // translators: Placeholder refers to a user display name (e.g. "Jane Doe")
288
  __( '%s logged in', 'stream' ),
289
  array(
290
  'display_name' => $user->display_name,
@@ -304,13 +315,13 @@ class Connector_Users extends Connector {
304
  public function callback_clear_auth_cookie() {
305
  $user = wp_get_current_user();
306
 
307
- // For some reason, incognito mode calls clear_auth_cookie on failed login attempts
308
  if ( empty( $user ) || ! $user->exists() ) {
309
  return;
310
  }
311
 
312
  $this->log(
313
- // translators: Placeholder refers to a user display name (e.g. "Jane Doe")
314
  __( '%s logged out', 'stream' ),
315
  array(
316
  'display_name' => $user->display_name,
@@ -330,7 +341,7 @@ class Connector_Users extends Connector {
330
  * was already removed from DB.
331
  *
332
  * @action delete_user
333
- * @param int $user_id User ID that maybe deleted
334
  */
335
  public function callback_delete_user( $user_id ) {
336
  if ( ! isset( $this->_users_object_pre_deleted[ $user_id ] ) ) {
@@ -342,13 +353,13 @@ class Connector_Users extends Connector {
342
  * Log deleted user.
343
  *
344
  * @action deleted_user
345
- * @param int $user_id Deleted user ID
346
  */
347
  public function callback_deleted_user( $user_id ) {
348
  $user = wp_get_current_user();
349
 
350
  if ( isset( $this->_users_object_pre_deleted[ $user_id ] ) ) {
351
- // translators: Placeholders refer to a user display name, and a user role (e.g. "Jane Doe", "subscriber")
352
  $message = _x(
353
  '%1$s\'s account was deleted (%2$s)',
354
  '1: User display name, 2: User roles',
@@ -358,7 +369,7 @@ class Connector_Users extends Connector {
358
  $deleted_user = $this->_users_object_pre_deleted[ $user_id ];
359
  unset( $this->_users_object_pre_deleted[ $user_id ] );
360
  } else {
361
- // translators: Placeholders refer to a user display name, and a user role (e.g. "Jane Doe", "subscriber")
362
  $message = esc_html__( 'User account #%d was deleted', 'stream' );
363
  $display_name = $user_id;
364
  $deleted_user = $user_id;
1
  <?php
2
+ /**
3
+ * Connector for users
4
+ *
5
+ * @package WP_Stream
6
+ */
7
+
8
  namespace WP_Stream;
9
 
10
+ /**
11
+ * Class - Connector_Users
12
+ */
13
  class Connector_Users extends Connector {
14
 
15
  /**
21
 
22
  /**
23
  * Stores users object before the user being deleted.
24
+ *
25
+ * @var WP_User
26
  */
27
+ protected $_users_object_pre_deleted = array(); // @codingStandardsIgnoreLine
28
 
29
  /**
30
  * Actions registered for this connector
90
  *
91
  * @filter wp_stream_action_links_{connector}
92
  *
93
+ * @param array $links Previous links registered.
94
+ * @param Record $record Stream record.
95
  *
96
  * @return array Action links
97
  */
109
  /**
110
  * Get an array of role lables assigned to a specific user.
111
  *
112
+ * @param object|int $user User object or user ID to get roles for.
113
  *
114
  * @return array $labels An array of role labels
115
  */
141
  *
142
  * @action user_register
143
  *
144
+ * @param int $user_id Newly registered user ID.
145
  */
146
  public function callback_user_register( $user_id ) {
147
  $current_user = wp_get_current_user();
148
  $registered_user = get_user_by( 'id', $user_id );
149
 
150
+ if ( ! $current_user->ID ) { // Non logged-in user registered themselves.
151
  $message = esc_html__( 'New user registration', 'stream' );
152
  $user_to_log = $registered_user->ID;
153
+ } else { // Current logged-in user created a new user.
154
+ /* translators: %1$s: a user display name, %2$s: a user role (e.g. "Jane Doe", "subscriber") */
155
  $message = _x(
156
  'New user account created for %1$s (%2$s)',
157
  '1: User display name, 2: User role',
178
  *
179
  * @action profile_update
180
  *
181
+ * @param int $user_id Registered user ID.
182
+ * @param \WP_User $user Registered user object.
183
  */
184
  public function callback_profile_update( $user_id, $user ) {
185
  unset( $user_id );
186
 
187
  $this->log(
188
+ /* translators: %s: a user display name (e.g. "Jane Doe") */
189
  __( '%s\'s profile was updated', 'stream' ),
190
  array(
191
  'display_name' => $user->display_name,
201
  *
202
  * @action set_user_role
203
  *
204
+ * @param int $user_id User ID.
205
+ * @param string $new_role User role.
206
+ * @param array $old_roles Old user roles.
207
  */
208
  public function callback_set_user_role( $user_id, $new_role, $old_roles ) {
209
  if ( empty( $old_roles ) ) {
213
  global $wp_roles;
214
 
215
  $this->log(
216
+ /* translators: %1$s: a user display name, %2$s: a user role, %3$s: another user role (e.g. "Jane Doe", "editor", "subscriber") */
217
  _x(
218
  '%1$s\'s role was changed from %2$s to %3$s',
219
  '1: User display name, 2: Old role, 3: New role',
235
  *
236
  * @action password_reset
237
  *
238
+ * @param \WP_User $user User.
239
  */
240
  public function callback_password_reset( $user ) {
241
  $this->log(
242
+ /* translators: %s: a user display name (e.g. "Jane Doe") */
243
  __( '%s\'s password was reset', 'stream' ),
244
  array(
245
  'email' => $user->display_name,
256
  *
257
  * @action retrieve_password
258
  *
259
+ * @param string $user_login User login.
260
  */
261
  public function callback_retrieve_password( $user_login ) {
262
  if ( wp_stream_filter_var( $user_login, FILTER_VALIDATE_EMAIL ) ) {
266
  }
267
 
268
  $this->log(
269
+ /* translators: %s: a user display name (e.g. "Jane Doe") */
270
  __( '%s\'s password was requested to be reset', 'stream' ),
271
  array(
272
  'display_name' => $user->display_name,
283
  *
284
  * @action set_logged_in_cookie
285
  *
286
+ * @param string $logged_in_cookie Authenticated cookie.
287
+ * @param int $expire Unused.
288
+ * @param int $expiration Unused.
289
+ * @param int $user_id Unused.
290
  */
291
  public function callback_set_logged_in_cookie( $logged_in_cookie, $expire, $expiration, $user_id ) {
292
  unset( $logged_in_cookie );
295
  $user = get_user_by( 'id', $user_id );
296
 
297
  $this->log(
298
+ /* translators: %s: a user display name (e.g. "Jane Doe") */
299
  __( '%s logged in', 'stream' ),
300
  array(
301
  'display_name' => $user->display_name,
315
  public function callback_clear_auth_cookie() {
316
  $user = wp_get_current_user();
317
 
318
+ // For some reason, incognito mode calls clear_auth_cookie on failed login attempts.
319
  if ( empty( $user ) || ! $user->exists() ) {
320
  return;
321
  }
322
 
323
  $this->log(
324
+ /* translators: %s: a user display name (e.g. "Jane Doe") */
325
  __( '%s logged out', 'stream' ),
326
  array(
327
  'display_name' => $user->display_name,
341
  * was already removed from DB.
342
  *
343
  * @action delete_user
344
+ * @param int $user_id User ID that maybe deleted.
345
  */
346
  public function callback_delete_user( $user_id ) {
347
  if ( ! isset( $this->_users_object_pre_deleted[ $user_id ] ) ) {
353
  * Log deleted user.
354
  *
355
  * @action deleted_user
356
+ * @param int $user_id Deleted user ID.
357
  */
358
  public function callback_deleted_user( $user_id ) {
359
  $user = wp_get_current_user();
360
 
361
  if ( isset( $this->_users_object_pre_deleted[ $user_id ] ) ) {
362
+ /* translators: %1$s: a user display name, %2$s: a user role (e.g. "Jane Doe", "subscriber") */
363
  $message = _x(
364
  '%1$s\'s account was deleted (%2$s)',
365
  '1: User display name, 2: User roles',
369
  $deleted_user = $this->_users_object_pre_deleted[ $user_id ];
370
  unset( $this->_users_object_pre_deleted[ $user_id ] );
371
  } else {
372
+ /* translators: %d: a user display name, and a user role (e.g. "Jane Doe", "subscriber") */
373
  $message = esc_html__( 'User account #%d was deleted', 'stream' );
374
  $display_name = $user_id;
375
  $deleted_user = $user_id;
connectors/class-connector-widgets.php CHANGED
@@ -1,6 +1,15 @@
1
  <?php
 
 
 
 
 
 
2
  namespace WP_Stream;
3
 
 
 
 
4
  class Connector_Widgets extends Connector {
5
 
6
  /**
@@ -90,8 +99,8 @@ class Connector_Widgets extends Connector {
90
  *
91
  * @filter wp_stream_action_links_{connector}
92
  *
93
- * @param array $links Previous links registered
94
- * @param Record $record Stream record
95
  *
96
  * @return array Action links
97
  */
@@ -101,10 +110,10 @@ class Connector_Widgets extends Connector {
101
  global $wp_registered_sidebars;
102
 
103
  if ( array_key_exists( $sidebar, $wp_registered_sidebars ) ) {
104
- $links[ esc_html__( 'Edit Widget Area', 'stream' ) ] = admin_url( 'widgets.php#' . $sidebar ); // xss ok (@todo fix WPCS rule)
105
  }
106
- // @todo Also old_sidebar_id and new_sidebar_id
107
- // @todo Add Edit Widget link
108
  }
109
 
110
  return $links;
@@ -115,13 +124,13 @@ class Connector_Widgets extends Connector {
115
  *
116
  * @action update_option_sidebars_widgets
117
  *
118
- * @param array $old Old sidebars widgets
119
- * @param array $new New sidebars widgets
120
  *
121
  * @return void
122
  */
123
  public function callback_update_option_sidebars_widgets( $old, $new ) {
124
- // Disable listener if we're switching themes
125
  if ( did_action( 'after_switch_theme' ) ) {
126
  return;
127
  }
@@ -151,8 +160,10 @@ class Connector_Widgets extends Connector {
151
  }
152
 
153
  /**
154
- * @param array $old
155
- * @param array $new
 
 
156
  */
157
  protected function handle_sidebars_widgets_changes( $old, $new ) {
158
  unset( $old['array_version'] );
@@ -173,8 +184,8 @@ class Connector_Widgets extends Connector {
173
  /**
174
  * Track deactivation of widgets from sidebars
175
  *
176
- * @param array $old Old sidebars widgets
177
- * @param array $new New sidebars widgets
178
  * @return void
179
  */
180
  protected function handle_deactivated_widgets( $old, $new ) {
@@ -197,19 +208,19 @@ class Connector_Widgets extends Connector {
197
  $sidebar_name = isset( $labels[ $sidebar_id ] ) ? $labels[ $sidebar_id ] : $sidebar_id;
198
 
199
  if ( $name && $title ) {
200
- // translators: Placeholders refer to a widget name, a widget title, and a sidebar name (e.g. "Archives", "Browse", "Footer Area 1")
201
  $message = _x( '%1$s widget named "%2$s" from "%3$s" deactivated', '1: Name, 2: Title, 3: Sidebar Name', 'stream' );
202
  } elseif ( $name ) {
203
- // Empty title, but we have the name
204
- // translators: Placeholders refer to a widget name, and a sidebar name (e.g. "Archives", "Footer Area 1")
205
  $message = _x( '%1$s widget from "%3$s" deactivated', '1: Name, 3: Sidebar Name', 'stream' );
206
  } elseif ( $title ) {
207
- // Likely a single widget since no name is available
208
- // translators: Placeholders refer to a widget title, and a sidebar name (e.g. "Browse", "Footer Area 1")
209
  $message = _x( 'Unknown widget type named "%2$s" from "%3$s" deactivated', '2: Title, 3: Sidebar Name', 'stream' );
210
  } else {
211
- // Neither a name nor a title are available, so use the widget ID
212
- // translators: Placeholders refer to a widget ID, and a sidebar name (e.g. "42", "Footer Area 1")
213
  $message = _x( '%4$s widget from "%3$s" deactivated', '4: Widget ID, 3: Sidebar Name', 'stream' );
214
  }
215
 
@@ -228,8 +239,8 @@ class Connector_Widgets extends Connector {
228
  /**
229
  * Track reactivation of widgets from sidebars
230
  *
231
- * @param array $old Old sidebars widgets
232
- * @param array $new New sidebars widgets
233
  * @return void
234
  */
235
  protected function handle_reactivated_widgets( $old, $new ) {
@@ -250,19 +261,19 @@ class Connector_Widgets extends Connector {
250
  $title = $this->get_widget_title( $widget_id );
251
 
252
  if ( $name && $title ) {
253
- // translators: Placeholders refer to a widget name, and a widget title (e.g. "Archives", "Browse")
254
  $message = _x( '%1$s widget named "%2$s" reactivated', '1: Name, 2: Title', 'stream' );
255
  } elseif ( $name ) {
256
- // Empty title, but we have the name
257
- // translators: Placeholder refers to a widget name (e.g. "Archives")
258
  $message = _x( '%1$s widget reactivated', '1: Name', 'stream' );
259
  } elseif ( $title ) {
260
- // Likely a single widget since no name is available
261
- // translators: Placeholder refers to a widget title (e.g. "Browse")
262
  $message = _x( 'Unknown widget type named "%2$s" reactivated', '2: Title', 'stream' );
263
  } else {
264
- // Neither a name nor a title are available, so use the widget ID
265
- // translators: Placeholder refers to a widget ID (e.g. "42")
266
  $message = _x( '%3$s widget reactivated', '3: Widget ID', 'stream' );
267
  }
268
 
@@ -281,8 +292,8 @@ class Connector_Widgets extends Connector {
281
  /**
282
  * Track deletion of widgets from sidebars
283
  *
284
- * @param array $old Old sidebars widgets
285
- * @param array $new New sidebars widgets
286
  * @return void
287
  */
288
  protected function handle_widget_removal( $old, $new ) {
@@ -310,19 +321,19 @@ class Connector_Widgets extends Connector {
310
  $sidebar_name = isset( $labels[ $sidebar_id ] ) ? $labels[ $sidebar_id ] : $sidebar_id;
311
 
312
  if ( $name && $title ) {
313
- // translators: Placeholders refer to a widget name, a widget title, and a sidebar name (e.g. "Archives", "Browse", "Footer Area 1")
314
  $message = _x( '%1$s widget named "%2$s" removed from "%3$s"', '1: Name, 2: Title, 3: Sidebar Name', 'stream' );
315
  } elseif ( $name ) {
316
- // Empty title, but we have the name
317
- // translators: Placeholders refer to a widget name, and a sidebar name (e.g. "Archives", "Footer Area 1")
318
  $message = _x( '%1$s widget removed from "%3$s"', '1: Name, 3: Sidebar Name', 'stream' );
319
  } elseif ( $title ) {
320
- // Likely a single widget since no name is available
321
- // translators: Placeholders refer to a widget title, and a sidebar name (e.g. "Browse", "Footer Area 1")
322
  $message = _x( 'Unknown widget type named "%2$s" removed from "%3$s"', '2: Title, 3: Sidebar Name', 'stream' );
323
  } else {
324
- // Neither a name nor a title are available, so use the widget ID
325
- // translators: Placeholders refer to a widget ID, and a sidebar name (e.g. "42", "Footer Area 1")
326
  $message = _x( '%4$s widget removed from "%3$s"', '4: Widget ID, 3: Sidebar Name', 'stream' );
327
  }
328
 
@@ -341,8 +352,8 @@ class Connector_Widgets extends Connector {
341
  /**
342
  * Track reactivation of widgets from sidebars
343
  *
344
- * @param array $old Old sidebars widgets
345
- * @param array $new New sidebars widgets
346
  * @return void
347
  */
348
  protected function handle_widget_addition( $old, $new ) {
@@ -367,19 +378,19 @@ class Connector_Widgets extends Connector {
367
  $sidebar_name = isset( $labels[ $sidebar_id ] ) ? $labels[ $sidebar_id ] : $sidebar_id;
368
 
369
  if ( $name && $title ) {
370
- // translators: Placeholders refer to a widget name, a widget title, and a sidebar name (e.g. "Archives", "Browse", "Footer Area 1")
371
  $message = _x( '%1$s widget named "%2$s" added to "%3$s"', '1: Name, 2: Title, 3: Sidebar Name', 'stream' );
372
  } elseif ( $name ) {
373
- // Empty title, but we have the name
374
- // translators: Placeholders refer to a widget name, and a sidebar name (e.g. "Archives", "Footer Area 1")
375
  $message = _x( '%1$s widget added to "%3$s"', '1: Name, 3: Sidebar Name', 'stream' );
376
  } elseif ( $title ) {
377
- // Likely a single widget since no name is available
378
- // translators: Placeholders refer to a widget title, and a sidebar name (e.g. "Browse", "Footer Area 1")
379
  $message = _x( 'Unknown widget type named "%2$s" added to "%3$s"', '2: Title, 3: Sidebar Name', 'stream' );
380
  } else {
381
- // Neither a name nor a title are available, so use the widget ID
382
- // translators: Placeholders refer to a widget ID, and a sidebar name (e.g. "42", "Footer Area 1")
383
  $message = _x( '%4$s widget added to "%3$s"', '4: Widget ID, 3: Sidebar Name', 'stream' );
384
  }
385
 
@@ -398,8 +409,8 @@ class Connector_Widgets extends Connector {
398
  /**
399
  * Track reordering of widgets
400
  *
401
- * @param array $old Old sidebars widgets
402
- * @param array $new New sidebars widgets
403
  * @return void
404
  */
405
  protected function handle_widget_reordering( $old, $new ) {
@@ -410,7 +421,7 @@ class Connector_Widgets extends Connector {
410
  continue;
411
  }
412
 
413
- // Use intersect to ignore widget additions and removals
414
  $all_widget_ids = array_unique( array_merge( $old[ $sidebar_id ], $new[ $sidebar_id ] ) );
415
  $common_widget_ids = array_intersect( $old[ $sidebar_id ], $new[ $sidebar_id ] );
416
  $uncommon_widget_ids = array_diff( $all_widget_ids, $common_widget_ids );
@@ -423,7 +434,7 @@ class Connector_Widgets extends Connector {
423
  $sidebar_name = isset( $labels[ $sidebar_id ] ) ? $labels[ $sidebar_id ] : $sidebar_id;
424
  $old_widget_ids = $old[ $sidebar_id ];
425
 
426
- // translators: Placeholder refers to a sidebar name (e.g. "Footer Area 1")
427
  $message = _x( 'Widgets reordered in "%s"', 'Sidebar name', 'stream' );
428
  $message = sprintf( $message, $sidebar_name );
429
 
@@ -442,8 +453,8 @@ class Connector_Widgets extends Connector {
442
  /**
443
  * Track movement of widgets to other sidebars
444
  *
445
- * @param array $old Old sidebars widgets
446
- * @param array $new New sidebars widgets
447
  * @return void
448
  */
449
  protected function handle_widget_moved( $old, $new ) {
@@ -457,7 +468,7 @@ class Connector_Widgets extends Connector {
457
  $new_widget_ids = array_diff( $new[ $new_sidebar_id ], $old[ $new_sidebar_id ] );
458
 
459
  foreach ( $new_widget_ids as $widget_id ) {
460
- // Now find the sidebar that the widget was originally located in, as long it is not wp_inactive_widgets
461
  $old_sidebar_id = null;
462
  foreach ( $old as $sidebar_id => $old_widget_ids ) {
463
  if ( in_array( $widget_id, $old_widget_ids, true ) ) {
@@ -479,19 +490,19 @@ class Connector_Widgets extends Connector {
479
  $new_sidebar_name = isset( $labels[ $new_sidebar_id ] ) ? $labels[ $new_sidebar_id ] : $new_sidebar_id;
480
 
481
  if ( $name && $title ) {
482
- // translators: Placeholders refer to a widget name, a widget title, a sidebar name, and another sidebar name (e.g. "Archives", "Browse", "Footer Area 1", "Footer Area 2")
483
  $message = _x( '%1$s widget named "%2$s" moved from "%4$s" to "%5$s"', '1: Name, 2: Title, 4: Old Sidebar Name, 5: New Sidebar Name', 'stream' );
484
  } elseif ( $name ) {
485
- // Empty title, but we have the name
486
- // translators: Placeholders refer to a widget name, a sidebar name, and another sidebar name (e.g. "Archives", "Footer Area 1", "Footer Area 2")
487
  $message = _x( '%1$s widget moved from "%4$s" to "%5$s"', '1: Name, 4: Old Sidebar Name, 5: New Sidebar Name', 'stream' );
488
  } elseif ( $title ) {
489
- // Likely a single widget since no name is available
490
- // translators: Placeholders refer to a widget title, a sidebar name, and another sidebar name (e.g. "Browse", "Footer Area 1", "Footer Area 2")
491
  $message = _x( 'Unknown widget type named "%2$s" moved from "%4$s" to "%5$s"', '2: Title, 4: Old Sidebar Name, 5: New Sidebar Name', 'stream' );
492
  } else {
493
- // Neither a name nor a title are available, so use the widget ID
494
- // translators: Placeholders refer to a widget ID, a sidebar name, and another sidebar name (e.g. "42", "Footer Area 1", "Footer Area 2")
495
  $message = _x( '%3$s widget moved from "%4$s" to "%5$s"', '3: Widget ID, 4: Old Sidebar Name, 5: New Sidebar Name', 'stream' );
496
  }
497
 
@@ -515,9 +526,9 @@ class Connector_Widgets extends Connector {
515
  *
516
  * @action updated_option
517
  *
518
- * @param string $option_name
519
- * @param array $old_value
520
- * @param array $new_value
521
  */
522
  public function callback_updated_option( $option_name, $old_value, $new_value ) {
523
  if ( ! preg_match( '/^widget_(.+)$/', $option_name, $matches ) || ! is_array( $new_value ) ) {
@@ -588,9 +599,9 @@ class Connector_Widgets extends Connector {
588
  $deletes[] = compact( 'name', 'title', 'widget_id', 'sidebar_id', 'instance' );
589
  }
590
  } else {
591
- // Doing our best guess for tracking changes to old single widgets, assuming their options start with 'widget_'
592
  $widget_id = $widget_id_base;
593
- $name = $widget_id; // There aren't names available for single widgets
594
  $title = ! empty( $new_value['title'] ) ? $new_value['title'] : null;
595
  $sidebar_id = $this->get_widget_sidebar_id( $widget_id );
596
  $old_instance = $old_value;
@@ -605,19 +616,19 @@ class Connector_Widgets extends Connector {
605
  */
606
  foreach ( $updates as $update ) {
607
  if ( $update['name'] && $update['title'] ) {
608
- // translators: Placeholders refer to a widget name, a widget title, and a sidebar name (e.g. "Archives", "Browse", "Footer Area 1")
609
  $message = _x( '%1$s widget named "%2$s" in "%3$s" updated', '1: Name, 2: Title, 3: Sidebar Name', 'stream' );
610
  } elseif ( $update['name'] ) {
611
- // Empty title, but we have the name
612
- // translators: Placeholders refer to a widget name, and a sidebar name (e.g. "Archives", "Footer Area 1")
613
  $message = _x( '%1$s widget in "%3$s" updated', '1: Name, 3: Sidebar Name', 'stream' );
614
  } elseif ( $update['title'] ) {
615
- // Likely a single widget since no name is available
616
- // translators: Placeholders refer to a widget title, and a sidebar name (e.g. "Browse", "Footer Area 1")
617
  $message = _x( 'Unknown widget type named "%2$s" in "%3$s" updated', '2: Title, 3: Sidebar Name', 'stream' );
618
  } else {
619
- // Neither a name nor a title are available, so use the widget ID
620
- // translators: Placeholders refer to a widget ID, and a sidebar name (e.g. "42", "Footer Area 1")
621
  $message = _x( '%4$s widget in "%3$s" updated', '4: Widget ID, 3: Sidebar Name', 'stream' );
622
  }
623
 
@@ -643,25 +654,25 @@ class Connector_Widgets extends Connector {
643
  * actions would be useful to log.
644
  */
645
  if ( $this->verbose_widget_created_deleted_actions ) {
646
- // We should only do these if not captured by an update to the sidebars_widgets option
647
  /**
648
  * Log created actions
649
  */
650
  foreach ( $creates as $create ) {
651
  if ( $create['name'] && $create['title'] ) {
652
- // translators: Placeholders refer to a widget name, and a widget title (e.g. "Archives", "Browse")
653
  $message = _x( '%1$s widget named "%2$s" created', '1: Name, 2: Title', 'stream' );
654
  } elseif ( $create['name'] ) {
655
- // Empty title, but we have the name
656
- // translators: Placeholder refers to a widget name (e.g. "Archives")
657
  $message = _x( '%1$s widget created', '1: Name', 'stream' );
658
  } elseif ( $create['title'] ) {
659
- // Likely a single widget since no name is available
660
- // translators: Placeholder refers to a widget title (e.g. "Browse")
661
  $message = _x( 'Unknown widget type named "%2$s" created', '2: Title', 'stream' );
662
  } else {
663
- // Neither a name nor a title are available, so use the widget ID
664
- // translators: Placeholder refers to a widget ID (e.g. "42")
665
  $message = _x( '%3$s widget created', '3: Widget ID', 'stream' );
666
  }
667
 
@@ -683,19 +694,19 @@ class Connector_Widgets extends Connector {
683
  */
684
  foreach ( $deletes as $delete ) {
685
  if ( $delete['name'] && $delete['title'] ) {
686
- // translators: Placeholders refer to a widget name, and a widget title (e.g. "Archives", "Browse")
687
  $message = _x( '%1$s widget named "%2$s" deleted', '1: Name, 2: Title', 'stream' );
688
  } elseif ( $delete['name'] ) {
689
- // Empty title, but we have the name
690
- // translators: Placeholder refers to a widget name (e.g. "Archives")
691
  $message = _x( '%1$s widget deleted', '1: Name', 'stream' );
692
  } elseif ( $delete['title'] ) {
693
- // Likely a single widget since no name is available
694
- // translators: Placeholder refers to a widget title (e.g. "Browse")
695
  $message = _x( 'Unknown widget type named "%2$s" deleted', '2: Title', 'stream' );
696
  } else {
697
- // Neither a name nor a title are available, so use the widget ID
698
- // translators: Placeholder refers to a widget ID (e.g. "42")
699
  $message = _x( '%3$s widget deleted', '3: Widget ID', 'stream' );
700
  }
701
 
@@ -715,7 +726,9 @@ class Connector_Widgets extends Connector {
715
  }
716
 
717
  /**
718
- * @param string $widget_id
 
 
719
  *
720
  * @return string
721
  */
@@ -725,7 +738,9 @@ class Connector_Widgets extends Connector {
725
  }
726
 
727
  /**
728
- * @param string $widget_id
 
 
729
  *
730
  * @return string|null
731
  */
@@ -735,7 +750,9 @@ class Connector_Widgets extends Connector {
735
  }
736
 
737
  /**
738
- * @param $widget_id
 
 
739
  *
740
  * @return array|null
741
  */
@@ -751,7 +768,9 @@ class Connector_Widgets extends Connector {
751
  }
752
 
753
  /**
754
- * @param string $widget_id
 
 
755
  *
756
  * @return \WP_Widget|null
757
  */
@@ -781,7 +800,7 @@ class Connector_Widgets extends Connector {
781
  /**
782
  * Returns widget instance settings
783
  *
784
- * @param string $widget_id Widget ID, ex: pages-1
785
  *
786
  * @return array|null Widget instance
787
  */
@@ -798,7 +817,7 @@ class Connector_Widgets extends Connector {
798
  $instance = $settings[ $multi_number ];
799
  }
800
  } else {
801
- // Single widgets, try our best guess at the option used
802
  $potential_instance = get_option( "widget_{$widget_id}" );
803
 
804
  if ( ! empty( $potential_instance ) && ! empty( $potential_instance['title'] ) ) {
@@ -830,7 +849,7 @@ class Connector_Widgets extends Connector {
830
  /**
831
  * Return the sidebar of a certain widget, based on widget_id
832
  *
833
- * @param string $widget_id Widget id, ex: pages-1
834
  *
835
  * @return string Sidebar id
836
  */
1
  <?php
2
+ /**
3
+ * Connector for Widgets
4
+ *
5
+ * @package WP_Stream
6
+ */
7
+
8
  namespace WP_Stream;
9
 
10
+ /**
11
+ * Class - Connector_Widgets
12
+ */
13
  class Connector_Widgets extends Connector {
14
 
15
  /**
99
  *
100
  * @filter wp_stream_action_links_{connector}
101
  *
102
+ * @param array $links Previous links registered.
103
+ * @param Record $record Stream record.
104
  *
105
  * @return array Action links
106
  */
110
  global $wp_registered_sidebars;
111
 
112
  if ( array_key_exists( $sidebar, $wp_registered_sidebars ) ) {
113
+ $links[ esc_html__( 'Edit Widget Area', 'stream' ) ] = admin_url( 'widgets.php#' . $sidebar ); // xss ok (@todo fix WPCS rule).
114
  }
115
+ // @todo Also old_sidebar_id and new_sidebar_id.
116
+ // @todo Add Edit Widget link.
117
  }
118
 
119
  return $links;
124
  *
125
  * @action update_option_sidebars_widgets
126
  *
127
+ * @param array $old Old sidebars widgets.
128
+ * @param array $new New sidebars widgets.
129
  *
130
  * @return void
131
  */
132
  public function callback_update_option_sidebars_widgets( $old, $new ) {
133
+ // Disable listener if we're switching themes.
134
  if ( did_action( 'after_switch_theme' ) ) {
135
  return;
136
  }
160
  }
161
 
162
  /**
163
+ * Processes tracked widget actions
164
+ *
165
+ * @param array $old Old sidebar widgets.
166
+ * @param array $new New sidebar widgets.
167
  */
168
  protected function handle_sidebars_widgets_changes( $old, $new ) {
169
  unset( $old['array_version'] );
184
  /**
185
  * Track deactivation of widgets from sidebars
186
  *
187
+ * @param array $old Old sidebars widgets.
188
+ * @param array $new New sidebars widgets.
189
  * @return void
190
  */
191
  protected function handle_deactivated_widgets( $old, $new ) {
208
  $sidebar_name = isset( $labels[ $sidebar_id ] ) ? $labels[ $sidebar_id ] : $sidebar_id;
209
 
210
  if ( $name && $title ) {
211
+ /* translators: %1$s: a widget name, %2$s: a widget title, %3$s: a sidebar name (e.g. "Archives", "Browse", "Footer Area 1") */
212
  $message = _x( '%1$s widget named "%2$s" from "%3$s" deactivated', '1: Name, 2: Title, 3: Sidebar Name', 'stream' );
213
  } elseif ( $name ) {
214
+ // Empty title, but we have the name.
215
+ /* translators: %1$s: a widget name, %3$s: a sidebar name (e.g. "Archives", "Footer Area 1") */
216
  $message = _x( '%1$s widget from "%3$s" deactivated', '1: Name, 3: Sidebar Name', 'stream' );
217
  } elseif ( $title ) {
218
+ // Likely a single widget since no name is available.
219
+ /* translators: %1$s: a widget title, %2$s: a sidebar name (e.g. "Browse", "Footer Area 1") */
220
  $message = _x( 'Unknown widget type named "%2$s" from "%3$s" deactivated', '2: Title, 3: Sidebar Name', 'stream' );
221
  } else {
222
+ // Neither a name nor a title are available, so use the widget ID.
223
+ /* translators: %4$s: a widget ID, %3$s: a sidebar name (e.g. "42", "Footer Area 1") */
224
  $message = _x( '%4$s widget from "%3$s" deactivated', '4: Widget ID, 3: Sidebar Name', 'stream' );
225
  }
226
 
239
  /**
240
  * Track reactivation of widgets from sidebars
241
  *
242
+ * @param array $old Old sidebars widgets.
243
+ * @param array $new New sidebars widgets.
244
  * @return void
245
  */
246
  protected function handle_reactivated_widgets( $old, $new ) {
261
  $title = $this->get_widget_title( $widget_id );
262
 
263
  if ( $name && $title ) {
264
+ /* translators: %1$s: a widget name, %2$s: a widget title (e.g. "Archives", "Browse") */
265
  $message = _x( '%1$s widget named "%2$s" reactivated', '1: Name, 2: Title', 'stream' );
266
  } elseif ( $name ) {
267
+ // Empty title, but we have the name.
268
+ /* translators: %1$s: a widget name (e.g. "Archives") */
269
  $message = _x( '%1$s widget reactivated', '1: Name', 'stream' );
270
  } elseif ( $title ) {
271
+ // Likely a single widget since no name is available.
272
+ /* translators: %2$s: a widget title (e.g. "Browse") */
273
  $message = _x( 'Unknown widget type named "%2$s" reactivated', '2: Title', 'stream' );
274
  } else {
275
+ // Neither a name nor a title are available, so use the widget ID.
276
+ /* translators: %3$s: a widget ID (e.g. "42") */
277
  $message = _x( '%3$s widget reactivated', '3: Widget ID', 'stream' );
278
  }
279
 
292
  /**
293
  * Track deletion of widgets from sidebars
294
  *
295
+ * @param array $old Old sidebars widgets.
296
+ * @param array $new New sidebars widgets.
297
  * @return void
298
  */
299
  protected function handle_widget_removal( $old, $new ) {
321
  $sidebar_name = isset( $labels[ $sidebar_id ] ) ? $labels[ $sidebar_id ] : $sidebar_id;
322
 
323
  if ( $name && $title ) {
324
+ /* translators: %1$s: a widget name, %2$s: a widget title, %3$s: a sidebar name (e.g. "Archives", "Browse", "Footer Area 1") */
325
  $message = _x( '%1$s widget named "%2$s" removed from "%3$s"', '1: Name, 2: Title, 3: Sidebar Name', 'stream' );
326
  } elseif ( $name ) {
327
+ // Empty title, but we have the name.
328
+ /* translators: %1$s: a widget name, %3$s: a sidebar name (e.g. "Archives", "Footer Area 1") */
329
  $message = _x( '%1$s widget removed from "%3$s"', '1: Name, 3: Sidebar Name', 'stream' );
330
  } elseif ( $title ) {
331
+ // Likely a single widget since no name is available.
332
+ /* translators: %2$s: a widget title, %3$s: a sidebar name (e.g. "Browse", "Footer Area 1") */
333
  $message = _x( 'Unknown widget type named "%2$s" removed from "%3$s"', '2: Title, 3: Sidebar Name', 'stream' );
334
  } else {
335
+ // Neither a name nor a title are available, so use the widget ID.
336
+ /* translators: %4$s: a widget ID, %3$s: a sidebar name (e.g. "42", "Footer Area 1") */
337
  $message = _x( '%4$s widget removed from "%3$s"', '4: Widget ID, 3: Sidebar Name', 'stream' );
338
  }
339
 
352
  /**
353
  * Track reactivation of widgets from sidebars
354
  *
355
+ * @param array $old Old sidebars widgets.
356
+ * @param array $new New sidebars widgets.
357
  * @return void
358
  */
359
  protected function handle_widget_addition( $old, $new ) {
378
  $sidebar_name = isset( $labels[ $sidebar_id ] ) ? $labels[ $sidebar_id ] : $sidebar_id;
379
 
380
  if ( $name && $title ) {
381
+ /* translators: %1$s: a widget name, %2$s: a widget title, %3$s: a sidebar name (e.g. "Archives", "Browse", "Footer Area 1") */
382
  $message = _x( '%1$s widget named "%2$s" added to "%3$s"', '1: Name, 2: Title, 3: Sidebar Name', 'stream' );
383
  } elseif ( $name ) {
384
+ // Empty title, but we have the name.
385
+ /* translators: %1$s: a widget name, %3$s: a sidebar name (e.g. "Archives", "Footer Area 1") */
386
  $message = _x( '%1$s widget added to "%3$s"', '1: Name, 3: Sidebar Name', 'stream' );
387
  } elseif ( $title ) {
388
+ // Likely a single widget since no name is available.
389
+ /* translators: %2$s: a widget title, %3$s: a sidebar name (e.g. "Browse", "Footer Area 1") */
390
  $message = _x( 'Unknown widget type named "%2$s" added to "%3$s"', '2: Title, 3: Sidebar Name', 'stream' );
391
  } else {
392
+ // Neither a name nor a title are available, so use the widget ID.
393
+ /* translators: %4$s: a widget ID, %3$s: a sidebar name (e.g. "42", "Footer Area 1") */
394
  $message = _x( '%4$s widget added to "%3$s"', '4: Widget ID, 3: Sidebar Name', 'stream' );
395
  }
396
 
409
  /**
410
  * Track reordering of widgets
411
  *
412
+ * @param array $old Old sidebars widgets.
413
+ * @param array $new New sidebars widgets.
414
  * @return void
415
  */
416
  protected function handle_widget_reordering( $old, $new ) {
421
  continue;
422
  }
423
 
424
+ // Use intersect to ignore widget additions and removals.
425
  $all_widget_ids = array_unique( array_merge( $old[ $sidebar_id ], $new[ $sidebar_id ] ) );
426
  $common_widget_ids = array_intersect( $old[ $sidebar_id ], $new[ $sidebar_id ] );
427
  $uncommon_widget_ids = array_diff( $all_widget_ids, $common_widget_ids );
434
  $sidebar_name = isset( $labels[ $sidebar_id ] ) ? $labels[ $sidebar_id ] : $sidebar_id;
435
  $old_widget_ids = $old[ $sidebar_id ];
436
 
437
+ /* translators: %s: a sidebar name (e.g. "Footer Area 1") */
438
  $message = _x( 'Widgets reordered in "%s"', 'Sidebar name', 'stream' );
439
  $message = sprintf( $message, $sidebar_name );
440
 
453
  /**
454
  * Track movement of widgets to other sidebars
455
  *
456
+ * @param array $old Old sidebars widgets.
457
+ * @param array $new New sidebars widgets.
458
  * @return void
459
  */
460
  protected function handle_widget_moved( $old, $new ) {
468
  $new_widget_ids = array_diff( $new[ $new_sidebar_id ], $old[ $new_sidebar_id ] );
469
 
470
  foreach ( $new_widget_ids as $widget_id ) {
471
+ // Now find the sidebar that the widget was originally located in, as long it is not wp_inactive_widgets.
472
  $old_sidebar_id = null;
473
  foreach ( $old as $sidebar_id => $old_widget_ids ) {
474
  if ( in_array( $widget_id, $old_widget_ids, true ) ) {
490
  $new_sidebar_name = isset( $labels[ $new_sidebar_id ] ) ? $labels[ $new_sidebar_id ] : $new_sidebar_id;
491
 
492
  if ( $name && $title ) {
493
+ /* translators: %1$s: a widget name, %2$s: a widget title, %4$s: a sidebar name, %5$s: another sidebar name (e.g. "Archives", "Browse", "Footer Area 1", "Footer Area 2") */
494
  $message = _x( '%1$s widget named "%2$s" moved from "%4$s" to "%5$s"', '1: Name, 2: Title, 4: Old Sidebar Name, 5: New Sidebar Name', 'stream' );
495
  } elseif ( $name ) {
496
+ // Empty title, but we have the name.
497
+ /* translators: %1$s: a widget name, %4$s: a sidebar name, %5$s: another sidebar name (e.g. "Archives", "Footer Area 1", "Footer Area 2") */
498
  $message = _x( '%1$s widget moved from "%4$s" to "%5$s"', '1: Name, 4: Old Sidebar Name, 5: New Sidebar Name', 'stream' );
499
  } elseif ( $title ) {
500
+ // Likely a single widget since no name is available.
501
+ /* translators: %2$s: a widget title, %4$s: a sidebar name, %5$s: another sidebar name (e.g. "Browse", "Footer Area 1", "Footer Area 2") */
502
  $message = _x( 'Unknown widget type named "%2$s" moved from "%4$s" to "%5$s"', '2: Title, 4: Old Sidebar Name, 5: New Sidebar Name', 'stream' );
503
  } else {
504
+ // Neither a name nor a title are available, so use the widget ID.
505
+ /* translators: %3$s: a widget ID, %4$s: a sidebar name, %5$s: another sidebar name (e.g. "42", "Footer Area 1", "Footer Area 2") */
506
  $message = _x( '%3$s widget moved from "%4$s" to "%5$s"', '3: Widget ID, 4: Old Sidebar Name, 5: New Sidebar Name', 'stream' );
507
  }
508
 
526
  *
527
  * @action updated_option
528
  *
529
+ * @param string $option_name Option key.
530
+ * @param array $old_value Old value.
531
+ * @param array $new_value New value.
532
  */
533
  public function callback_updated_option( $option_name, $old_value, $new_value ) {
534
  if ( ! preg_match( '/^widget_(.+)$/', $option_name, $matches ) || ! is_array( $new_value ) ) {
599
  $deletes[] = compact( 'name', 'title', 'widget_id', 'sidebar_id', 'instance' );
600
  }
601
  } else {
602
+ // Doing our best guess for tracking changes to old single widgets, assuming their options start with 'widget_'.
603
  $widget_id = $widget_id_base;
604
+ $name = $widget_id; // There aren't names available for single widgets.
605
  $title = ! empty( $new_value['title'] ) ? $new_value['title'] : null;
606
  $sidebar_id = $this->get_widget_sidebar_id( $widget_id );
607
  $old_instance = $old_value;
616
  */
617
  foreach ( $updates as $update ) {
618
  if ( $update['name'] && $update['title'] ) {
619
+ /* translators: %1$s: a widget name, %2$s: a widget title, %3$s: a sidebar name (e.g. "Archives", "Browse", "Footer Area 1") */
620
  $message = _x( '%1$s widget named "%2$s" in "%3$s" updated', '1: Name, 2: Title, 3: Sidebar Name', 'stream' );
621
  } elseif ( $update['name'] ) {
622
+ // Empty title, but we have the name.
623
+ /* translators: %1$s: a widget name, %3$s: a sidebar name (e.g. "Archives", "Footer Area 1") */
624
  $message = _x( '%1$s widget in "%3$s" updated', '1: Name, 3: Sidebar Name', 'stream' );
625
  } elseif ( $update['title'] ) {
626
+ // Likely a single widget since no name is available.
627
+ /* translators: %2$s: a widget title, %3$s: a sidebar name (e.g. "Browse", "Footer Area 1") */
628
  $message = _x( 'Unknown widget type named "%2$s" in "%3$s" updated', '2: Title, 3: Sidebar Name', 'stream' );
629
  } else {
630
+ // Neither a name nor a title are available, so use the widget ID.
631
+ /* translators: %4$s: a widget ID, %3$s: a sidebar name (e.g. "42", "Footer Area 1") */
632
  $message = _x( '%4$s widget in "%3$s" updated', '4: Widget ID, 3: Sidebar Name', 'stream' );
633
  }
634
 
654
  * actions would be useful to log.
655
  */
656
  if ( $this->verbose_widget_created_deleted_actions ) {
657
+ // We should only do these if not captured by an update to the sidebars_widgets option.
658
  /**
659
  * Log created actions
660
  */
661
  foreach ( $creates as $create ) {
662
  if ( $create['name'] && $create['title'] ) {
663
+ /* translators: %1$s: a widget name, %2$s: a widget title (e.g. "Archives", "Browse") */
664
  $message = _x( '%1$s widget named "%2$s" created', '1: Name, 2: Title', 'stream' );
665
  } elseif ( $create['name'] ) {
666
+ // Empty title, but we have the name.
667
+ /* translators: %1$s: a widget name (e.g. "Archives") */
668
  $message = _x( '%1$s widget created', '1: Name', 'stream' );
669
  } elseif ( $create['title'] ) {
670
+ // Likely a single widget since no name is available.
671
+ /* translators: %2$s: a widget title (e.g. "Browse") */
672
  $message = _x( 'Unknown widget type named "%2$s" created', '2: Title', 'stream' );
673
  } else {
674
+ // Neither a name nor a title are available, so use the widget ID.
675
+ /* translators: %3$s: a widget ID (e.g. "42") */
676
  $message = _x( '%3$s widget created', '3: Widget ID', 'stream' );
677
  }
678
 
694
  */
695
  foreach ( $deletes as $delete ) {
696
  if ( $delete['name'] && $delete['title'] ) {
697
+ /* translators: %1$s: a widget name, %2$s: a widget title (e.g. "Archives", "Browse") */
698
  $message = _x( '%1$s widget named "%2$s" deleted', '1: Name, 2: Title', 'stream' );
699
  } elseif ( $delete['name'] ) {
700
+ // Empty title, but we have the name.
701
+ /* translators: %1$s: a widget name (e.g. "Archives") */
702
  $message = _x( '%1$s widget deleted', '1: Name', 'stream' );
703
  } elseif ( $delete['title'] ) {
704
+ // Likely a single widget since no name is available.
705
+ /* translators: %2$s: a widget title (e.g. "Browse") */
706
  $message = _x( 'Unknown widget type named "%2$s" deleted', '2: Title', 'stream' );
707
  } else {
708
+ // Neither a name nor a title are available, so use the widget ID.
709
+ /* translators: %3$s: a widget ID (e.g. "42") */
710
  $message = _x( '%3$s widget deleted', '3: Widget ID', 'stream' );
711
  }
712
 
726
  }
727
 
728
  /**
729
+ * Returns widget title.
730
+ *
731
+ * @param string $widget_id Widget instance ID.
732
  *
733
  * @return string
734
  */
738
  }
739
 
740
  /**
741
+ * Returns widget name.
742
+ *
743
+ * @param string $widget_id Widget instance ID.
744
  *
745
  * @return string|null
746
  */
750
  }
751
 
752
  /**
753
+ * Parses widget instance ID and widget type data.
754
+ *
755
+ * @param string $widget_id Widget instance ID.
756
  *
757
  * @return array|null
758
  */
768
  }
769
 
770
  /**
771
+ * Returns widget object.
772
+ *
773
+ * @param string $widget_id Widget instance ID.
774
  *
775
  * @return \WP_Widget|null
776
  */
800
  /**
801
  * Returns widget instance settings
802
  *
803
+ * @param string $widget_id Widget ID, ex: pages-1.
804
  *
805
  * @return array|null Widget instance
806
  */
817
  $instance = $settings[ $multi_number ];
818
  }
819
  } else {
820
+ // Single widgets, try our best guess at the option used.
821
  $potential_instance = get_option( "widget_{$widget_id}" );
822
 
823
  if ( ! empty( $potential_instance ) && ! empty( $potential_instance['title'] ) ) {
849
  /**
850
  * Return the sidebar of a certain widget, based on widget_id
851
  *
852
+ * @param string $widget_id Widget id, ex: pages-1.
853
  *
854
  * @return string Sidebar id
855
  */
connectors/class-connector-woocommerce.php CHANGED
@@ -1,6 +1,15 @@
1
  <?php
 
 
 
 
 
 
2
  namespace WP_Stream;
3
 
 
 
 
4
  class Connector_Woocommerce extends Connector {
5
  /**
6
  * Context name
@@ -35,6 +44,11 @@ class Connector_Woocommerce extends Connector {
35
  'woocommerce_tax_rate_deleted',
36
  );
37
 
 
 
 
 
 
38
  public $taxonomies = array(
39
  'product_type',
40
  'product_cat',
@@ -43,6 +57,11 @@ class Connector_Woocommerce extends Connector {
43
  'shop_order_status',
44
  );
45
 
 
 
 
 
 
46
  public $post_types = array(
47
  'product',
48
  'product_variation',
@@ -50,14 +69,37 @@ class Connector_Woocommerce extends Connector {
50
  'shop_coupon',
51
  );
52
 
 
 
 
 
 
53
  private $order_update_logged = false;
54
 
 
 
 
 
 
55
  private $settings_pages = array();
56
 
 
 
 
 
 
57
  private $settings = array();
58
 
 
 
 
 
 
59
  private $plugin_version = null;
60
 
 
 
 
61
  public function register() {
62
  parent::register();
63
 
@@ -208,8 +250,8 @@ class Connector_Woocommerce extends Connector {
208
  *
209
  * @filter wp_stream_action_links_{connector}
210
  *
211
- * @param array $links Previous links registered
212
- * @param Record $record Stream record
213
  *
214
  * @return array Action links
215
  */
@@ -219,7 +261,7 @@ class Connector_Woocommerce extends Connector {
219
  if ( $edit_post_link ) {
220
  $posts_connector = new Connector_Posts();
221
  $post_type_name = $posts_connector->get_post_type_name( get_post_type( $record->object_id ) );
222
- // translators: Placeholder refers to a post type singular name (e.g. "Post")
223
  $links[ sprintf( esc_html_x( 'Edit %s', 'Post type singular name', 'stream' ), $post_type_name ) ] = $edit_post_link;
224
  }
225
 
@@ -236,7 +278,7 @@ class Connector_Woocommerce extends Connector {
236
  $option_section = $record->get_meta( 'section', true );
237
 
238
  if ( $option_key && $option_tab ) {
239
- // translators: Placeholder refers to a context (e.g. "Attribute")
240
  $text = sprintf( esc_html__( 'Edit WooCommerce %s', 'stream' ), $context_labels[ $record->context ] );
241
  $url = add_query_arg(
242
  array(
@@ -244,7 +286,7 @@ class Connector_Woocommerce extends Connector {
244
  'tab' => $option_tab,
245
  'section' => $option_section,
246
  ),
247
- admin_url( 'admin.php' ) // Not self_admin_url here, as WooCommerce doesn't exist in Network Admin
248
  );
249
 
250
  $links[ $text ] = $url . '#wp-stream-highlight:' . $option_key;
@@ -259,7 +301,7 @@ class Connector_Woocommerce extends Connector {
259
  *
260
  * @filter wp_stream_posts_exclude_post_types
261
  *
262
- * @param array $post_types Ignored post types
263
  *
264
  * @return array Filtered post types
265
  */
@@ -275,7 +317,7 @@ class Connector_Woocommerce extends Connector {
275
  *
276
  * @filter wp_stream_commnent_exclude_comment_types
277
  *
278
- * @param array $comment_types Ignored post types
279
  *
280
  * @return array Filtered post types
281
  */
@@ -290,27 +332,27 @@ class Connector_Woocommerce extends Connector {
290
  *
291
  * @action transition_post_status
292
  *
293
- * @param string $new
294
- * @param string $old
295
- * @param \WP_Post $post
296
  */
297
  public function callback_transition_post_status( $new, $old, $post ) {
298
- // Only track orders
299
  if ( 'shop_order' !== $post->post_type ) {
300
  return;
301
  }
302
 
303
- // Don't track customer actions
304
  if ( ! is_admin() ) {
305
  return;
306
  }
307
 
308
- // Don't track minor status change actions
309
  if ( in_array( wp_stream_filter_input( INPUT_GET, 'action' ), array( 'mark_processing', 'mark_on-hold', 'mark_completed' ), true ) || defined( 'DOING_AJAX' ) ) {
310
  return;
311
  }
312
 
313
- // Don't log updates when more than one happens at the same time
314
  if ( $post->ID === $this->order_update_logged ) {
315
  return;
316
  }
@@ -318,7 +360,7 @@ class Connector_Woocommerce extends Connector {
318
  if ( in_array( $new, array( 'auto-draft', 'draft', 'inherit' ), true ) ) {
319
  return;
320
  } elseif ( 'auto-draft' === $old && 'publish' === $new ) {
321
- // translators: Placeholder refers to an order title (e.g. "Order #42")
322
  $message = esc_html_x(
323
  '%s created',
324
  'Order title',
@@ -326,7 +368,7 @@ class Connector_Woocommerce extends Connector {
326
  );
327
  $action = 'created';
328
  } elseif ( 'trash' === $new ) {
329
- // translators: Placeholder refers to an order title (e.g. "Order #42")
330
  $message = esc_html_x(
331
  '%s trashed',
332
  'Order title',
@@ -334,7 +376,7 @@ class Connector_Woocommerce extends Connector {
334
  );
335
  $action = 'trashed';
336
  } elseif ( 'trash' === $old && 'publish' === $new ) {
337
- // translators: Placeholder refers to an order title (e.g. "Order #42")
338
  $message = esc_html_x(
339
  '%s restored from the trash',
340
  'Order title',
@@ -342,7 +384,7 @@ class Connector_Woocommerce extends Connector {
342
  );
343
  $action = 'untrashed';
344
  } else {
345
- // translators: Placeholder refers to an order title (e.g. "Order #42")
346
  $message = esc_html_x(
347
  '%s updated',
348
  'Order title',
@@ -380,17 +422,17 @@ class Connector_Woocommerce extends Connector {
380
  *
381
  * @action deleted_post
382
  *
383
- * @param int $post_id
384
  */
385
  public function callback_deleted_post( $post_id ) {
386
  $post = get_post( $post_id );
387
 
388
- // We check if post is an instance of WP_Post as it doesn't always resolve in unit testing
389
  if ( ! ( $post instanceof \WP_Post ) || 'shop_order' !== $post->post_type ) {
390
  return;
391
  }
392
 
393
- // Ignore auto-drafts that are deleted by the system, see issue-293
394
  if ( 'auto-draft' === $post->post_status ) {
395
  return;
396
  }
@@ -400,7 +442,7 @@ class Connector_Woocommerce extends Connector {
400
  $order_type_name = esc_html__( 'order', 'stream' );
401
 
402
  $this->log(
403
- // translators: Placeholder refers to an order title (e.g. "Order #42")
404
  _x(
405
  '"%s" deleted from trash',
406
  'Order title',
@@ -421,17 +463,17 @@ class Connector_Woocommerce extends Connector {
421
  *
422
  * @action woocommerce_order_status_changed
423
  *
424
- * @param int $order_id
425
- * @param string $old
426
- * @param string $new
427
  */
428
  public function callback_woocommerce_order_status_changed( $order_id, $old, $new ) {
429
- // Don't track customer actions
430
  if ( ! is_admin() ) {
431
  return;
432
  }
433
 
434
- // Don't track new statuses
435
  if ( empty( $old ) ) {
436
  return;
437
  }
@@ -446,7 +488,7 @@ class Connector_Woocommerce extends Connector {
446
  $old_status_name = $old_status->name;
447
  }
448
 
449
- // translators: Placeholders refer to an order title, and order status, and another order status (e.g. "Order #42", "processing", "complete")
450
  $message = esc_html_x(
451
  '%1$s status changed from %2$s to %3$s',
452
  '1. Order title, 2. Old status, 3. New status',
@@ -479,12 +521,12 @@ class Connector_Woocommerce extends Connector {
479
  *
480
  * @action woocommerce_attribute_added
481
  *
482
- * @param int $attribute_id
483
- * @param array $attribute
484
  */
485
  public function callback_woocommerce_attribute_added( $attribute_id, $attribute ) {
486
  $this->log(
487
- // translators: Placeholder refers to a term name (e.g. "color")
488
  _x(
489
  '"%s" product attribute created',
490
  'Term name',
@@ -502,12 +544,12 @@ class Connector_Woocommerce extends Connector {
502
  *
503
  * @action woocommerce_attribute_updated
504
  *
505
- * @param int $attribute_id
506
- * @param array $attribute
507
  */
508
  public function callback_woocommerce_attribute_updated( $attribute_id, $attribute ) {
509
  $this->log(
510
- // translators: Placeholder refers to a term name (e.g. "color")
511
  _x(
512
  '"%s" product attribute updated',
513
  'Term name',
@@ -525,12 +567,12 @@ class Connector_Woocommerce extends Connector {
525
  *
526
  * @action woocommerce_attribute_updated
527
  *
528
- * @param int $attribute_id
529
- * @param string $attribute_name
530
  */
531
  public function callback_woocommerce_attribute_deleted( $attribute_id, $attribute_name ) {
532
  $this->log(
533
- // translators: Placeholder refers to a term name (e.g. "color")
534
  _x(
535
  '"%s" product attribute deleted',
536
  'Term name',
@@ -550,12 +592,12 @@ class Connector_Woocommerce extends Connector {
550
  *
551
  * @action woocommerce_tax_rate_added
552
  *
553
- * @param int $tax_rate_id
554
- * @param array $tax_rate
555
  */
556
  public function callback_woocommerce_tax_rate_added( $tax_rate_id, $tax_rate ) {
557
  $this->log(
558
- // translators: Placeholder refers to a tax rate name (e.g. "GST")
559
  _x(
560
  '"%4$s" tax rate created',
561
  'Tax rate name',
@@ -573,12 +615,12 @@ class Connector_Woocommerce extends Connector {
573
  *
574
  * @action woocommerce_tax_rate_updated
575
  *
576
- * @param int $tax_rate_id
577
- * @param array $tax_rate
578
  */
579
  public function callback_woocommerce_tax_rate_updated( $tax_rate_id, $tax_rate ) {
580
  $this->log(
581
- // translators: Placeholder refers to a tax rate name (e.g. "GST")
582
  _x(
583
  '"%4$s" tax rate updated',
584
  'Tax rate name',
@@ -596,7 +638,7 @@ class Connector_Woocommerce extends Connector {
596
  *
597
  * @action woocommerce_tax_rate_updated
598
  *
599
- * @param int $tax_rate_id
600
  */
601
  public function callback_woocommerce_tax_rate_deleted( $tax_rate_id ) {
602
  global $wpdb;
@@ -611,7 +653,7 @@ class Connector_Woocommerce extends Connector {
611
  );
612
 
613
  $this->log(
614
- // translators: Placeholder refers to a tax rate name (e.g. "GST")
615
  _x(
616
  '"%s" tax rate deleted',
617
  'Tax rate name',
@@ -631,7 +673,7 @@ class Connector_Woocommerce extends Connector {
631
  *
632
  * @filter wp_stream_record_array
633
  *
634
- * @param array $recordarr Record data to be inserted
635
  *
636
  * @return array Filtered record data
637
  */
@@ -641,7 +683,7 @@ class Connector_Woocommerce extends Connector {
641
  continue;
642
  }
643
 
644
- // Change connector::posts records
645
  if ( 'posts' === $record['connector'] && in_array( $record['context'], $this->post_types, true ) ) {
646
  $recordarr[ $key ]['connector'] = $this->name;
647
  } elseif ( 'taxonomies' === $record['connector'] && in_array( $record['context'], $this->taxonomies, true ) ) {
@@ -658,6 +700,13 @@ class Connector_Woocommerce extends Connector {
658
  return $recordarr;
659
  }
660
 
 
 
 
 
 
 
 
661
  public function callback_updated_option( $option_key, $old_value, $value ) {
662
  $options = array( $option_key );
663
 
@@ -673,7 +722,7 @@ class Connector_Woocommerce extends Connector {
673
  }
674
 
675
  $this->log(
676
- // translators: Placeholders refer to a setting name and a setting type (e.g. "Direct Deposit", "Payment Method")
677
  __( '"%1$s" %2$s updated', 'stream' ),
678
  array(
679
  'label' => $this->settings[ $option ]['title'],
@@ -692,6 +741,9 @@ class Connector_Woocommerce extends Connector {
692
  }
693
  }
694
 
 
 
 
695
  public function get_woocommerce_settings_fields() {
696
  if ( ! defined( 'WC_VERSION' ) || ! class_exists( 'WC_Admin_Settings' ) ) {
697
  return false;
@@ -714,8 +766,10 @@ class Connector_Woocommerce extends Connector {
714
  $settings_pages = array();
715
 
716
  foreach ( \WC_Admin_Settings::get_settings_pages() as $page ) {
717
- // Get ID / Label of the page, since they're protected, by hacking into
718
- // the callback filter for 'woocommerce_settings_tabs_array'
 
 
719
  $info = $page->add_settings_page( array() );
720
  $page_id = key( $info );
721
  $page_label = current( $info );
@@ -727,7 +781,7 @@ class Connector_Woocommerce extends Connector {
727
 
728
  $settings_pages[ $page_id ] = $page_label;
729
 
730
- // Remove non-fields ( sections, titles and whatever )
731
  $fields = array();
732
 
733
  foreach ( $sections as $section_key => $section_label ) {
@@ -750,11 +804,11 @@ class Connector_Woocommerce extends Connector {
750
  }
751
  }
752
 
753
- // Store fields in the global array to be searched later
754
  $settings = array_merge( $settings, $fields );
755
  }
756
 
757
- // Provide additional context for each of the settings pages
758
  array_walk(
759
  $settings_pages,
760
  function( &$value ) {
@@ -762,7 +816,7 @@ class Connector_Woocommerce extends Connector {
762
  }
763
  );
764
 
765
- // Load Payment Gateway Settings
766
  $payment_gateway_settings = array();
767
  $payment_gateways = $woocommerce->payment_gateways();
768
 
@@ -781,7 +835,7 @@ class Connector_Woocommerce extends Connector {
781
 
782
  $settings = array_merge( $settings, $payment_gateway_settings );
783
 
784
- // Load Shipping Method Settings
785
  $shipping_method_settings = array();
786
  $shipping_methods = $woocommerce->shipping();
787
 
@@ -800,7 +854,7 @@ class Connector_Woocommerce extends Connector {
800
 
801
  $settings = array_merge( $settings, $shipping_method_settings );
802
 
803
- // Load Email Settings
804
  $email_settings = array();
805
  $emails = $woocommerce->mailer();
806
 
@@ -819,14 +873,14 @@ class Connector_Woocommerce extends Connector {
819
 
820
  $settings = array_merge( $settings, $email_settings );
821
 
822
- // Tools page
823
  $tools_page = array(
824
  'tools' => esc_html__( 'Tools', 'stream' ),
825
  );
826
 
827
  $settings_pages = array_merge( $settings_pages, $tools_page );
828
 
829
- // Cache the results
830
  $settings_cache = array(
831
  'settings' => $settings,
832
  'settings_pages' => $settings_pages,
1
  <?php
2
+ /**
3
+ * Connector for WooCommerce
4
+ *
5
+ * @package WP_Stream
6
+ */
7
+
8
  namespace WP_Stream;
9
 
10
+ /**
11
+ * Class - Connector_WooCommerce
12
+ */
13
  class Connector_Woocommerce extends Connector {
14
  /**
15
  * Context name
44
  'woocommerce_tax_rate_deleted',
45
  );
46
 
47
+ /**
48
+ * Taxonomies tracked by this connector.
49
+ *
50
+ * @var array
51
+ */
52
  public $taxonomies = array(
53
  'product_type',
54
  'product_cat',
57
  'shop_order_status',
58
  );
59
 
60
+ /**
61
+ * Post-types tracked by this connector.
62
+ *
63
+ * @var array
64
+ */
65
  public $post_types = array(
66
  'product',
67
  'product_variation',
69
  'shop_coupon',
70
  );
71
 
72
+ /**
73
+ * Is the most recently update order logged yet.
74
+ *
75
+ * @var boolean
76
+ */
77
  private $order_update_logged = false;
78
 
79
+ /**
80
+ * Caches WooCommerce settings page objects.
81
+ *
82
+ * @var array
83
+ */
84
  private $settings_pages = array();
85
 
86
+ /**
87
+ * Caches WooCommerce settings.
88
+ *
89
+ * @var array
90
+ */
91
  private $settings = array();
92
 
93
+ /**
94
+ * Stores the WooCommerce version number.
95
+ *
96
+ * @var string|null
97
+ */
98
  private $plugin_version = null;
99
 
100
+ /**
101
+ * Register connection
102
+ */
103
  public function register() {
104
  parent::register();
105
 
250
  *
251
  * @filter wp_stream_action_links_{connector}
252
  *
253
+ * @param array $links Previous links registered.
254
+ * @param Record $record Stream record.
255
  *
256
  * @return array Action links
257
  */
261
  if ( $edit_post_link ) {
262
  $posts_connector = new Connector_Posts();
263
  $post_type_name = $posts_connector->get_post_type_name( get_post_type( $record->object_id ) );
264
+ /* translators: %s: a post type singular name (e.g. "Post") */
265
  $links[ sprintf( esc_html_x( 'Edit %s', 'Post type singular name', 'stream' ), $post_type_name ) ] = $edit_post_link;
266
  }
267
 
278
  $option_section = $record->get_meta( 'section', true );
279
 
280
  if ( $option_key && $option_tab ) {
281
+ /* translators: %s a context (e.g. "Attribute") */
282
  $text = sprintf( esc_html__( 'Edit WooCommerce %s', 'stream' ), $context_labels[ $record->context ] );
283
  $url = add_query_arg(
284
  array(
286
  'tab' => $option_tab,
287
  'section' => $option_section,
288
  ),
289
+ admin_url( 'admin.php' ) // Not self_admin_url here, as WooCommerce doesn't exist in Network Admin.
290
  );
291
 
292
  $links[ $text ] = $url . '#wp-stream-highlight:' . $option_key;
301
  *
302
  * @filter wp_stream_posts_exclude_post_types
303
  *
304
+ * @param array $post_types Ignored post types.
305
  *
306
  * @return array Filtered post types
307
  */
317
  *
318
  * @filter wp_stream_commnent_exclude_comment_types
319
  *
320
+ * @param array $comment_types Ignored post types.
321
  *
322
  * @return array Filtered post types
323
  */
332
  *
333
  * @action transition_post_status
334
  *
335
+ * @param string $new New status.
336
+ * @param string $old Old status.
337
+ * @param \WP_Post $post Post object.
338
  */
339
  public function callback_transition_post_status( $new, $old, $post ) {
340
+ // Only track orders.
341
  if ( 'shop_order' !== $post->post_type ) {
342
  return;
343
  }
344
 
345
+ // Don't track customer actions.
346
  if ( ! is_admin() ) {
347
  return;
348
  }
349
 
350
+ // Don't track minor status change actions.
351
  if ( in_array( wp_stream_filter_input( INPUT_GET, 'action' ), array( 'mark_processing', 'mark_on-hold', 'mark_completed' ), true ) || defined( 'DOING_AJAX' ) ) {
352
  return;
353
  }
354
 
355
+ // Don't log updates when more than one happens at the same time.
356
  if ( $post->ID === $this->order_update_logged ) {
357
  return;
358
  }
360
  if ( in_array( $new, array( 'auto-draft', 'draft', 'inherit' ), true ) ) {
361
  return;
362
  } elseif ( 'auto-draft' === $old && 'publish' === $new ) {
363
+ /* translators: %s: an order title (e.g. "Order #42") */
364
  $message = esc_html_x(
365
  '%s created',
366
  'Order title',
368
  );
369
  $action = 'created';
370
  } elseif ( 'trash' === $new ) {
371
+ /* translators: %s: an order title (e.g. "Order #42") */
372
  $message = esc_html_x(
373
  '%s trashed',
374
  'Order title',
376
  );
377
  $action = 'trashed';
378
  } elseif ( 'trash' === $old && 'publish' === $new ) {
379
+ /* translators: %s: an order title (e.g. "Order #42") */
380
  $message = esc_html_x(
381
  '%s restored from the trash',
382
  'Order title',
384
  );
385
  $action = 'untrashed';
386
  } else {
387
+ /* translators: %s: an order title (e.g. "Order #42") */
388
  $message = esc_html_x(
389
  '%s updated',
390
  'Order title',
422
  *
423
  * @action deleted_post
424
  *
425
+ * @param int $post_id Post ID.
426
  */
427
  public function callback_deleted_post( $post_id ) {
428
  $post = get_post( $post_id );
429
 
430
+ // We check if post is an instance of WP_Post as it doesn't always resolve in unit testing.
431
  if ( ! ( $post instanceof \WP_Post ) || 'shop_order' !== $post->post_type ) {
432
  return;
433
  }
434
 
435
+ // Ignore auto-drafts that are deleted by the system, see issue-293.
436
  if ( 'auto-draft' === $post->post_status ) {
437
  return;
438
  }
442
  $order_type_name = esc_html__( 'order', 'stream' );
443
 
444
  $this->log(
445
+ /* translators: %s: an order title (e.g. "Order #42") */
446
  _x(
447
  '"%s" deleted from trash',
448
  'Order title',
463
  *
464
  * @action woocommerce_order_status_changed
465
  *
466
+ * @param int $order_id Order ID.
467
+ * @param string $old Old status.
468
+ * @param string $new New status.
469
  */
470
  public function callback_woocommerce_order_status_changed( $order_id, $old, $new ) {
471
+ // Don't track customer actions.
472
  if ( ! is_admin() ) {
473
  return;
474
  }
475
 
476
+ // Don't track new statuses.
477
  if ( empty( $old ) ) {
478
  return;
479
  }
488
  $old_status_name = $old_status->name;
489
  }
490
 
491
+ /* translators: %1$s: an order title, %2$s: order status, %3$s: another order status (e.g. "Order #42", "processing", "complete") */
492
  $message = esc_html_x(
493
  '%1$s status changed from %2$s to %3$s',
494
  '1. Order title, 2. Old status, 3. New status',
521
  *
522
  * @action woocommerce_attribute_added
523
  *
524
+ * @param int $attribute_id Attribute ID.
525
+ * @param array $attribute Attribute data.
526
  */
527
  public function callback_woocommerce_attribute_added( $attribute_id, $attribute ) {
528
  $this->log(
529
+ /* translators: %s: a term name (e.g. "color") */
530
  _x(
531
  '"%s" product attribute created',
532
  'Term name',
544
  *
545
  * @action woocommerce_attribute_updated
546
  *
547
+ * @param int $attribute_id Attribute ID.
548
+ * @param array $attribute Attribute data.
549
  */
550
  public function callback_woocommerce_attribute_updated( $attribute_id, $attribute ) {
551
  $this->log(
552
+ /* translators: %s a term name (e.g. "color") */
553
  _x(
554
  '"%s" product attribute updated',
555
  'Term name',
567
  *
568
  * @action woocommerce_attribute_updated
569
  *
570
+ * @param int $attribute_id Attribute ID.
571
+ * @param string $attribute_name Attribute name.
572
  */
573
  public function callback_woocommerce_attribute_deleted( $attribute_id, $attribute_name ) {
574
  $this->log(
575
+ /* translators: %s: a term name (e.g. "color") */
576
  _x(
577
  '"%s" product attribute deleted',
578
  'Term name',
592
  *
593
  * @action woocommerce_tax_rate_added
594
  *
595
+ * @param int $tax_rate_id Tax Rate ID.
596
+ * @param array $tax_rate Tax Rate data.
597
  */
598
  public function callback_woocommerce_tax_rate_added( $tax_rate_id, $tax_rate ) {
599
  $this->log(
600
+ /* translators: %4$s: a tax rate name (e.g. "GST") */
601
  _x(
602
  '"%4$s" tax rate created',
603
  'Tax rate name',
615
  *
616
  * @action woocommerce_tax_rate_updated
617
  *
618
+ * @param int $tax_rate_id Tax Rate ID.
619
+ * @param array $tax_rate Tax Rate data.
620
  */
621
  public function callback_woocommerce_tax_rate_updated( $tax_rate_id, $tax_rate ) {
622
  $this->log(
623
+ /* translators: %4$s: a tax rate name (e.g. "GST") */
624
  _x(
625
  '"%4$s" tax rate updated',
626
  'Tax rate name',
638
  *
639
  * @action woocommerce_tax_rate_updated
640
  *
641
+ * @param int $tax_rate_id Tax Rate ID.
642
  */
643
  public function callback_woocommerce_tax_rate_deleted( $tax_rate_id ) {
644
  global $wpdb;
653
  );
654
 
655
  $this->log(
656
+ /* translators: %4$s: a tax rate name (e.g. "GST") */
657
  _x(
658
  '"%s" tax rate deleted',
659
  'Tax rate name',
673
  *
674
  * @filter wp_stream_record_array
675
  *
676
+ * @param array $recordarr Record data to be inserted.
677
  *
678
  * @return array Filtered record data
679
  */
683
  continue;
684
  }
685
 
686
+ // Change connector::posts records.
687
  if ( 'posts' === $record['connector'] && in_array( $record['context'], $this->post_types, true ) ) {
688
  $recordarr[ $key ]['connector'] = $this->name;
689
  } elseif ( 'taxonomies' === $record['connector'] && in_array( $record['context'], $this->taxonomies, true ) ) {
700
  return $recordarr;
701
  }
702
 
703
+ /**
704
+ * Track WooCommerce-specific option changes.
705
+ *
706
+ * @param string $option_key Option key.
707
+ * @param string $old_value Old value.
708
+ * @param string $value New value.
709
+ */
710
  public function callback_updated_option( $option_key, $old_value, $value ) {
711
  $options = array( $option_key );
712
 
722
  }
723
 
724
  $this->log(
725
+ /* translators: %1$s: a setting name, %2$s: a setting type (e.g. "Direct Deposit", "Payment Method") */
726
  __( '"%1$s" %2$s updated', 'stream' ),
727
  array(
728
  'label' => $this->settings[ $option ]['title'],
741
  }
742
  }
743
 
744
+ /**
745
+ * Loads the WooCommerce admin settings.
746
+ */
747
  public function get_woocommerce_settings_fields() {
748
  if ( ! defined( 'WC_VERSION' ) || ! class_exists( 'WC_Admin_Settings' ) ) {
749
  return false;
766
  $settings_pages = array();
767
 
768
  foreach ( \WC_Admin_Settings::get_settings_pages() as $page ) {
769
+ /**
770
+ * Get ID / Label of the page, since they're protected, by hacking into
771
+ * the callback filter for 'woocommerce_settings_tabs_array'.
772
+ */
773
  $info = $page->add_settings_page( array() );
774
  $page_id = key( $info );
775
  $page_label = current( $info );
781
 
782
  $settings_pages[ $page_id ] = $page_label;
783
 
784
+ // Remove non-fields ( sections, titles and whatever ).
785
  $fields = array();
786
 
787
  foreach ( $sections as $section_key => $section_label ) {
804
  }
805
  }
806
 
807
+ // Store fields in the global array to be searched later.
808
  $settings = array_merge( $settings, $fields );
809
  }
810
 
811
+ // Provide additional context for each of the settings pages.
812
  array_walk(
813
  $settings_pages,
814
  function( &$value ) {
816
  }
817
  );
818
 
819
+ // Load Payment Gateway Settings.
820
  $payment_gateway_settings = array();
821
  $payment_gateways = $woocommerce->payment_gateways();
822
 
835
 
836
  $settings = array_merge( $settings, $payment_gateway_settings );
837
 
838
+ // Load Shipping Method Settings.
839
  $shipping_method_settings = array();
840
  $shipping_methods = $woocommerce->shipping();
841
 
854
 
855
  $settings = array_merge( $settings, $shipping_method_settings );
856
 
857
+ // Load Email Settings.
858
  $email_settings = array();
859
  $emails = $woocommerce->mailer();
860
 
873
 
874
  $settings = array_merge( $settings, $email_settings );
875
 
876
+ // Tools page.
877
  $tools_page = array(
878
  'tools' => esc_html__( 'Tools', 'stream' ),
879
  );
880
 
881
  $settings_pages = array_merge( $settings_pages, $tools_page );
882
 
883
+ // Cache the results.
884
  $settings_cache = array(
885
  'settings' => $settings,
886
  'settings_pages' => $settings_pages,
connectors/class-connector-wordpress-seo.php CHANGED
@@ -1,6 +1,15 @@
1
  <?php
 
 
 
 
 
 
2
  namespace WP_Stream;
3
 
 
 
 
4
  class Connector_WordPress_SEO extends Connector {
5
 
6
  /**
@@ -104,13 +113,13 @@ class Connector_WordPress_SEO extends Connector {
104
  *
105
  * @filter wp_stream_action_links_{connector}
106
  *
107
- * @param array $links Previous links registered
108
- * @param Record $record Stream record
109
  *
110
  * @return array Action links
111
  */
112
  public function action_links( $links, $record ) {
113
- // Options
114
  $option = $record->get_meta( 'option', true );
115
  if ( $option ) {
116
  $key = $record->get_meta( 'option_key', true );
@@ -158,12 +167,12 @@ class Connector_WordPress_SEO extends Connector {
158
  sprintf( 'delete-post_%d', $post->ID )
159
  );
160
 
161
- // translators: Placeholder refers to a post type singular name (e.g. "Post")
162
  $links[ sprintf( esc_html_x( 'Restore %s', 'Post type singular name', 'stream' ), $post_type_name ) ] = $untrash;
163
- // translators: Placeholder refers to a post type singular name (e.g. "Post")
164
  $links[ sprintf( esc_html_x( 'Delete %s Permenantly', 'Post type singular name', 'stream' ), $post_type_name ) ] = $delete;
165
  } else {
166
- // translators: Placeholder refers to a post type singular name (e.g. "Post")
167
  $links[ sprintf( esc_html_x( 'Edit %s', 'Post type singular name', 'stream' ), $post_type_name ) ] = get_edit_post_link( $post->ID );
168
 
169
  $view_link = get_permalink( $post->ID );
@@ -182,6 +191,9 @@ class Connector_WordPress_SEO extends Connector {
182
  return $links;
183
  }
184
 
 
 
 
185
  public function register() {
186
  if ( is_network_admin() && ! is_plugin_active_for_network( 'wordpress-seo/wordpress-seo-main.php' ) ) {
187
  return;
@@ -189,7 +201,11 @@ class Connector_WordPress_SEO extends Connector {
189
  parent::register();
190
 
191
  foreach ( \WPSEO_Options::$options as $class ) {
192
- /* @var $class WPSEO_Options */
 
 
 
 
193
  $this->option_groups[ $class::get_instance()->group_name ] = array(
194
  'class' => $class,
195
  'name' => $class::get_instance()->option_name,
@@ -200,26 +216,39 @@ class Connector_WordPress_SEO extends Connector {
200
  add_filter( 'wp_stream_log_data', array( $this, 'log_override' ) );
201
  }
202
 
 
 
 
 
 
203
  public function admin_enqueue_scripts( $hook ) {
204
  if ( 0 === strpos( $hook, 'seo_page_' ) ) {
205
  $stream = wp_stream_get_instance();
206
  $src = $stream->locations['url'] . '/ui/js/wpseo-admin.js';
207
- wp_enqueue_script( 'stream-connector-wpseo', $src, array( 'jquery' ), $stream->get_version() );
 
 
 
 
 
 
208
  }
209
  }
210
 
211
  /**
212
  * Track importing settings from other plugins
 
 
213
  */
214
  public function callback_wpseo_handle_import() {
215
  $imports = array(
216
- 'importheadspace' => esc_html__( 'HeadSpace2', 'stream' ), // type = checkbox
217
- 'importaioseo' => esc_html__( 'All-in-One SEO', 'stream' ), // type = checkbox
218
- 'importaioseoold' => esc_html__( 'OLD All-in-One SEO', 'stream' ), // type = checkbox
219
- 'importwoo' => esc_html__( 'WooThemes SEO framework', 'stream' ), // type = checkbox
220
- 'importrobotsmeta' => esc_html__( 'Robots Meta (by Yoast)', 'stream' ), // type = checkbox
221
- 'importrssfooter' => esc_html__( 'RSS Footer (by Yoast)', 'stream' ), // type = checkbox
222
- 'importbreadcrumbs' => esc_html__( 'Yoast Breadcrumbs', 'stream' ), // type = checkbox
223
  );
224
 
225
  $opts = wp_stream_filter_input( INPUT_POST, 'wpseo' );
@@ -228,7 +257,7 @@ class Connector_WordPress_SEO extends Connector {
228
  if ( isset( $opts[ $key ] ) ) {
229
  $this->log(
230
  sprintf(
231
- // translators: Placeholders refer to an import method, and an extra string (sometimes blank) (e.g. "HeadSpace2", ", and deleted old data")
232
  __( 'Imported settings from %1$s%2$s', 'stream' ),
233
  $name,
234
  isset( $opts['deleteolddata'] ) ? esc_html__( ', and deleted old data', 'stream' ) : ''
@@ -245,13 +274,18 @@ class Connector_WordPress_SEO extends Connector {
245
  }
246
  }
247
 
 
 
 
 
 
248
  public function callback_wpseo_import() {
249
  $opts = wp_stream_filter_input( INPUT_POST, 'wpseo' );
250
 
251
  if ( wp_stream_filter_input( INPUT_POST, 'wpseo_export' ) ) {
252
  $this->log(
253
  sprintf(
254
- // translators: Placeholder refers to an extra string (sometimes blank) (e.g. ", including taxonomy meta")
255
  __( 'Exported settings%s', 'stream' ),
256
  isset( $opts['include_taxonomy_meta'] ) ? esc_html__( ', including taxonomy meta', 'stream' ) : ''
257
  ),
@@ -262,15 +296,15 @@ class Connector_WordPress_SEO extends Connector {
262
  'wpseo_import',
263
  'exported'
264
  );
265
- } elseif ( isset( $_FILES['settings_import_file']['name'] ) ) { // phpcs: input var okay
266
  $this->log(
267
  sprintf(
268
- // translators: Placeholder refers to a filename (e.g. "test.xml")
269
  __( 'Tried importing settings from "%s"', 'stream' ),
270
- sanitize_text_field( wp_unslash( $_FILES['settings_import_file']['name'] ) ) // phpcs: input var okay
271
  ),
272
  array(
273
- 'file' => sanitize_text_field( wp_unslash( $_FILES['settings_import_file']['name'] ) ), // phpcs: input var okay
274
  ),
275
  null,
276
  'wpseo_import',
@@ -279,6 +313,11 @@ class Connector_WordPress_SEO extends Connector {
279
  }
280
  }
281
 
 
 
 
 
 
282
  public function callback_seo_page_wpseo_files() {
283
  if ( wp_stream_filter_input( INPUT_POST, 'create_robots' ) ) {
284
  $message = esc_html__( 'Tried creating robots.txt file', 'stream' );
@@ -299,19 +338,58 @@ class Connector_WordPress_SEO extends Connector {
299
  }
300
  }
301
 
 
 
 
 
 
 
 
 
 
 
302
  public function callback_added_post_meta( $meta_id, $object_id, $meta_key, $meta_value ) {
303
  unset( $meta_id );
304
  $this->meta( $object_id, $meta_key, $meta_value );
305
  }
 
 
 
 
 
 
 
 
 
 
 
306
  public function callback_updated_post_meta( $meta_id, $object_id, $meta_key, $meta_value ) {
307
  unset( $meta_id );
308
  $this->meta( $object_id, $meta_key, $meta_value );
309
  }
 
 
 
 
 
 
 
 
 
 
 
310
  public function callback_deleted_post_meta( $meta_id, $object_id, $meta_key, $meta_value ) {
311
  unset( $meta_id );
312
  $this->meta( $object_id, $meta_key, $meta_value );
313
  }
314
 
 
 
 
 
 
 
 
315
  private function meta( $object_id, $meta_key, $meta_value ) {
316
  $prefix = \WPSEO_Meta::$meta_prefix;
317
 
@@ -339,7 +417,7 @@ class Connector_WordPress_SEO extends Connector {
339
 
340
  $this->log(
341
  sprintf(
342
- // translators: Placeholders refer to a meta field title, a post title, and a post type (e.g. "Description", "Hello World", "Post")
343
  __( 'Updated "%1$s" of "%2$s" %3$s', 'stream' ),
344
  $field['title'],
345
  $post->post_title,
@@ -359,7 +437,7 @@ class Connector_WordPress_SEO extends Connector {
359
  /**
360
  * Override connector log for our own Settings / Actions
361
  *
362
- * @param array $data
363
  *
364
  * @return array|bool
365
  */
@@ -384,7 +462,7 @@ class Connector_WordPress_SEO extends Connector {
384
 
385
  $label = $this->settings_labels( $data['args']['option_key'] );
386
  if ( ! $label ) {
387
- // translators: Placeholder refers to a context (e.g. "Dashboard")
388
  $data['message'] = esc_html__( '%s settings updated', 'stream' );
389
  $label = $labels[ $page ];
390
  }
@@ -398,114 +476,121 @@ class Connector_WordPress_SEO extends Connector {
398
  return $data;
399
  }
400
 
 
 
 
 
 
 
 
401
  private function settings_labels( $option ) {
402
  $labels = array(
403
- // wp-content/plugins/wordpress-seo/admin/pages/dashboard.php:
404
- 'yoast_tracking' => esc_html_x( "Allow tracking of this WordPress install's anonymous data.", 'wordpress-seo', 'stream' ), // type = checkbox
405
- 'disableadvanced_meta' => esc_html_x( 'Disable the Advanced part of the WordPress SEO meta box', 'wordpress-seo', 'stream' ), // type = checkbox
406
- 'alexaverify' => esc_html_x( 'Alexa Verification ID', 'wordpress-seo', 'stream' ), // type = textinput
407
- 'msverify' => esc_html_x( 'Bing Webmaster Tools', 'wordpress-seo', 'stream' ), // type = textinput
408
- 'googleverify' => esc_html_x( 'Google Webmaster Tools', 'wordpress-seo', 'stream' ), // type = textinput
409
- 'pinterestverify' => esc_html_x( 'Pinterest', 'wordpress-seo', 'stream' ), // type = textinput
410
- 'yandexverify' => esc_html_x( 'Yandex Webmaster Tools', 'wordpress-seo', 'stream' ), // type = textinput
411
-
412
- // wp-content/plugins/wordpress-seo/admin/pages/advanced.php:
413
- 'breadcrumbs-enable' => esc_html_x( 'Enable Breadcrumbs', 'wordpress-seo', 'stream' ), // type = checkbox
414
- 'breadcrumbs-sep' => esc_html_x( 'Separator between breadcrumbs', 'wordpress-seo', 'stream' ), // type = textinput
415
- 'breadcrumbs-home' => esc_html_x( 'Anchor text for the Homepage', 'wordpress-seo', 'stream' ), // type = textinput
416
- 'breadcrumbs-prefix' => esc_html_x( 'Prefix for the breadcrumb path', 'wordpress-seo', 'stream' ), // type = textinput
417
- 'breadcrumbs-archiveprefix' => esc_html_x( 'Prefix for Archive breadcrumbs', 'wordpress-seo', 'stream' ), // type = textinput
418
- 'breadcrumbs-searchprefix' => esc_html_x( 'Prefix for Search Page breadcrumbs', 'wordpress-seo', 'stream' ), // type = textinput
419
- 'breadcrumbs-404crumb' => esc_html_x( 'Breadcrumb for 404 Page', 'wordpress-seo', 'stream' ), // type = textinput
420
- 'breadcrumbs-blog-remove' => esc_html_x( 'Remove Blog page from Breadcrumbs', 'wordpress-seo', 'stream' ), // type = checkbox
421
- 'breadcrumbs-boldlast' => esc_html_x( 'Bold the last page in the breadcrumb', 'wordpress-seo', 'stream' ), // type = checkbox
422
- 'post_types-post-maintax' => esc_html_x( 'Taxonomy to show in breadcrumbs for post types', 'wordpress-seo', 'stream' ), // type = select
423
-
424
- // wp-content/plugins/wordpress-seo/admin/pages/metas.php:
425
- 'forcerewritetitle' => esc_html_x( 'Force rewrite titles', 'wordpress-seo', 'stream' ), // type = checkbox
426
- 'noindex-subpages-wpseo' => esc_html_x( 'Noindex subpages of archives', 'wordpress-seo', 'stream' ), // type = checkbox
427
- 'usemetakeywords' => _x( 'Use <code>meta</code> keywords tag?', 'wordpress-seo', 'stream' ), // type = checkbox
428
- 'noodp' => _x( 'Add <code>noodp</code> meta robots tag sitewide', 'wordpress-seo', 'stream' ), // type = checkbox
429
- 'noydir' => _x( 'Add <code>noydir</code> meta robots tag sitewide', 'wordpress-seo', 'stream' ), // type = checkbox
430
- 'hide-rsdlink' => esc_html_x( 'Hide RSD Links', 'wordpress-seo', 'stream' ), // type = checkbox
431
- 'hide-wlwmanifest' => esc_html_x( 'Hide WLW Manifest Links', 'wordpress-seo', 'stream' ), // type = checkbox
432
- 'hide-shortlink' => esc_html_x( 'Hide Shortlink for posts', 'wordpress-seo', 'stream' ), // type = checkbox
433
- 'hide-feedlinks' => esc_html_x( 'Hide RSS Links', 'wordpress-seo', 'stream' ), // type = checkbox
434
- 'disable-author' => esc_html_x( 'Disable the author archives', 'wordpress-seo', 'stream' ), // type = checkbox
435
- 'disable-date' => esc_html_x( 'Disable the date-based archives', 'wordpress-seo', 'stream' ), // type = checkbox
436
-
437
- // wp-content/plugins/wordpress-seo/admin/pages/network.php:
438
- 'access' => esc_html_x( 'Who should have access to the WordPress SEO settings', 'wordpress-seo', 'stream' ), // type = select
439
- 'defaultblog' => esc_html_x( 'New blogs get the SEO settings from this blog', 'wordpress-seo', 'stream' ), // type = textinput
440
- 'restoreblog' => esc_html_x( 'Blog ID', 'wordpress-seo', 'stream' ), // type = textinput
441
-
442
- // wp-content/plugins/wordpress-seo/admin/pages/permalinks.php:
443
- 'stripcategorybase' => _x( 'Strip the category base (usually <code>/category/</code>) from the category URL.', 'wordpress-seo', 'stream' ), // type = checkbox
444
- 'trailingslash' => esc_html_x( "Enforce a trailing slash on all category and tag URL's", 'wordpress-seo', 'stream' ), // type = checkbox
445
- 'cleanslugs' => esc_html_x( 'Remove stop words from slugs.', 'wordpress-seo', 'stream' ), // type = checkbox
446
- 'redirectattachment' => esc_html_x( "Redirect attachment URL's to parent post URL.", 'wordpress-seo', 'stream' ), // type = checkbox
447
- 'cleanreplytocom' => _x( 'Remove the <code>?replytocom</code> variables.', 'wordpress-seo', 'stream' ), // type = checkbox
448
- 'cleanpermalinks' => esc_html_x( "Redirect ugly URL's to clean permalinks. (Not recommended in many cases!)", 'wordpress-seo', 'stream' ), // type = checkbox
449
- 'force_transport' => esc_html_x( 'Force Transport', 'wordpress-seo', 'stream' ), // type = select
450
- 'cleanpermalink-googlesitesearch' => esc_html_x( "Prevent cleaning out Google Site Search URL's.", 'wordpress-seo', 'stream' ), // type = checkbox
451
- 'cleanpermalink-googlecampaign' => esc_html_x( 'Prevent cleaning out Google Analytics Campaign & Google AdWords Parameters.', 'wordpress-seo', 'stream' ), // type = checkbox
452
- 'cleanpermalink-extravars' => esc_html_x( 'Other variables not to clean', 'wordpress-seo', 'stream' ), // type = textinput
453
-
454
- // wp-content/plugins/wordpress-seo/admin/pages/social.php:
455
- 'opengraph' => esc_html_x( 'Add Open Graph meta data', 'wordpress-seo', 'stream' ), // type = checkbox
456
- 'facebook_site' => esc_html_x( 'Facebook Page URL', 'wordpress-seo', 'stream' ), // type = textinput
457
- 'instagram_url' => esc_html_x( 'Instagram URL', 'wordpress-seo', 'stream' ), // type = textinput
458
- 'linkedin_url' => esc_html_x( 'LinkedIn URL', 'wordpress-seo', 'stream' ), // type = textinput
459
- 'myspace_url' => esc_html_x( 'MySpace URL', 'wordpress-seo', 'stream' ), // type = textinput
460
- 'pinterest_url' => esc_html_x( 'Pinterest URL', 'wordpress-seo', 'stream' ), // type = textinput
461
- 'youtube_url' => esc_html_x( 'YouTube URL', 'wordpress-seo', 'stream' ), // type = textinput
462
- 'google_plus_url' => esc_html_x( 'Google+ URL', 'wordpress-seo', 'stream' ), // type = textinput
463
- 'og_frontpage_image' => esc_html_x( 'Image URL', 'wordpress-seo', 'stream' ), // type = textinput
464
- 'og_frontpage_desc' => esc_html_x( 'Description', 'wordpress-seo', 'stream' ), // type = textinput
465
- 'og_frontpage_title' => esc_html_x( 'Title', 'wordpress-seo', 'stream' ), // type = textinput
466
- 'og_default_image' => esc_html_x( 'Image URL', 'wordpress-seo', 'stream' ), // type = textinput
467
- 'twitter' => esc_html_x( 'Add Twitter card meta data', 'wordpress-seo', 'stream' ), // type = checkbox
468
- 'twitter_site' => esc_html_x( 'Site Twitter Username', 'wordpress-seo', 'stream' ), // type = textinput
469
- 'twitter_card_type' => esc_html_x( 'The default card type to use', 'wordpress-seo', 'stream' ), // type = select
470
- 'googleplus' => esc_html_x( 'Add Google+ specific post meta data (excluding author metadata)', 'wordpress-seo', 'stream' ), // type = checkbox
471
- 'plus-publisher' => esc_html_x( 'Google Publisher Page', 'wordpress-seo', 'stream' ), // type = textinput
472
- 'fbadminapp' => esc_html_x( 'Facebook App ID', 'wordpress-seo', 'stream' ), // type = textinput
473
-
474
- // wp-content/plugins/wordpress-seo/admin/pages/xml-sitemaps.php:
475
- 'enablexmlsitemap' => esc_html_x( 'Check this box to enable XML sitemap functionality.', 'wordpress-seo', 'stream' ), // type = checkbox
476
- 'disable_author_sitemap' => esc_html_x( 'Disable author/user sitemap', 'wordpress-seo', 'stream' ), // type = checkbox
477
- 'disable_author_noposts' => esc_html_x( 'Users with zero posts', 'wordpress-seo', 'stream' ), // type = checkbox
478
- 'user_role-administrator-not_in_sitemap' => esc_html_x( 'Filter specific user roles - Administrator', 'wordpress-seo', 'stream' ), // type = checkbox
479
- 'user_role-editor-not_in_sitemap' => esc_html_x( 'Filter specific user roles - Editor', 'wordpress-seo', 'stream' ), // type = checkbox
480
- 'user_role-author-not_in_sitemap' => esc_html_x( 'Filter specific user roles - Author', 'wordpress-seo', 'stream' ), // type = checkbox
481
- 'user_role-contributor-not_in_sitemap' => esc_html_x( 'Filter specific user roles - Contributor', 'wordpress-seo', 'stream' ), // type = checkbox
482
- 'user_role-subscriber-not_in_sitemap' => esc_html_x( 'Filter specific user roles - Subscriber', 'wordpress-seo', 'stream' ), // type = checkbox
483
- 'xml_ping_yahoo' => esc_html_x( 'Ping Yahoo!', 'wordpress-seo', 'stream' ), // type = checkbox
484
- 'xml_ping_ask' => esc_html_x( 'Ping Ask.com', 'wordpress-seo', 'stream' ), // type = checkbox
485
- 'entries-per-page' => esc_html_x( 'Max entries per sitemap page', 'wordpress-seo', 'stream' ), // type = textinput
486
- 'excluded-posts' => esc_html_x( 'Posts to exclude', 'wordpress-seo', 'stream' ), // type = textinput
487
- 'post_types-post-not_in_sitemap' => _x( 'Post Types Posts (<code>post</code>)', 'wordpress-seo', 'stream' ), // type = checkbox
488
- 'post_types-page-not_in_sitemap' => _x( 'Post Types Pages (<code>page</code>)', 'wordpress-seo', 'stream' ), // type = checkbox
489
- 'post_types-attachment-not_in_sitemap' => _x( 'Post Types Media (<code>attachment</code>)', 'wordpress-seo', 'stream' ), // type = checkbox
490
- 'taxonomies-category-not_in_sitemap' => _x( 'Taxonomies Categories (<code>category</code>)', 'wordpress-seo', 'stream' ), // type = checkbox
491
- 'taxonomies-post_tag-not_in_sitemap' => _x( 'Taxonomies Tags (<code>post_tag</code>)', 'wordpress-seo', 'stream' ), // type = checkbox
492
-
493
- // Added manually
494
  'rssbefore' => esc_html_x( 'Content to put before each post in the feed', 'wordpress-seo', 'stream' ),
495
  'rssafter' => esc_html_x( 'Content to put after each post', 'wordpress-seo', 'stream' ),
496
  );
497
 
498
  $ast_labels = array(
499
- 'title-' => esc_html_x( 'Title template', 'wordpress-seo', 'stream' ), // type = textinput
500
- 'metadesc-' => esc_html_x( 'Meta description template', 'wordpress-seo', 'stream' ), // type = textarea
501
- 'metakey-' => esc_html_x( 'Meta keywords template', 'wordpress-seo', 'stream' ), // type = textinput
502
- 'noindex-' => esc_html_x( 'Meta Robots', 'wordpress-seo', 'stream' ), // type = checkbox
503
- 'noauthorship-' => esc_html_x( 'Authorship', 'wordpress-seo', 'stream' ), // type = checkbox
504
- 'showdate-' => esc_html_x( 'Show date in snippet preview?', 'wordpress-seo', 'stream' ), // type = checkbox
505
- 'hideeditbox-' => esc_html_x( 'WordPress SEO Meta Box', 'wordpress-seo', 'stream' ), // type = checkbox
506
- 'bctitle-' => esc_html_x( 'Breadcrumbs Title', 'wordpress-seo', 'stream' ), // type = textinput
507
- 'post_types-' => esc_html_x( 'Post types', 'wordpress-seo', 'stream' ), // type = checkbox
508
- 'taxonomies-' => esc_html_x( 'Taxonomies', 'wordpress-seo', 'stream' ), // type = checkbox
509
  );
510
 
511
  if ( $option ) {
1
  <?php
2
+ /**
3
+ * Connector for WordPress SEO
4
+ *
5
+ * @package WP_Stream
6
+ */
7
+
8
  namespace WP_Stream;
9
 
10
+ /**
11
+ * Class - Connector_WordPress_SEO
12
+ */
13
  class Connector_WordPress_SEO extends Connector {
14
 
15
  /**
113
  *
114
  * @filter wp_stream_action_links_{connector}
115
  *
116
+ * @param array $links Previous links registered.
117
+ * @param Record $record Stream record.
118
  *
119
  * @return array Action links
120
  */
121
  public function action_links( $links, $record ) {
122
+ // Options.
123
  $option = $record->get_meta( 'option', true );
124
  if ( $option ) {
125
  $key = $record->get_meta( 'option_key', true );
167
  sprintf( 'delete-post_%d', $post->ID )
168
  );
169
 
170
+ /* translators: %s: a post type singular name (e.g. "Post") */
171
  $links[ sprintf( esc_html_x( 'Restore %s', 'Post type singular name', 'stream' ), $post_type_name ) ] = $untrash;
172
+ /* translators: %s: a post type singular name (e.g. "Post") */
173
  $links[ sprintf( esc_html_x( 'Delete %s Permenantly', 'Post type singular name', 'stream' ), $post_type_name ) ] = $delete;
174
  } else {
175
+ /* translators: %s: a post type singular name (e.g. "Post") */
176
  $links[ sprintf( esc_html_x( 'Edit %s', 'Post type singular name', 'stream' ), $post_type_name ) ] = get_edit_post_link( $post->ID );
177
 
178
  $view_link = get_permalink( $post->ID );
191
  return $links;
192
  }
193
 
194
+ /**
195
+ * Register connection
196
+ */
197
  public function register() {
198
  if ( is_network_admin() && ! is_plugin_active_for_network( 'wordpress-seo/wordpress-seo-main.php' ) ) {
199
  return;
201
  parent::register();
202
 
203
  foreach ( \WPSEO_Options::$options as $class ) {
204
+ /**
205
+ * WPSEO Options object.
206
+ *
207
+ * @var WPSEO_Options $class
208
+ */
209
  $this->option_groups[ $class::get_instance()->group_name ] = array(
210
  'class' => $class,
211
  'name' => $class::get_instance()->option_name,
216
  add_filter( 'wp_stream_log_data', array( $this, 'log_override' ) );
217
  }
218
 
219
+ /**
220
+ * Register admin scripts.
221
+ *
222
+ * @param string $hook Current hook.
223
+ */
224
  public function admin_enqueue_scripts( $hook ) {
225
  if ( 0 === strpos( $hook, 'seo_page_' ) ) {
226
  $stream = wp_stream_get_instance();
227
  $src = $stream->locations['url'] . '/ui/js/wpseo-admin.js';
228
+ wp_enqueue_script(
229
+ 'stream-connector-wpseo',
230
+ $src,
231
+ array( 'jquery' ),
232
+ $stream->get_version(),
233
+ false
234
+ );
235
  }
236
  }
237
 
238
  /**
239
  * Track importing settings from other plugins
240
+ *
241
+ * @action wpseo_handle_import
242
  */
243
  public function callback_wpseo_handle_import() {
244
  $imports = array(
245
+ 'importheadspace' => esc_html__( 'HeadSpace2', 'stream' ), // type = checkbox.
246
+ 'importaioseo' => esc_html__( 'All-in-One SEO', 'stream' ), // type = checkbox.
247
+ 'importaioseoold' => esc_html__( 'OLD All-in-One SEO', 'stream' ), // type = checkbox.
248
+ 'importwoo' => esc_html__( 'WooThemes SEO framework', 'stream' ), // type = checkbox.
249
+ 'importrobotsmeta' => esc_html__( 'Robots Meta (by Yoast)', 'stream' ), // type = checkbox.
250
+ 'importrssfooter' => esc_html__( 'RSS Footer (by Yoast)', 'stream' ), // type = checkbox.
251
+ 'importbreadcrumbs' => esc_html__( 'Yoast Breadcrumbs', 'stream' ), // type = checkbox.
252
  );
253
 
254
  $opts = wp_stream_filter_input( INPUT_POST, 'wpseo' );
257
  if ( isset( $opts[ $key ] ) ) {
258
  $this->log(
259
  sprintf(
260
+ /* translators: %1$s: an import method, %2$s: an extra string (sometimes blank) (e.g. "HeadSpace2", ", and deleted old data") */
261
  __( 'Imported settings from %1$s%2$s', 'stream' ),
262
  $name,
263
  isset( $opts['deleteolddata'] ) ? esc_html__( ', and deleted old data', 'stream' ) : ''
274
  }
275
  }
276
 
277
+ /**
278
+ * Track importing settings
279
+ *
280
+ * @callback wpseo_import
281
+ */
282
  public function callback_wpseo_import() {
283
  $opts = wp_stream_filter_input( INPUT_POST, 'wpseo' );
284
 
285
  if ( wp_stream_filter_input( INPUT_POST, 'wpseo_export' ) ) {
286
  $this->log(
287
  sprintf(
288
+ /* translators: %s: an extra string (sometimes blank) (e.g. ", including taxonomy meta") */
289
  __( 'Exported settings%s', 'stream' ),
290
  isset( $opts['include_taxonomy_meta'] ) ? esc_html__( ', including taxonomy meta', 'stream' ) : ''
291
  ),
296
  'wpseo_import',
297
  'exported'
298
  );
299
+ } elseif ( isset( $_FILES['settings_import_file']['name'] ) ) { // phpcs: input var okay.
300
  $this->log(
301
  sprintf(
302
+ /* translators: %s: a filename (e.g. "test.xml") */
303
  __( 'Tried importing settings from "%s"', 'stream' ),
304
+ sanitize_text_field( wp_unslash( $_FILES['settings_import_file']['name'] ) ) // phpcs: input var okay.
305
  ),
306
  array(
307
+ 'file' => sanitize_text_field( wp_unslash( $_FILES['settings_import_file']['name'] ) ), // phpcs: input var okay.
308
  ),
309
  null,
310
  'wpseo_import',
313
  }
314
  }
315
 
316
+ /**
317
+ * Tracks creation of SEO-related files.
318
+ *
319
+ * @action seo_page_wpseo_files
320
+ */
321
  public function callback_seo_page_wpseo_files() {
322
  if ( wp_stream_filter_input( INPUT_POST, 'create_robots' ) ) {
323
  $message = esc_html__( 'Tried creating robots.txt file', 'stream' );
338
  }
339
  }
340
 
341
+ /**
342
+ * Tracks the creation of WordPress SEO post meta
343
+ *
344
+ * @action added_post_meta
345
+ *
346
+ * @param int $meta_id Meta ID.
347
+ * @param int $object_id Object ID.
348
+ * @param string $meta_key Meta key.
349
+ * @param string $meta_value Meta value.
350
+ */
351
  public function callback_added_post_meta( $meta_id, $object_id, $meta_key, $meta_value ) {
352
  unset( $meta_id );
353
  $this->meta( $object_id, $meta_key, $meta_value );
354
  }
355
+
356
+ /**
357
+ * Tracks the updates to WordPress SEO post meta
358
+ *
359
+ * @action updated_post_meta
360
+ *
361
+ * @param int $meta_id Meta ID.
362
+ * @param int $object_id Object ID.
363
+ * @param string $meta_key Meta key.
364
+ * @param string $meta_value Meta value.
365
+ */
366
  public function callback_updated_post_meta( $meta_id, $object_id, $meta_key, $meta_value ) {
367
  unset( $meta_id );
368
  $this->meta( $object_id, $meta_key, $meta_value );
369
  }
370
+
371
+ /**
372
+ * Tracks the deletions of WordPress SEO post meta
373
+ *
374
+ * @action deleted_post_meta
375
+ *
376
+ * @param int $meta_id Meta ID.
377
+ * @param int $object_id Object ID.
378
+ * @param string $meta_key Meta key.
379
+ * @param string $meta_value Meta value.
380
+ */
381
  public function callback_deleted_post_meta( $meta_id, $object_id, $meta_key, $meta_value ) {
382
  unset( $meta_id );
383
  $this->meta( $object_id, $meta_key, $meta_value );
384
  }
385
 
386
+ /**
387
+ * Logs WordPress SEO meta activity
388
+ *
389
+ * @param int $object_id Object ID.
390
+ * @param int $meta_key Meta key.
391
+ * @param string $meta_value Meta value.
392
+ */
393
  private function meta( $object_id, $meta_key, $meta_value ) {
394
  $prefix = \WPSEO_Meta::$meta_prefix;
395
 
417
 
418
  $this->log(
419
  sprintf(
420
+ /* translators: %1$s: a meta field title, %2$s: a post title, %3$s: a post type (e.g. "Description", "Hello World", "Post") */
421
  __( 'Updated "%1$s" of "%2$s" %3$s', 'stream' ),
422
  $field['title'],
423
  $post->post_title,
437
  /**
438
  * Override connector log for our own Settings / Actions
439
  *
440
+ * @param array $data Record data.
441
  *
442
  * @return array|bool
443
  */
462
 
463
  $label = $this->settings_labels( $data['args']['option_key'] );
464
  if ( ! $label ) {
465
+ /* translators: %s: a context (e.g. "Dashboard") */
466
  $data['message'] = esc_html__( '%s settings updated', 'stream' );
467
  $label = $labels[ $page ];
468
  }
476
  return $data;
477
  }
478
 
479
+ /**
480
+ * Return the labels
481
+ *
482
+ * @param string $option Name of option to be retrieved.
483
+ *
484
+ * @return array|bool.
485
+ */
486
  private function settings_labels( $option ) {
487
  $labels = array(
488
+ // wp-content/plugins/wordpress-seo/admin/pages/dashboard.php:.
489
+ 'yoast_tracking' => esc_html_x( "Allow tracking of this WordPress install's anonymous data.", 'wordpress-seo', 'stream' ), // type = checkbox.
490
+ 'disableadvanced_meta' => esc_html_x( 'Disable the Advanced part of the WordPress SEO meta box', 'wordpress-seo', 'stream' ), // type = checkbox.
491
+ 'alexaverify' => esc_html_x( 'Alexa Verification ID', 'wordpress-seo', 'stream' ), // type = textinput.
492
+ 'msverify' => esc_html_x( 'Bing Webmaster Tools', 'wordpress-seo', 'stream' ), // type = textinput.
493
+ 'googleverify' => esc_html_x( 'Google Webmaster Tools', 'wordpress-seo', 'stream' ), // type = textinput.
494
+ 'pinterestverify' => esc_html_x( 'Pinterest', 'wordpress-seo', 'stream' ), // type = textinput.
495
+ 'yandexverify' => esc_html_x( 'Yandex Webmaster Tools', 'wordpress-seo', 'stream' ), // type = textinput.
496
+
497
+ // wp-content/plugins/wordpress-seo/admin/pages/advanced.php:.
498
+ 'breadcrumbs-enable' => esc_html_x( 'Enable Breadcrumbs', 'wordpress-seo', 'stream' ), // type = checkbox.
499
+ 'breadcrumbs-sep' => esc_html_x( 'Separator between breadcrumbs', 'wordpress-seo', 'stream' ), // type = textinput.
500
+ 'breadcrumbs-home' => esc_html_x( 'Anchor text for the Homepage', 'wordpress-seo', 'stream' ), // type = textinput.
501
+ 'breadcrumbs-prefix' => esc_html_x( 'Prefix for the breadcrumb path', 'wordpress-seo', 'stream' ), // type = textinput.
502
+ 'breadcrumbs-archiveprefix' => esc_html_x( 'Prefix for Archive breadcrumbs', 'wordpress-seo', 'stream' ), // type = textinput.
503
+ 'breadcrumbs-searchprefix' => esc_html_x( 'Prefix for Search Page breadcrumbs', 'wordpress-seo', 'stream' ), // type = textinput.
504
+ 'breadcrumbs-404crumb' => esc_html_x( 'Breadcrumb for 404 Page', 'wordpress-seo', 'stream' ), // type = textinput.
505
+ 'breadcrumbs-blog-remove' => esc_html_x( 'Remove Blog page from Breadcrumbs', 'wordpress-seo', 'stream' ), // type = checkbox.
506
+ 'breadcrumbs-boldlast' => esc_html_x( 'Bold the last page in the breadcrumb', 'wordpress-seo', 'stream' ), // type = checkbox.
507
+ 'post_types-post-maintax' => esc_html_x( 'Taxonomy to show in breadcrumbs for post types', 'wordpress-seo', 'stream' ), // type = select.
508
+
509
+ // wp-content/plugins/wordpress-seo/admin/pages/metas.php:.
510
+ 'forcerewritetitle' => esc_html_x( 'Force rewrite titles', 'wordpress-seo', 'stream' ), // type = checkbox.
511
+ 'noindex-subpages-wpseo' => esc_html_x( 'Noindex subpages of archives', 'wordpress-seo', 'stream' ), // type = checkbox.
512
+ 'usemetakeywords' => _x( 'Use <code>meta</code> keywords tag?', 'wordpress-seo', 'stream' ), // type = checkbox.
513
+ 'noodp' => _x( 'Add <code>noodp</code> meta robots tag sitewide', 'wordpress-seo', 'stream' ), // type = checkbox.
514
+ 'noydir' => _x( 'Add <code>noydir</code> meta robots tag sitewide', 'wordpress-seo', 'stream' ), // type = checkbox.
515
+ 'hide-rsdlink' => esc_html_x( 'Hide RSD Links', 'wordpress-seo', 'stream' ), // type = checkbox.
516
+ 'hide-wlwmanifest' => esc_html_x( 'Hide WLW Manifest Links', 'wordpress-seo', 'stream' ), // type = checkbox.
517
+ 'hide-shortlink' => esc_html_x( 'Hide Shortlink for posts', 'wordpress-seo', 'stream' ), // type = checkbox.
518
+ 'hide-feedlinks' => esc_html_x( 'Hide RSS Links', 'wordpress-seo', 'stream' ), // type = checkbox.
519
+ 'disable-author' => esc_html_x( 'Disable the author archives', 'wordpress-seo', 'stream' ), // type = checkbox.
520
+ 'disable-date' => esc_html_x( 'Disable the date-based archives', 'wordpress-seo', 'stream' ), // type = checkbox.
521
+
522
+ // wp-content/plugins/wordpress-seo/admin/pages/network.php:.
523
+ 'access' => esc_html_x( 'Who should have access to the WordPress SEO settings', 'wordpress-seo', 'stream' ), // type = select.
524
+ 'defaultblog' => esc_html_x( 'New blogs get the SEO settings from this blog', 'wordpress-seo', 'stream' ), // type = textinput.
525
+ 'restoreblog' => esc_html_x( 'Blog ID', 'wordpress-seo', 'stream' ), // type = textinput.
526
+
527
+ // wp-content/plugins/wordpress-seo/admin/pages/permalinks.php:.
528
+ 'stripcategorybase' => _x( 'Strip the category base (usually <code>/category/</code>) from the category URL.', 'wordpress-seo', 'stream' ), // type = checkbox.
529
+ 'trailingslash' => esc_html_x( "Enforce a trailing slash on all category and tag URL's", 'wordpress-seo', 'stream' ), // type = checkbox.
530
+ 'cleanslugs' => esc_html_x( 'Remove stop words from slugs.', 'wordpress-seo', 'stream' ), // type = checkbox.
531
+ 'redirectattachment' => esc_html_x( "Redirect attachment URL's to parent post URL.", 'wordpress-seo', 'stream' ), // type = checkbox.
532
+ 'cleanreplytocom' => _x( 'Remove the <code>?replytocom</code> variables.', 'wordpress-seo', 'stream' ), // type = checkbox.
533
+ 'cleanpermalinks' => esc_html_x( "Redirect ugly URL's to clean permalinks. (Not recommended in many cases!)", 'wordpress-seo', 'stream' ), // type = checkbox.
534
+ 'force_transport' => esc_html_x( 'Force Transport', 'wordpress-seo', 'stream' ), // type = select.
535
+ 'cleanpermalink-googlesitesearch' => esc_html_x( "Prevent cleaning out Google Site Search URL's.", 'wordpress-seo', 'stream' ), // type = checkbox.
536
+ 'cleanpermalink-googlecampaign' => esc_html_x( 'Prevent cleaning out Google Analytics Campaign & Google AdWords Parameters.', 'wordpress-seo', 'stream' ), // type = checkbox.
537
+ 'cleanpermalink-extravars' => esc_html_x( 'Other variables not to clean', 'wordpress-seo', 'stream' ), // type = textinput.
538
+
539
+ // wp-content/plugins/wordpress-seo/admin/pages/social.php:.
540
+ 'opengraph' => esc_html_x( 'Add Open Graph meta data', 'wordpress-seo', 'stream' ), // type = checkbox.
541
+ 'facebook_site' => esc_html_x( 'Facebook Page URL', 'wordpress-seo', 'stream' ), // type = textinput.
542
+ 'instagram_url' => esc_html_x( 'Instagram URL', 'wordpress-seo', 'stream' ), // type = textinput.
543
+ 'linkedin_url' => esc_html_x( 'LinkedIn URL', 'wordpress-seo', 'stream' ), // type = textinput.
544
+ 'myspace_url' => esc_html_x( 'MySpace URL', 'wordpress-seo', 'stream' ), // type = textinput.
545
+ 'pinterest_url' => esc_html_x( 'Pinterest URL', 'wordpress-seo', 'stream' ), // type = textinput.
546
+ 'youtube_url' => esc_html_x( 'YouTube URL', 'wordpress-seo', 'stream' ), // type = textinput.
547
+ 'google_plus_url' => esc_html_x( 'Google+ URL', 'wordpress-seo', 'stream' ), // type = textinput.
548
+ 'og_frontpage_image' => esc_html_x( 'Image URL', 'wordpress-seo', 'stream' ), // type = textinput.
549
+ 'og_frontpage_desc' => esc_html_x( 'Description', 'wordpress-seo', 'stream' ), // type = textinput.
550
+ 'og_frontpage_title' => esc_html_x( 'Title', 'wordpress-seo', 'stream' ), // type = textinput.
551
+ 'og_default_image' => esc_html_x( 'Image URL', 'wordpress-seo', 'stream' ), // type = textinput.
552
+ 'twitter' => esc_html_x( 'Add Twitter card meta data', 'wordpress-seo', 'stream' ), // type = checkbox.
553
+ 'twitter_site' => esc_html_x( 'Site Twitter Username', 'wordpress-seo', 'stream' ), // type = textinput.
554
+ 'twitter_card_type' => esc_html_x( 'The default card type to use', 'wordpress-seo', 'stream' ), // type = select.
555
+ 'googleplus' => esc_html_x( 'Add Google+ specific post meta data (excluding author metadata)', 'wordpress-seo', 'stream' ), // type = checkbox.
556
+ 'plus-publisher' => esc_html_x( 'Google Publisher Page', 'wordpress-seo', 'stream' ), // type = textinput.
557
+ 'fbadminapp' => esc_html_x( 'Facebook App ID', 'wordpress-seo', 'stream' ), // type = textinput.
558
+
559
+ // wp-content/plugins/wordpress-seo/admin/pages/xml-sitemaps.php:.
560
+ 'enablexmlsitemap' => esc_html_x( 'Check this box to enable XML sitemap functionality.', 'wordpress-seo', 'stream' ), // type = checkbox.
561
+ 'disable_author_sitemap' => esc_html_x( 'Disable author/user sitemap', 'wordpress-seo', 'stream' ), // type = checkbox.
562
+ 'disable_author_noposts' => esc_html_x( 'Users with zero posts', 'wordpress-seo', 'stream' ), // type = checkbox.
563
+ 'user_role-administrator-not_in_sitemap' => esc_html_x( 'Filter specific user roles - Administrator', 'wordpress-seo', 'stream' ), // type = checkbox.
564
+ 'user_role-editor-not_in_sitemap' => esc_html_x( 'Filter specific user roles - Editor', 'wordpress-seo', 'stream' ), // type = checkbox.
565
+ 'user_role-author-not_in_sitemap' => esc_html_x( 'Filter specific user roles - Author', 'wordpress-seo', 'stream' ), // type = checkbox.
566
+ 'user_role-contributor-not_in_sitemap' => esc_html_x( 'Filter specific user roles - Contributor', 'wordpress-seo', 'stream' ), // type = checkbox.
567
+ 'user_role-subscriber-not_in_sitemap' => esc_html_x( 'Filter specific user roles - Subscriber', 'wordpress-seo', 'stream' ), // type = checkbox.
568
+ 'xml_ping_yahoo' => esc_html_x( 'Ping Yahoo!', 'wordpress-seo', 'stream' ), // type = checkbox.
569
+ 'xml_ping_ask' => esc_html_x( 'Ping Ask.com', 'wordpress-seo', 'stream' ), // type = checkbox.
570
+ 'entries-per-page' => esc_html_x( 'Max entries per sitemap page', 'wordpress-seo', 'stream' ), // type = textinput.
571
+ 'excluded-posts' => esc_html_x( 'Posts to exclude', 'wordpress-seo', 'stream' ), // type = textinput.
572
+ 'post_types-post-not_in_sitemap' => _x( 'Post Types Posts (<code>post</code>)', 'wordpress-seo', 'stream' ), // type = checkbox.
573
+ 'post_types-page-not_in_sitemap' => _x( 'Post Types Pages (<code>page</code>)', 'wordpress-seo', 'stream' ), // type = checkbox.
574
+ 'post_types-attachment-not_in_sitemap' => _x( 'Post Types Media (<code>attachment</code>)', 'wordpress-seo', 'stream' ), // type = checkbox.
575
+ 'taxonomies-category-not_in_sitemap' => _x( 'Taxonomies Categories (<code>category</code>)', 'wordpress-seo', 'stream' ), // type = checkbox.
576
+ 'taxonomies-post_tag-not_in_sitemap' => _x( 'Taxonomies Tags (<code>post_tag</code>)', 'wordpress-seo', 'stream' ), // type = checkbox.
577
+
578
+ // Added manually.
579
  'rssbefore' => esc_html_x( 'Content to put before each post in the feed', 'wordpress-seo', 'stream' ),
580
  'rssafter' => esc_html_x( 'Content to put after each post', 'wordpress-seo', 'stream' ),
581
  );
582
 
583
  $ast_labels = array(
584
+ 'title-' => esc_html_x( 'Title template', 'wordpress-seo', 'stream' ), // type = textinput.
585
+ 'metadesc-' => esc_html_x( 'Meta description template', 'wordpress-seo', 'stream' ), // type = textarea.
586
+ 'metakey-' => esc_html_x( 'Meta keywords template', 'wordpress-seo', 'stream' ), // type = textinput.
587
+ 'noindex-' => esc_html_x( 'Meta Robots', 'wordpress-seo', 'stream' ), // type = checkbox.
588
+ 'noauthorship-' => esc_html_x( 'Authorship', 'wordpress-seo', 'stream' ), // type = checkbox.
589
+ 'showdate-' => esc_html_x( 'Show date in snippet preview?', 'wordpress-seo', 'stream' ), // type = checkbox.
590
+ 'hideeditbox-' => esc_html_x( 'WordPress SEO Meta Box', 'wordpress-seo', 'stream' ), // type = checkbox.
591
+ 'bctitle-' => esc_html_x( 'Breadcrumbs Title', 'wordpress-seo', 'stream' ), // type = textinput.
592
+ 'post_types-' => esc_html_x( 'Post types', 'wordpress-seo', 'stream' ), // type = checkbox.
593
+ 'taxonomies-' => esc_html_x( 'Taxonomies', 'wordpress-seo', 'stream' ), // type = checkbox.
594
  );
595
 
596
  if ( $option ) {
contributing.md CHANGED
@@ -26,7 +26,7 @@ For setups with local Docker environment you don't need Vagrant and VirtualBox.
26
  1. See the [Git Flow](#git-flow) section below for how to fork the repository.
27
  2. Run `npm install` to install all project dependencies.
28
  3. Run `vagrant up` to start the development environment.
29
- 4. Visit [stream.local](https://stream.local) and login using `admin` / `password`.
30
  5. Activate the Stream plugin.
31
 
32
  ### PHP Xdebug
26
  1. See the [Git Flow](#git-flow) section below for how to fork the repository.
27
  2. Run `npm install` to install all project dependencies.
28
  3. Run `vagrant up` to start the development environment.
29
+ 4. Visit [stream.local](http://stream.local) and login using `admin` / `password`.
30
  5. Activate the Stream plugin.
31
 
32
  ### PHP Xdebug
exporters/class-exporter-csv.php CHANGED
@@ -1,6 +1,15 @@
1
  <?php
 
 
 
 
 
 
2
  namespace WP_Stream;
3
 
 
 
 
4
  class Exporter_CSV extends Exporter {
5
  /**
6
  * Exporter name
1
  <?php
2
+ /**
3
+ * CSV Exporter
4
+ *
5
+ * @package WP_Stream
6
+ */
7
+
8
  namespace WP_Stream;
9
 
10
+ /**
11
+ * Class - Exporter_CSV
12
+ */
13
  class Exporter_CSV extends Exporter {
14
  /**
15
  * Exporter name
exporters/class-exporter-json.php CHANGED
@@ -1,6 +1,15 @@
1
  <?php
 
 
 
 
 
 
2
  namespace WP_Stream;
3
 
 
 
 
4
  class Exporter_JSON extends Exporter {
5
  /**
6
  * Exporter name
1
  <?php
2
+ /**
3
+ * JSON Exporter
4
+ *
5
+ * @package WP_Stream
6
+ */
7
+
8
  namespace WP_Stream;
9
 
10
+ /**
11
+ * Class - Exporter_JSON
12
+ */
13
  class Exporter_JSON extends Exporter {
14
  /**
15
  * Exporter name
includes/db-updates.php CHANGED
@@ -1,11 +1,17 @@
1
  <?php
 
 
 
 
 
 
2
  /**
3
  * Version 3.0.8
4
  *
5
  * Force update for older versions to call \dbdelta in install() method to fix column widths.
6
  *
7
- * @param string $db_version
8
- * @param string $current_version
9
  *
10
  * @return string
11
  */
@@ -19,8 +25,8 @@ function wp_stream_update_auto_308( $db_version, $current_version ) {
19
  /**
20
  * Version 3.0.2
21
  *
22
- * @param string $db_version
23
- * @param string $current_version
24
  *
25
  * @return string
26
  */
@@ -62,15 +68,15 @@ function wp_stream_update_302( $db_version, $current_version ) {
62
  *
63
  * Update from 1.4.9
64
  *
65
- * @param string $db_version
66
- * @param string $current_version
67
  *
68
  * @return string
69
  */
70
  function wp_stream_update_auto_300( $db_version, $current_version ) {
71
  global $wpdb;
72
 
73
- // Get only the author_meta values that are double-serialized
74
  $wpdb->query( "RENAME TABLE {$wpdb->base_prefix}stream TO {$wpdb->base_prefix}stream_tmp, {$wpdb->base_prefix}stream_context TO {$wpdb->base_prefix}stream_context_tmp" );
75
 
76
  $plugin = wp_stream_get_instance();
1
  <?php
2
+ /**
3
+ * Defines DB migrations.
4
+ *
5
+ * @package WP_Stream
6
+ */
7
+
8
  /**
9
  * Version 3.0.8
10
  *
11
  * Force update for older versions to call \dbdelta in install() method to fix column widths.
12
  *
13
+ * @param string $db_version New database version.
14
+ * @param string $current_version Current database version.
15
  *
16
  * @return string
17
  */
25
  /**
26
  * Version 3.0.2
27
  *
28
+ * @param string $db_version New database version.
29
+ * @param string $current_version Current database version.
30
  *
31
  * @return string
32
  */
68
  *
69
  * Update from 1.4.9
70
  *
71
+ * @param string $db_version New database version.
72
+ * @param string $current_version Current database version.
73
  *
74
  * @return string
75
  */
76
  function wp_stream_update_auto_300( $db_version, $current_version ) {
77
  global $wpdb;
78
 
79
+ // Get only the author_meta values that are double-serialized.
80
  $wpdb->query( "RENAME TABLE {$wpdb->base_prefix}stream TO {$wpdb->base_prefix}stream_tmp, {$wpdb->base_prefix}stream_context TO {$wpdb->base_prefix}stream_context_tmp" );
81
 
82
  $plugin = wp_stream_get_instance();
includes/feeds/atom.php CHANGED
@@ -1,4 +1,10 @@
1
  <?php
 
 
 
 
 
 
2
  header( 'Content-Type: ' . feed_content_type( 'atom' ) . '; charset=' . get_option( 'blog_charset' ), true );
3
  printf( '<?xml version="1.0" encoding="%s"?>', esc_attr( get_option( 'blog_charset' ) ) );
4
  ?>
@@ -30,7 +36,7 @@ printf( '<?xml version="1.0" encoding="%s"?>', esc_attr( get_option( 'blog_chars
30
  $display_name = isset( $author->display_name ) ? $author->display_name : 'N/A';
31
  ?>
32
  <entry>
33
- <title type="html"><![CDATA[[<?php echo esc_html( $domain ); ?>] <?php echo esc_html( $record->summary ); // xss ok ?> ]]></title>
34
  <link href="<?php echo esc_url( $record_link ); ?>" />
35
  <updated><?php echo esc_html( mysql2date( 'c', $record->created, false ) ); ?></updated>
36
  <author>
1
  <?php
2
+ /**
3
+ * Renders an Atom feed of records.
4
+ *
5
+ * @package WP_Stream
6
+ */
7
+
8
  header( 'Content-Type: ' . feed_content_type( 'atom' ) . '; charset=' . get_option( 'blog_charset' ), true );
9
  printf( '<?xml version="1.0" encoding="%s"?>', esc_attr( get_option( 'blog_charset' ) ) );
10
  ?>
36
  $display_name = isset( $author->display_name ) ? $author->display_name : 'N/A';
37
  ?>
38
  <entry>
39
+ <title type="html"><![CDATA[[<?php echo esc_html( $domain ); ?>] <?php echo esc_html( $record->summary ); // xss ok. ?> ]]></title>
40
  <link href="<?php echo esc_url( $record_link ); ?>" />
41
  <updated><?php echo esc_html( mysql2date( 'c', $record->created, false ) ); ?></updated>
42
  <author>
includes/feeds/json.php CHANGED
@@ -1,7 +1,13 @@
1
  <?php
 
 
 
 
 
 
2
  header( 'Content-type: application/json; charset=' . get_option( 'blog_charset' ), true );
3
  if ( version_compare( PHP_VERSION, '5.4', '<' ) ) {
4
- echo wp_stream_json_encode( $records ); // xss ok
5
  } else {
6
- echo wp_stream_json_encode( $records, JSON_PRETTY_PRINT ); // xss ok
7
  }
1
  <?php
2
+ /**
3
+ * Renders a JSON of records.
4
+ *
5
+ * @package WP_Stream
6
+ */
7
+
8
  header( 'Content-type: application/json; charset=' . get_option( 'blog_charset' ), true );
9
  if ( version_compare( PHP_VERSION, '5.4', '<' ) ) {
10
+ echo wp_stream_json_encode( $records ); // xss ok.
11
  } else {
12
+ echo wp_stream_json_encode( $records, JSON_PRETTY_PRINT ); // xss ok.
13
  }
includes/feeds/rss-2.0.php CHANGED
@@ -1,4 +1,10 @@
1
  <?php
 
 
 
 
 
 
2
  header( 'Content-Type: ' . feed_content_type( 'rss-http' ) . '; charset=' . get_option( 'blog_charset' ), true );
3
  printf( '<?xml version="1.0" encoding="%s"?>', esc_attr( get_option( 'blog_charset' ) ) );
4
  ?>
@@ -44,7 +50,7 @@ printf( '<?xml version="1.0" encoding="%s"?>', esc_attr( get_option( 'blog_chars
44
  $display_name = isset( $author->display_name ) ? $author->display_name : 'N/A';
45
  ?>
46
  <item>
47
- <title><![CDATA[ <?php echo esc_html( $record->summary ); // xss ok ?> ]]></title>
48
  <pubDate><?php echo esc_html( mysql2date( 'r', $record->created, false ) ); ?></pubDate>
49
  <dc:creator><?php echo esc_html( $display_name ); ?></dc:creator>
50
  <category domain="connector"><![CDATA[ <?php echo esc_html( $record->connector ); ?> ]]></category>
1
  <?php
2
+ /**
3
+ * Renders a RSS feed of records.
4
+ *
5
+ * @package WP_Stream
6
+ */
7
+
8
  header( 'Content-Type: ' . feed_content_type( 'rss-http' ) . '; charset=' . get_option( 'blog_charset' ), true );
9
  printf( '<?xml version="1.0" encoding="%s"?>', esc_attr( get_option( 'blog_charset' ) ) );
10
  ?>
50
  $display_name = isset( $author->display_name ) ? $author->display_name : 'N/A';
51
  ?>
52
  <item>
53
+ <title><![CDATA[ <?php echo esc_html( $record->summary ); // xss ok. ?> ]]></title>
54
  <pubDate><?php echo esc_html( mysql2date( 'r', $record->created, false ) ); ?></pubDate>
55
  <dc:creator><?php echo esc_html( $display_name ); ?></dc:creator>
56
  <category domain="connector"><![CDATA[ <?php echo esc_html( $record->connector ); ?> ]]></category>
includes/functions.php CHANGED
@@ -1,4 +1,10 @@
1
  <?php
 
 
 
 
 
 
2
  /**
3
  * Gets a specific external variable by name and optionally filters it.
4
  *
@@ -35,8 +41,8 @@ function wp_stream_filter_var( $var, $filter = null, $options = array() ) {
35
  /**
36
  * Converts a time into an ISO 8601 extended formatted string.
37
  *
38
- * @param int|bool $time Seconds since unix epoc
39
- * @param int $offset Hour offset
40
  *
41
  * @return string an ISO 8601 extended formatted time
42
  */
@@ -48,25 +54,20 @@ function wp_stream_get_iso_8601_extended_date( $time = false, $offset = 0 ) {
48
  }
49
 
50
  $micro_seconds = sprintf( '%06d', ( $microtime - floor( $microtime ) ) * 1000000 );
51
- $offset_string = sprintf( 'Etc/GMT%s%s', $offset < 0 ? '+' : '-', abs( $offset ) );
52
 
53
  $timezone = new DateTimeZone( $offset_string );
54
- $date = new DateTime( date( 'Y-m-d H:i:s.' . $micro_seconds, $microtime ), $timezone );
55
 
56
- return sprintf(
57
- '%s%03d%s',
58
- $date->format( 'Y-m-d\TH:i:s.' ),
59
- floor( $date->format( 'u' ) / 1000 ),
60
- $date->format( 'O' )
61
- );
62
  }
63
 
64
  /**
65
  * Encode to JSON in a way that is also backwards compatible
66
  *
67
- * @param mixed $data
68
- * @param int $options (optional)
69
- * @param int $depth (optional)
70
  *
71
  * @return string
72
  */
@@ -89,7 +90,7 @@ function wp_stream_json_encode( $data, $options = 0, $depth = 512 ) {
89
  /**
90
  * Return an array of sites for a network in a way that is also backwards compatible
91
  *
92
- * @param string|array $args
93
  *
94
  * @return array
95
  */
@@ -131,7 +132,7 @@ function wp_stream_is_cron_enabled() {
131
  * @return string
132
  */
133
  function wp_stream_min_suffix() {
134
- $min = '';
135
  $is_script_debugging = ! defined( 'SCRIPT_DEBUG' ) || false === SCRIPT_DEBUG;
136
 
137
  if ( apply_filters( 'wp_stream_load_min_assets', $is_script_debugging ) ) {
1
  <?php
2
+ /**
3
+ * Defines common functionality used throughout the plugin.
4
+ *
5
+ * @package WP_Stream
6
+ */
7
+
8
  /**
9
  * Gets a specific external variable by name and optionally filters it.
10
  *
41
  /**
42
  * Converts a time into an ISO 8601 extended formatted string.
43
  *
44
+ * @param int|bool $time Seconds since unix epoch.
45
+ * @param int $offset Timezone offset.
46
  *
47
  * @return string an ISO 8601 extended formatted time
48
  */
54
  }
55
 
56
  $micro_seconds = sprintf( '%06d', ( $microtime - floor( $microtime ) ) * 1000000 );
57
+ $offset_string = sprintf( 'Etc/GMT%s%d', $offset < 0 ? '+' : '-', abs( $offset ) );
58
 
59
  $timezone = new DateTimeZone( $offset_string );
60
+ $date = new DateTime( gmdate( 'Y-m-d H:i:s.' . $micro_seconds, $microtime ), $timezone );
61
 
62
+ return $date->format( 'Y-m-d\TH:i:sO' );
 
 
 
 
 
63
  }
64
 
65
  /**
66
  * Encode to JSON in a way that is also backwards compatible
67
  *
68
+ * @param mixed $data Data to be encoded.
69
+ * @param int $options Compression options (optional).
70
+ * @param int $depth Tree depth limit (optional).
71
  *
72
  * @return string
73
  */
90
  /**
91
  * Return an array of sites for a network in a way that is also backwards compatible
92
  *
93
+ * @param string|array $args Argument to filter results by.
94
  *
95
  * @return array
96
  */
132
  * @return string
133
  */
134
  function wp_stream_min_suffix() {
135
+ $min = '';
136
  $is_script_debugging = ! defined( 'SCRIPT_DEBUG' ) || false === SCRIPT_DEBUG;
137
 
138
  if ( apply_filters( 'wp_stream_load_min_assets', $is_script_debugging ) ) {
includes/lib/Carbon.php CHANGED
@@ -312,14 +312,14 @@ class Carbon extends DateTime
312
  */
313
  public static function create($year = null, $month = null, $day = null, $hour = null, $minute = null, $second = null, $tz = null)
314
  {
315
- $year = ($year === null) ? date('Y') : $year;
316
- $month = ($month === null) ? date('n') : $month;
317
- $day = ($day === null) ? date('j') : $day;
318
 
319
  if ($hour === null) {
320
- $hour = date('G');
321
- $minute = ($minute === null) ? date('i') : $minute;
322
- $second = ($second === null) ? date('s') : $second;
323
  } else {
324
  $minute = ($minute === null) ? 0 : $minute;
325
  $second = ($second === null) ? 0 : $second;
@@ -2211,4 +2211,4 @@ class Carbon extends DateTime
2211
  {
2212
  return $this->month === $dt->month && $this->day === $dt->day;
2213
  }
2214
- }
312
  */
313
  public static function create($year = null, $month = null, $day = null, $hour = null, $minute = null, $second = null, $tz = null)
314
  {
315
+ $year = ($year === null) ? gmdate('Y') : $year;
316
+ $month = ($month === null) ? gmdate('n') : $month;
317
+ $day = ($day === null) ? gmdate('j') : $day;
318
 
319
  if ($hour === null) {
320
+ $hour = gmdate('G');
321
+ $minute = ($minute === null) ? gmdate('i') : $minute;
322
+ $second = ($second === null) ? gmdate('s') : $second;
323
  } else {
324
  $minute = ($minute === null) ? 0 : $minute;
325
  $second = ($second === null) ? 0 : $second;
2211
  {
2212
  return $this->month === $dt->month && $this->day === $dt->day;
2213
  }
2214
+ }
readme.md CHANGED
@@ -1,6 +1,7 @@
1
  # Stream for WordPress
2
 
3
  [![Build Status](https://travis-ci.com/xwp/stream.svg?branch=master)](https://travis-ci.com/xwp/stream)
 
4
 
5
  **Track WordPress user and system actions for debugging, logging and compliance purposes.**
6
 
1
  # Stream for WordPress
2
 
3
  [![Build Status](https://travis-ci.com/xwp/stream.svg?branch=master)](https://travis-ci.com/xwp/stream)
4
+ [![Coverage Status](https://coveralls.io/repos/github/xwp/stream/badge.svg?branch=develop)](https://coveralls.io/github/xwp/stream?branch=develop)
5
 
6
  **Track WordPress user and system actions for debugging, logging and compliance purposes.**
7
 
readme.txt CHANGED
@@ -1,24 +1,26 @@
1
  === Stream ===
2
- Contributors: lukecarbis, fjarrett, stream, xwp, kasparsd
3
  Tags: wp stream, stream, activity, logs, track
4
  Requires at least: 4.5
5
  Tested up to: 5.4
6
- Stable tag: 3.4.3
7
  License: GPLv2 or later
8
  License URI: https://www.gnu.org/licenses/gpl-2.0.html
9
 
10
- Planes have a black box, WordPress has Stream. When something goes wrong, you need to know how it happened.
11
-
12
 
13
  == Description ==
14
 
15
- With Stream, you're never left in the dark about WordPress Admin activity.
 
 
 
 
16
 
17
- Every logged-in user action is displayed in an activity stream and organized for easy filtering by User, Role, Context, Action or IP address.
18
 
19
- For advanced users, Stream also supports a Multisite view of all activity records on your network, the ability to set exclude rules to ignore certain kinds of user activity, and a WP‑CLI command for querying records.
20
 
21
- Stream is perfect for keeping tabs on your clients. When something breaks, Stream is there to help. See what changed and who changed it.
22
 
23
  = Built-In Tracking Integrations For Popular Plugins: =
24
 
@@ -30,7 +32,7 @@ Stream is perfect for keeping tabs on your clients. When something breaks, Strea
30
  * Jetpack
31
  * User Switching
32
  * WooCommerce
33
- * WordPress SEO by Yoast
34
 
35
  = Built-In Tracking For Core Actions: =
36
 
@@ -77,6 +79,8 @@ There are several ways you can get involved to help make Stream better:
77
 
78
  Thank you for wanting to make Stream better for everyone!
79
 
 
 
80
 
81
  == Screenshots ==
82
 
@@ -87,6 +91,12 @@ Thank you for wanting to make Stream better for everyone!
87
 
88
  == Changelog ==
89
 
 
 
 
 
 
 
90
  = 3.4.3 - March 19, 2020 =
91
 
92
  * Fix: Stream records can be filtered by users again [#929](https://github.com/xwp/stream/issues/929), props [@tareiking](https://github.com/tareiking).
1
  === Stream ===
2
+ Contributors: xwp
3
  Tags: wp stream, stream, activity, logs, track
4
  Requires at least: 4.5
5
  Tested up to: 5.4
6
+ Stable tag: 3.5.0
7
  License: GPLv2 or later
8
  License URI: https://www.gnu.org/licenses/gpl-2.0.html
9
 
10
+ With Stream, you’re never left in the dark about changes to your WordPress site.
 
11
 
12
  == Description ==
13
 
14
+ With real-time notifications and third-party integrations, Stream can proactively alert you when something goes wrong with your WordPress site.
15
+
16
+ Designed for debugging and compliance purposes, Stream is useful for keeping tabs on your WordPress users: From activating plugins to deleting posts, to login attempts and new user creation, you can see what’s changed, who changed it and when.
17
+
18
+ The plugin records WordPress user and system action to the Stream logs. Every logged-in user action is displayed in an activity stream and organized for easy filtering by User, Role, Context, Action or IP address. Admins can highlight entries in the Stream log—such as suspicious user activity—to investigate what’s happening in real time. Stream also allows you to configure email alerts and webhooks for integrations like Slack and IFTTT to notify you and your team when something has gone wrong.
19
 
20
+ For advanced users, Stream also supports a network view of all activity records on your Multisite, the ability to set exclude rules to ignore certain kinds of user activity, and a WP‑CLI command for querying records.
21
 
22
+ With Stream’s powerful logging, you’ll have the valuable information you need to responsibly manage your WordPress sites.
23
 
 
24
 
25
  = Built-In Tracking Integrations For Popular Plugins: =
26
 
32
  * Jetpack
33
  * User Switching
34
  * WooCommerce
35
+ * Yoast SEO
36
 
37
  = Built-In Tracking For Core Actions: =
38
 
79
 
80
  Thank you for wanting to make Stream better for everyone!
81
 
82
+ Past Contributors: fjarrett, shadyvb, chacha, westonruter, johnregan3, jacobschweitzer, lukecarbis, kasparsd, bordoni, dero, faishal, rob, desaiuditd, DavidCramer, renovate-bot, marcin-lawrowski, JeffMatson, Powdered-Toast-Man, johnolek, johnbillion, greguly, pascal-klaeres, szepeviktor, rheinardkorf, frozzare, khromov, dkotter, bhubbard, stipsan, stephenharris, omniwired, kopepasah, joehoyle, eugenekireev, barryceelen, valendesigns, tlovett1, tareiking, stayallive, sayedtaqui, robbiet480, oscarssanchez, kidunot89, johnwatkins0, javorszky, jamesgol, desrosj, davelozier, davefx, cfoellmann, JustinSainton, JJJ, postphotos
83
+
84
 
85
  == Screenshots ==
86
 
91
 
92
  == Changelog ==
93
 
94
+ = 3.5.0 - July 8, 2020 =
95
+
96
+ * Fix: Stream records now show the correct timestamp instead of dates like `-0001/11/30` [#1091](https://github.com/xwp/stream/issues/1091), props [@kidunot89](https://github.com/kidunot89).
97
+ * Fix: Searching Stream records is now more performant as we throttle the amount of search requests [#1081](https://github.com/xwp/stream/issues/1081), props [@oscarssanchez](https://github.com/oscarssanchez).
98
+ * Tweak: Inline PHP documentation updates and WordPress coding standard fixes, props [@kidunot89](https://github.com/kidunot89).
99
+
100
  = 3.4.3 - March 19, 2020 =
101
 
102
  * Fix: Stream records can be filtered by users again [#929](https://github.com/xwp/stream/issues/929), props [@tareiking](https://github.com/tareiking).
stream.php CHANGED
@@ -3,12 +3,14 @@
3
  * Plugin Name: Stream
4
  * Plugin URI: https://wp-stream.com
5
  * Description: Stream tracks logged-in user activity so you can monitor every change made on your WordPress site in beautifully organized detail. All activity is organized by context, action and IP address for easy filtering. Developers can extend Stream with custom connectors to log any kind of action.
6
- * Version: 3.4.3
7
  * Author: XWP
8
  * Author URI: https://xwp.co
9
  * License: GPLv2+
10
  * Text Domain: stream
11
  * Domain Path: /languages
 
 
12
  */
13
 
14
  /**
3
  * Plugin Name: Stream
4
  * Plugin URI: https://wp-stream.com
5
  * Description: Stream tracks logged-in user activity so you can monitor every change made on your WordPress site in beautifully organized detail. All activity is organized by context, action and IP address for easy filtering. Developers can extend Stream with custom connectors to log any kind of action.
6
+ * Version: 3.5.0
7
  * Author: XWP
8
  * Author URI: https://xwp.co
9
  * License: GPLv2+
10
  * Text Domain: stream
11
  * Domain Path: /languages
12
+ *
13
+ * @package WP_Stream
14
  */
15
 
16
  /**
ui/js/admin.js CHANGED
@@ -68,6 +68,7 @@ jQuery(
68
  width: '165px',
69
  ajax: {
70
  url: ajaxurl,
 
71
  dataType: 'json',
72
  quietMillis: 100,
73
  data: function( term ) {
68
  width: '165px',
69
  ajax: {
70
  url: ajaxurl,
71
+ delay: 500,
72
  dataType: 'json',
73
  quietMillis: 100,
74
  data: function( term ) {
ui/js/admin.min.js CHANGED
@@ -1 +1 @@
1
- jQuery(function(e){"en"===wp_stream.locale&&void 0!==e.timeago&&(e.timeago.settings.strings.seconds="seconds",e.timeago.settings.strings.minute="a minute",e.timeago.settings.strings.hour="an hour",e.timeago.settings.strings.hours="%d hours",e.timeago.settings.strings.month="a month",e.timeago.settings.strings.year="a year"),e("li.toplevel_page_wp_stream ul li.wp-first-item.current").parent().parent().find(".update-plugins").remove(),e(".toplevel_page_wp_stream :input.chosen-select").each(function(t,a){var i={},n=function(t){var a=e("<span>"),i=e(t.element),n="";return"- "===t.text.substring(0,2)&&(t.text=t.text.substring(2)),void 0!==t.id&&"string"==typeof t.id&&(0===t.id.indexOf("group-")?a.addClass("parent"):i.hasClass("level-2")&&a.addClass("child")),void 0!==t.icon?n=t.icon:void 0!==i&&""!==i.data("icon")&&(n=i.data("icon")),n&&a.html('<img src="'+n+'" class="wp-stream-select2-icon">'),a.append(t.text),a},r=function(e){return"- "===e.text.substring(0,2)&&(e.text=e.text.substring(2)),e.text};i=e(a).find("option").not(":selected").not(":empty").length>0?{minimumResultsForSearch:10,templateResult:n,templateSelection:r,allowClear:!0,width:"165px"}:{minimumInputLength:3,allowClear:!0,width:"165px",ajax:{url:ajaxurl,dataType:"json",quietMillis:100,data:function(t){return{action:"wp_stream_filters",nonce:e("#stream_filters_user_search_nonce").val(),filter:e(a).attr("name"),q:t.term}},processResults:function(t){var a=[];return e.each(t,function(e,t){a.push({id:t.id,text:t.label})}),{results:a}}},templateResult:n,templateSelection:r},e(a).select2(i)});var t=e.streamGetQueryVars(),a=e('.toplevel_page_wp_stream select.chosen-select[name="context"]');void 0!==t.context&&""!==t.context||void 0===t.connector||(a.val("group-"+t.connector),a.trigger("change")),e("input[type=submit]","#record-filter-form").click(function(){e("input[type=submit]",e(this).parents("form")).removeAttr("clicked"),e(this).attr("clicked","true")}),e("#record-filter-form").submit(function(){var t=e('.toplevel_page_wp_stream :input.chosen-select[name="context"]'),a=t.find("option:selected"),i=t.parent().find(".record-filter-connector"),n=a.data("group"),r=a.prop("class"),s=e(".recordactions select");"true"!==e("#record-actions-submit").attr("clicked")&&s.val(""),i.val(n),"level-1"===r&&a.val("")}),e(window).load(function(){e('.toplevel_page_wp_stream input[type="search"]').off("mousedown")}),e("body").on("click","#wp_stream_advanced_delete_all_records, #wp_stream_network_advanced_delete_all_records",function(e){window.confirm(wp_stream.i18n.confirm_purge)||e.preventDefault()}),e("body").on("click","#wp_stream_advanced_reset_site_settings, #wp_stream_network_advanced_reset_site_settings",function(e){window.confirm(wp_stream.i18n.confirm_defaults)||e.preventDefault()}),e("body").on("click","#wp_stream_uninstall",function(e){window.confirm(wp_stream.i18n.confirm_uninstall)||e.preventDefault()});var i=e(".wp_stream_screen .nav-tab-wrapper"),n=e(".wp_stream_screen .nav-tab-content table.form-table"),r=i.find(".nav-tab-active"),s=r.length>0?i.find("a").index(r):0,o=window.location.hash.match(/^#(\d+)$/),c=null!==o?o[1]:s,d=function(t){var a=e('input[name="option_page"][value^="wp_stream"]').closest("form");if(0!==a.length){var i=a.attr("action");a.prop("action",i.replace(/(^[^#]*).*$/,"$1#"+t))}};i.on("click","a",function(){var t=i.find("a").index(e(this)),a=window.location.hash.match(/^#(\d+)$/);return n.hide().eq(t).show(),i.find("a").removeClass("nav-tab-active").filter(e(this)).addClass("nav-tab-active"),""!==window.location.hash&&null===a||(window.location.hash=t),d(t),!1}),i.children().eq(c).trigger("click"),e(document).ready(function(){function t(){var t=!0;e('div.metabox-prefs [name="date-hide"]').is(":checked")&&(t=!1),e("div.alignleft.actions div.select2-container").each(function(){if(!e(this).is(":hidden"))return t=!1,!1}),t?(e("input#record-query-submit").hide(),e("span.filter_info").show()):(e("input#record-query-submit").show(),e("span.filter_info").hide())}e("#enable_live_update").click(function(){var t=e("#stream_live_update_nonce").val(),a=e("#enable_live_update_user").val(),i="unchecked",n="true";e("#enable_live_update").is(":checked")&&(i="checked"),n=e("#enable_live_update").data("heartbeat"),e.ajax({type:"POST",url:ajaxurl,data:{action:"stream_enable_live_update",nonce:t,user:a,checked:i,heartbeat:n},dataType:"json",beforeSend:function(){e(".stream-live-update-checkbox .spinner").show().css({display:"inline-block"})},success:function(t){e(".stream-live-update-checkbox .spinner").hide(),!1===t.success&&(e("#enable_live_update").prop("checked",!1),t.data&&window.alert(t.data))}})}),e('div.metabox-prefs [name="date-hide"]').is(":checked")?e("div.date-interval").show():e("div.date-interval").hide(),e("div.actions select.chosen-select").each(function(){var t=e(this).prop("name");e('div.metabox-prefs [name="'+t+'-hide"]').is(":checked")?e(this).prev(".select2-container").show():e(this).prev(".select2-container").hide()}),t(),e('div.metabox-prefs [type="checkbox"]').click(function(){var a=e(this).prop("id");"date-hide"===a?e(this).is(":checked")?e("div.date-interval").show():e("div.date-interval").hide():(a=a.replace("-hide",""),e(this).is(":checked")?e('[name="'+a+'"]').prev(".select2-container").show():e('[name="'+a+'"]').prev(".select2-container").hide()),t()}),e("#ui-datepicker-div").addClass("stream-datepicker")}),e("table.wp-list-table").on("updated",function(){e(this).find("time.relative-time").each(function(t,a){var i=e(a);i.removeClass("relative-time"),e('<strong><time datetime="'+i.attr("datetime")+'" class="timeago"/></time></strong><br/>').prependTo(i.parent().parent()).find("time.timeago").timeago()})}).trigger("updated");var l={init:function(t){this.wrapper=t,this.save_interval(this.wrapper.find(".button-primary"),this.wrapper),this.$=this.wrapper.each(function(t,a){var i=e(a),n=i.find(".date-inputs"),r=i.find(".field-from"),s=i.find(".field-to"),o=s.prev(".date-remove"),c=r.prev(".date-remove"),d=i.children(".field-predefined"),l=e("").add(s).add(r);if(jQuery.datepicker){var p=parseFloat(wp_stream.gmt_offset)-(new Date).getTimezoneOffset()/60*-1,u=new Date,h=new Date(u.getTime()+60*p*60*1e3),m=0;u.getDate()===h.getDate()&&u.getMonth()===h.getMonth()||(m=u.getTime()<h.getTime()?"+1d":"-1d"),l.datepicker({dateFormat:"yy/mm/dd",minDate:null,maxDate:m,defaultDate:h,beforeShow:function(){e(this).prop("disabled",!0)},onClose:function(){e(this).prop("disabled",!1)}}),l.datepicker("widget").addClass("stream-datepicker")}d.select2({allowClear:!0}),""!==r.val()&&c.show(),""!==s.val()&&o.show(),d.on({change:function(){var t=e(this).val(),a=d.find('[value="'+t+'"]'),i=a.data("to"),o=a.data("from");if("custom"===t)return n.show(),!1;n.hide(),l.datepicker("hide"),r.val(o).trigger("change",[!0]),s.val(i).trigger("change",[!0]),jQuery.datepicker&&l.datepicker("widget").is(":visible")&&l.datepicker("refresh").datepicker("hide")},"select2-removed":function(){d.val("").trigger("change")},check_options:function(){if(""!==s.val()&&""!==r.val()){var e=d.find("option").filter('[data-to="'+s.val()+'"]').filter('[data-from="'+r.val()+'"]');0!==e.length?d.val(e.attr("value")).trigger("change",[!0]):d.val("custom").trigger("change",[!0])}else""===s.val()&&""===r.val()?d.val("").trigger("change",[!0]):d.val("custom").trigger("change",[!0])}}),r.on("change",function(){if(""!==r.val()?(c.show(),s.datepicker("option","minDate",r.val())):c.hide(),!0===arguments[arguments.length-1])return!1;d.trigger("check_options")}),s.on("change",function(){if(""!==s.val()?(o.show(),r.datepicker("option","maxDate",s.val())):o.hide(),!0===arguments[arguments.length-1])return!1;d.trigger("check_options")}),d.trigger("change"),e("").add(c).add(o).on("click",function(){e(this).next("input").val("").trigger("change")})})},save_interval:function(t){var a=this.wrapper;t.click(function(){var t={key:a.find("select.field-predefined").find(":selected").val(),start:a.find(".date-inputs .field-from").val(),end:a.find(".date-inputs .field-to").val()};e(this).attr("href",e(this).attr("href")+"&"+e.param(t))})}};e(document).ready(function(){l.init(e(".date-interval")),e('select[name="context"] .level-1').each(function(){var t=!0;e(this).nextUntil(".level-1").each(function(){if(e(this).is(":not(:disabled)"))return t=!1,!1}),!0===t&&e(this).prop("disabled",!0)})})}),jQuery.extend({streamGetQueryVars:function(e){return(e||document.location.search).replace(/(^\?)/,"").split("&").map(function(e){return e=e.split("="),this[e[0]]=e[1],this}.bind({}))[0]}});
1
+ jQuery(function(m){"en"===wp_stream.locale&&void 0!==m.timeago&&(m.timeago.settings.strings.seconds="seconds",m.timeago.settings.strings.minute="a minute",m.timeago.settings.strings.hour="an hour",m.timeago.settings.strings.hours="%d hours",m.timeago.settings.strings.month="a month",m.timeago.settings.strings.year="a year"),m("li.toplevel_page_wp_stream ul li.wp-first-item.current").parent().parent().find(".update-plugins").remove(),m(".toplevel_page_wp_stream :input.chosen-select").each(function(e,t){function a(e){var t=m("<span>"),a=m(e.element),i="";return"- "===e.text.substring(0,2)&&(e.text=e.text.substring(2)),void 0!==e.id&&"string"==typeof e.id&&(0===e.id.indexOf("group-")?t.addClass("parent"):a.hasClass("level-2")&&t.addClass("child")),void 0!==e.icon?i=e.icon:void 0!==a&&""!==a.data("icon")&&(i=a.data("icon")),i&&t.html('<img src="'+i+'" class="wp-stream-select2-icon">'),t.append(e.text),t}function i(e){return"- "===e.text.substring(0,2)&&(e.text=e.text.substring(2)),e.text}var n={};n=0<m(t).find("option").not(":selected").not(":empty").length?{minimumResultsForSearch:10,templateResult:a,templateSelection:i,allowClear:!0,width:"165px"}:{minimumInputLength:3,allowClear:!0,width:"165px",ajax:{url:ajaxurl,delay:500,dataType:"json",quietMillis:100,data:function(e){return{action:"wp_stream_filters",nonce:m("#stream_filters_user_search_nonce").val(),filter:m(t).attr("name"),q:e.term}},processResults:function(e){var a=[];return m.each(e,function(e,t){a.push({id:t.id,text:t.label})}),{results:a}}},templateResult:a,templateSelection:i},m(t).select2(n)});var e=m.streamGetQueryVars(),t=m('.toplevel_page_wp_stream select.chosen-select[name="context"]');void 0!==e.context&&""!==e.context||void 0===e.connector||(t.val("group-"+e.connector),t.trigger("change")),m("input[type=submit]","#record-filter-form").click(function(){m("input[type=submit]",m(this).parents("form")).removeAttr("clicked"),m(this).attr("clicked","true")}),m("#record-filter-form").submit(function(){var e=m('.toplevel_page_wp_stream :input.chosen-select[name="context"]'),t=e.find("option:selected"),a=e.parent().find(".record-filter-connector"),i=t.data("group"),n=t.prop("class"),r=m(".recordactions select");"true"!==m("#record-actions-submit").attr("clicked")&&r.val(""),a.val(i),"level-1"===n&&t.val("")}),m(window).load(function(){m('.toplevel_page_wp_stream input[type="search"]').off("mousedown")}),m("body").on("click","#wp_stream_advanced_delete_all_records, #wp_stream_network_advanced_delete_all_records",function(e){window.confirm(wp_stream.i18n.confirm_purge)||e.preventDefault()}),m("body").on("click","#wp_stream_advanced_reset_site_settings, #wp_stream_network_advanced_reset_site_settings",function(e){window.confirm(wp_stream.i18n.confirm_defaults)||e.preventDefault()}),m("body").on("click","#wp_stream_uninstall",function(e){window.confirm(wp_stream.i18n.confirm_uninstall)||e.preventDefault()});var a=m(".wp_stream_screen .nav-tab-wrapper"),i=m(".wp_stream_screen .nav-tab-content table.form-table"),n=a.find(".nav-tab-active"),r=0<n.length?a.find("a").index(n):0,s=window.location.hash.match(/^#(\d+)$/),o=null!==s?s[1]:r;a.on("click","a",function(){var e=a.find("a").index(m(this)),t=window.location.hash.match(/^#(\d+)$/);return i.hide().eq(e).show(),a.find("a").removeClass("nav-tab-active").filter(m(this)).addClass("nav-tab-active"),""!==window.location.hash&&null===t||(window.location.hash=e),function(e){var t=m('input[name="option_page"][value^="wp_stream"]').closest("form");if(0!==t.length){var a=t.attr("action");t.prop("action",a.replace(/(^[^#]*).*$/,"$1#"+e))}}(e),!1}),a.children().eq(o).trigger("click"),m(document).ready(function(){function t(){var e=!0;m('div.metabox-prefs [name="date-hide"]').is(":checked")&&(e=!1),m("div.alignleft.actions div.select2-container").each(function(){if(!m(this).is(":hidden"))return e=!1}),e?(m("input#record-query-submit").hide(),m("span.filter_info").show()):(m("input#record-query-submit").show(),m("span.filter_info").hide())}m("#enable_live_update").click(function(){var e,t=m("#stream_live_update_nonce").val(),a=m("#enable_live_update_user").val(),i="unchecked";m("#enable_live_update").is(":checked")&&(i="checked"),e=m("#enable_live_update").data("heartbeat"),m.ajax({type:"POST",url:ajaxurl,data:{action:"stream_enable_live_update",nonce:t,user:a,checked:i,heartbeat:e},dataType:"json",beforeSend:function(){m(".stream-live-update-checkbox .spinner").show().css({display:"inline-block"})},success:function(e){m(".stream-live-update-checkbox .spinner").hide(),!1===e.success&&(m("#enable_live_update").prop("checked",!1),e.data&&window.alert(e.data))}})}),m('div.metabox-prefs [name="date-hide"]').is(":checked")?m("div.date-interval").show():m("div.date-interval").hide(),m("div.actions select.chosen-select").each(function(){var e=m(this).prop("name");m('div.metabox-prefs [name="'+e+'-hide"]').is(":checked")?m(this).prev(".select2-container").show():m(this).prev(".select2-container").hide()}),t(),m('div.metabox-prefs [type="checkbox"]').click(function(){var e=m(this).prop("id");"date-hide"===e?m(this).is(":checked")?m("div.date-interval").show():m("div.date-interval").hide():(e=e.replace("-hide",""),m(this).is(":checked")?m('[name="'+e+'"]').prev(".select2-container").show():m('[name="'+e+'"]').prev(".select2-container").hide()),t()}),m("#ui-datepicker-div").addClass("stream-datepicker")}),m("table.wp-list-table").on("updated",function(){m(this).find("time.relative-time").each(function(e,t){var a=m(t);a.removeClass("relative-time"),m('<strong><time datetime="'+a.attr("datetime")+'" class="timeago"/></time></strong><br/>').prependTo(a.parent().parent()).find("time.timeago").timeago()})}).trigger("updated");var c={init:function(e){this.wrapper=e,this.save_interval(this.wrapper.find(".button-primary"),this.wrapper),this.$=this.wrapper.each(function(e,t){var a=m(t),n=a.find(".date-inputs"),r=a.find(".field-from"),s=a.find(".field-to"),i=s.prev(".date-remove"),o=r.prev(".date-remove"),c=a.children(".field-predefined"),d=m("").add(s).add(r);if(jQuery.datepicker){var l=parseFloat(wp_stream.gmt_offset)-(new Date).getTimezoneOffset()/60*-1,p=new Date,u=new Date(p.getTime()+60*l*60*1e3),h=0;p.getDate()===u.getDate()&&p.getMonth()===u.getMonth()||(h=p.getTime()<u.getTime()?"+1d":"-1d"),d.datepicker({dateFormat:"yy/mm/dd",minDate:null,maxDate:h,defaultDate:u,beforeShow:function(){m(this).prop("disabled",!0)},onClose:function(){m(this).prop("disabled",!1)}}),d.datepicker("widget").addClass("stream-datepicker")}c.select2({allowClear:!0}),""!==r.val()&&o.show(),""!==s.val()&&i.show(),c.on({change:function(){var e=m(this).val(),t=c.find('[value="'+e+'"]'),a=t.data("to"),i=t.data("from");if("custom"===e)return n.show(),!1;n.hide(),d.datepicker("hide"),r.val(i).trigger("change",[!0]),s.val(a).trigger("change",[!0]),jQuery.datepicker&&d.datepicker("widget").is(":visible")&&d.datepicker("refresh").datepicker("hide")},"select2-removed":function(){c.val("").trigger("change")},check_options:function(){if(""!==s.val()&&""!==r.val()){var e=c.find("option").filter('[data-to="'+s.val()+'"]').filter('[data-from="'+r.val()+'"]');0!==e.length?c.val(e.attr("value")).trigger("change",[!0]):c.val("custom").trigger("change",[!0])}else""===s.val()&&""===r.val()?c.val("").trigger("change",[!0]):c.val("custom").trigger("change",[!0])}}),r.on("change",function(){if(""!==r.val()?(o.show(),s.datepicker("option","minDate",r.val())):o.hide(),!0===arguments[arguments.length-1])return!1;c.trigger("check_options")}),s.on("change",function(){if(""!==s.val()?(i.show(),r.datepicker("option","maxDate",s.val())):i.hide(),!0===arguments[arguments.length-1])return!1;c.trigger("check_options")}),c.trigger("change"),m("").add(o).add(i).on("click",function(){m(this).next("input").val("").trigger("change")})})},save_interval:function(e){var t=this.wrapper;e.click(function(){var e={key:t.find("select.field-predefined").find(":selected").val(),start:t.find(".date-inputs .field-from").val(),end:t.find(".date-inputs .field-to").val()};m(this).attr("href",m(this).attr("href")+"&"+m.param(e))})}};m(document).ready(function(){c.init(m(".date-interval")),m('select[name="context"] .level-1').each(function(){var e=!0;m(this).nextUntil(".level-1").each(function(){if(m(this).is(":not(:disabled)"))return e=!1}),!0===e&&m(this).prop("disabled",!0)})})}),jQuery.extend({streamGetQueryVars:function(e){return(e||document.location.search).replace(/(^\?)/,"").split("&").map(function(e){return this[(e=e.split("="))[0]]=e[1],this}.bind({}))[0]}});
ui/js/alerts.min.js CHANGED
@@ -1 +1 @@
1
- jQuery(function(t){"use strict";var e,n,a=function(e){var n=t(e);n.find(".select2-select.connector_or_context").each(function(e,n){t(n).select2({allowClear:!0,placeholder:streamAlerts.anyContext,templateResult:function(e){return void 0===e.id?e.text:t(-1===e.id.indexOf("-")?'<span class="parent">'+e.text+"</span>":'<span class="child">'+e.text+"</span>")},matcher:function(e,n){var a=t.extend(!0,{},n);if(null===e.term||""===t.trim(e.term))return a;var i=e.term.toLowerCase();if(a.id=a.id.replace("blogs","sites"),a.id.toLowerCase().indexOf(i)>=0)return a;if(a.children){for(var r=a.children.length-1;r>=0;r--)-1===a.children[r].id.toLowerCase().indexOf(i)&&a.children.splice(r,1);if(a.children.length>0)return a}return null}}).change(function(){var e=t(this).val();if(e){var n=e.split("-");t(this).siblings(".connector").val(n[0]),t(this).siblings(".context").val(n[1])}});var a=[t(n).siblings(".connector").val(),t(n).siblings(".context").val()];""===a[1]&&a.splice(1,1),t(n).val(a.join("-")).trigger("change")}),n.find("select.select2-select:not(.connector_or_context)").each(function(){var e=t(this).attr("id").split("_"),n=e[e.length-1].charAt(0).toUpperCase()+e[e.length-1].slice(1);t(this).select2({allowClear:!0,placeholder:streamAlerts.any+" "+n})})},i=t("#wp_stream_alert_type"),r=function(e){var n={action:"load_alerts_settings",alert_type:e},a=t("#wp_stream_alert_type").closest("tr").attr("id");n.post_id=a.split("-")[1],t.post(window.ajaxurl,n,function(e){var n=t("#wp_stream_alert_type_form");"none"!==t("#wp_stream_alert_type").val()?(n.html(e.data.html),n.show()):n.hide()})};t("#the-list").on("change","#wp_stream_trigger_connector_or_context",function(){if("wp_stream_trigger_connector_or_context"===t(this).attr("id")){var e=t(this).val();e&&0<e.indexOf("-")&&(e=e.split("-")[0]),s(e)}});var s=function(e){var n=t("#wp_stream_trigger_action");n.empty(),n.prop("disabled",!0);var a=t("<option/>",{value:"",text:""});n.append(a);var i={action:"get_actions",connector:e};t.post(window.ajaxurl,i,function(e){var a=e.success,i=e.data;if(a){for(var r in i)if(i.hasOwnProperty(r)){var s=i[r],l=t("<option/>",{value:r,text:s});n.append(l)}n.prop("disabled",!1),t(document).trigger("alert-actions-updated")}})};i.change(function(){r(t(this).val())}),t("#wpbody-content").on("click","a.page-title-action",function(e){e.preventDefault(),t("#add-new-alert").remove(),t(".inline-edit-wp_stream_alerts").length>0&&t(".inline-edit-wp_stream_alerts .inline-edit-save button.button-secondary.cancel").trigger("click");var n="",i={action:"get_new_alert_triggers_notifications"};t.post(window.ajaxurl,i,function(e){if(!0===e.success){n=e.data.html,t("tbody#the-list").prepend('<tr id="add-new-alert" class="inline-edit-row inline-edit-row-page inline-edit-page quick-edit-row quick-edit-row-page inline-edit-page inline-editor" style=""><td colspan="4" class="colspanchange">'+n+'<p class="submit inline-edit-save"> <button type="button" class="button-secondary cancel alignleft">Cancel</button> <input type="hidden" id="_inline_edit" name="_inline_edit" value="3550d271fe"> <button type="button" class="button-primary save alignright">Save</button> <span class="spinner"></span><span class="error" style="display:none"></span> <br class="clear"></p></td></tr>');var i=t("#add-new-alert"),s=i.css("background-color");i.css("background-color","#C1E1B9"),setTimeout(function(){i.css("background-color",s)},250),t("#wp_stream_alert_type").change(function(){r(t(this).val())}),i.on("click",".button-secondary.cancel",function(){t("#add-new-alert").remove()}),i.on("click",".button-primary.save",l),a("#add-new-alert")}})});var l=function(e){e.preventDefault(),t("#add-new-alert").find("p.submit.inline-edit-save span.spinner").css("visibility","visible");var n={action:"save_new_alert",wp_stream_alerts_nonce:t("#wp_stream_alerts_nonce").val(),wp_stream_trigger_author:t("#wp_stream_trigger_author").val(),wp_stream_trigger_context:t("#wp_stream_trigger_connector_or_context").val(),wp_stream_trigger_action:t("#wp_stream_trigger_action").val(),wp_stream_alert_type:t("#wp_stream_alert_type").val(),wp_stream_alert_status:t("#wp_stream_alert_status").val()};t("#wp_stream_alert_type_form").find(":input").each(function(){var e=t(this).attr("id");t(this).val()&&(n[e]=t(this).val())}),t.post(window.ajaxurl,n,function(e){!0===e.success&&(t("#add-new-alert").find("p.submit.inline-edit-save span.spinner").css("visibility","hidden"),location.reload())})},o=inlineEditPost.edit;if(inlineEditPost.edit=function(i){o.apply(this,arguments);var r=0;if("object"==typeof i&&(r=parseInt(this.getId(i),10)),r>0){n=t("#edit-"+r);var s=(e=t("#post-"+r)).find('input[name="wp_stream_trigger_connector"]').val(),l=e.find('input[name="wp_stream_trigger_context"]').val(),c=s+"-"+l,p=e.find('input[name="wp_stream_trigger_action"]').val(),_=e.find('input[name="wp_stream_alert_status"]').val();n.find('input[name="wp_stream_trigger_connector"]').attr("value",s),n.find('input[name="wp_stream_trigger_context"]').attr("value",l),n.find('select[name="wp_stream_trigger_connector_or_context"] option[value="'+c+'"]').attr("selected","selected"),t(document).one("alert-actions-updated",function(){n.find('input[name="wp_stream_trigger_action"]').attr("value",p),n.find('select[name="wp_stream_trigger_action"] option[value="'+p+'"]').attr("selected","selected").trigger("change")}),n.find('select[name="wp_stream_alert_status"] option[value="'+_+'"]').attr("selected","selected"),a("#edit-"+r),t("#wp_stream_alert_type_form").hide();var d=e.find('input[name="wp_stream_alert_type"]').val();n.find('select[name="wp_stream_alert_type"] option[value="'+d+'"]').attr("selected","selected").trigger("change")}},window.location.hash){var c=t(window.location.hash);if(c.length){var p=c.offset().top-t("#wpadminbar").height();t("html, body").animate({scrollTop:p},1e3),c.find(".row-actions a.editinline").trigger("click")}}});
1
+ jQuery(function(o){"use strict";function c(t){var e=o(t);e.find(".select2-select.connector_or_context").each(function(t,e){o(e).select2({allowClear:!0,placeholder:streamAlerts.anyContext,templateResult:function(t){return void 0===t.id?t.text:-1===t.id.indexOf("-")?o('<span class="parent">'+t.text+"</span>"):o('<span class="child">'+t.text+"</span>")},matcher:function(t,e){var n=o.extend(!0,{},e);if(null===t.term||""===o.trim(t.term))return n;var a=t.term.toLowerCase();if(n.id=n.id.replace("blogs","sites"),0<=n.id.toLowerCase().indexOf(a))return n;if(n.children){for(var i=n.children.length-1;0<=i;i--){-1===n.children[i].id.toLowerCase().indexOf(a)&&n.children.splice(i,1)}if(0<n.children.length)return n}return null}}).change(function(){var t=o(this).val();if(t){var e=t.split("-");o(this).siblings(".connector").val(e[0]),o(this).siblings(".context").val(e[1])}});var n=[o(e).siblings(".connector").val(),o(e).siblings(".context").val()];""===n[1]&&n.splice(1,1),o(e).val(n.join("-")).trigger("change")}),e.find("select.select2-select:not(.connector_or_context)").each(function(){var t=o(this).attr("id").split("_"),e=t[t.length-1].charAt(0).toUpperCase()+t[t.length-1].slice(1);o(this).select2({allowClear:!0,placeholder:streamAlerts.any+" "+e})})}function i(t){var e={action:"load_alerts_settings",alert_type:t},n=o("#wp_stream_alert_type").closest("tr").attr("id");e.post_id=n.split("-")[1],o.post(window.ajaxurl,e,function(t){var e=o("#wp_stream_alert_type_form");"none"!==o("#wp_stream_alert_type").val()?(e.html(t.data.html),e.show()):e.hide()})}var p,_,t=o("#wp_stream_alert_type");o("#the-list").on("change","#wp_stream_trigger_connector_or_context",function(){if("wp_stream_trigger_connector_or_context"===o(this).attr("id")){var t=o(this).val();if(t&&0<t.indexOf("-"))t=t.split("-")[0];e(t)}});var e=function(t){var s=o("#wp_stream_trigger_action");s.empty(),s.prop("disabled",!0);var e=o("<option/>",{value:"",text:""});s.append(e);var n={action:"get_actions",connector:t};o.post(window.ajaxurl,n,function(t){var e=t.success,n=t.data;if(e){for(var a in n)if(n.hasOwnProperty(a)){var i=n[a],r=o("<option/>",{value:a,text:i});s.append(r)}s.prop("disabled",!1),o(document).trigger("alert-actions-updated")}})};t.change(function(){i(o(this).val())}),o("#wpbody-content").on("click","a.page-title-action",function(t){t.preventDefault(),o("#add-new-alert").remove(),0<o(".inline-edit-wp_stream_alerts").length&&o(".inline-edit-wp_stream_alerts .inline-edit-save button.button-secondary.cancel").trigger("click");var a="";o.post(window.ajaxurl,{action:"get_new_alert_triggers_notifications"},function(t){if(!0===t.success){a=t.data.html,o("tbody#the-list").prepend('<tr id="add-new-alert" class="inline-edit-row inline-edit-row-page inline-edit-page quick-edit-row quick-edit-row-page inline-edit-page inline-editor" style=""><td colspan="4" class="colspanchange">'+a+'<p class="submit inline-edit-save"> <button type="button" class="button-secondary cancel alignleft">Cancel</button> <input type="hidden" id="_inline_edit" name="_inline_edit" value="3550d271fe"> <button type="button" class="button-primary save alignright">Save</button> <span class="spinner"></span><span class="error" style="display:none"></span> <br class="clear"></p></td></tr>');var e=o("#add-new-alert"),n=e.css("background-color");e.css("background-color","#C1E1B9"),setTimeout(function(){e.css("background-color",n)},250),o("#wp_stream_alert_type").change(function(){i(o(this).val())}),e.on("click",".button-secondary.cancel",function(){o("#add-new-alert").remove()}),e.on("click",".button-primary.save",r),c("#add-new-alert")}})});var r=function(t){t.preventDefault(),o("#add-new-alert").find("p.submit.inline-edit-save span.spinner").css("visibility","visible");var e={action:"save_new_alert",wp_stream_alerts_nonce:o("#wp_stream_alerts_nonce").val(),wp_stream_trigger_author:o("#wp_stream_trigger_author").val(),wp_stream_trigger_context:o("#wp_stream_trigger_connector_or_context").val(),wp_stream_trigger_action:o("#wp_stream_trigger_action").val(),wp_stream_alert_type:o("#wp_stream_alert_type").val(),wp_stream_alert_status:o("#wp_stream_alert_status").val()};o("#wp_stream_alert_type_form").find(":input").each(function(){var t=o(this).attr("id");o(this).val()&&(e[t]=o(this).val())}),o.post(window.ajaxurl,e,function(t){!0===t.success&&(o("#add-new-alert").find("p.submit.inline-edit-save span.spinner").css("visibility","hidden"),location.reload())})},d=inlineEditPost.edit;if(inlineEditPost.edit=function(t){d.apply(this,arguments);var e=0;if("object"==typeof t&&(e=parseInt(this.getId(t),10)),0<e){_=o("#edit-"+e);var n=(p=o("#post-"+e)).find('input[name="wp_stream_trigger_connector"]').val(),a=p.find('input[name="wp_stream_trigger_context"]').val(),i=n+"-"+a,r=p.find('input[name="wp_stream_trigger_action"]').val(),s=p.find('input[name="wp_stream_alert_status"]').val();_.find('input[name="wp_stream_trigger_connector"]').attr("value",n),_.find('input[name="wp_stream_trigger_context"]').attr("value",a),_.find('select[name="wp_stream_trigger_connector_or_context"] option[value="'+i+'"]').attr("selected","selected"),o(document).one("alert-actions-updated",function(){_.find('input[name="wp_stream_trigger_action"]').attr("value",r),_.find('select[name="wp_stream_trigger_action"] option[value="'+r+'"]').attr("selected","selected").trigger("change")}),_.find('select[name="wp_stream_alert_status"] option[value="'+s+'"]').attr("selected","selected"),c("#edit-"+e),o("#wp_stream_alert_type_form").hide();var l=p.find('input[name="wp_stream_alert_type"]').val();_.find('select[name="wp_stream_alert_type"] option[value="'+l+'"]').attr("selected","selected").trigger("change")}},window.location.hash){var n=o(window.location.hash);if(n.length){var a=n.offset().top-o("#wpadminbar").height();o("html, body").animate({scrollTop:a},1e3),n.find(".row-actions a.editinline").trigger("click")}}});
ui/js/exclude.min.js CHANGED
@@ -1 +1 @@
1
- jQuery(function(e){function t(t,s){var n=e(".select2-select.action",t),i=n.val();n.empty(),n.prop("disabled",!0);var l=e("<option/>",{value:"",text:""});n.append(l);var c={action:"get_actions",connector:s};e.post(window.ajaxurl,c,function(t){var s=t.success,l=t.data;if(s){for(var c in l)if(l.hasOwnProperty(c)){var r=l[c],a=e("<option/>",{value:c,text:r});n.append(a)}n.val(i),n.prop("disabled",!1),e(document).trigger("alert-actions-updated")}})}function s(){var t=e("table.stream-exclude-list tbody tr:not( .hidden ) input.cb-select:checked"),s=e("#exclude_rules_remove_rules");0===t.length?s.prop("disabled",!0):s.prop("disabled",!1)}function n(){var t=e("table.stream-exclude-list tbody tr:not( .hidden )"),s=e("table.stream-exclude-list tbody tr.no-items"),n=e(".check-column.manage-column input.cb-select"),i=e("#exclude_rules_remove_rules");0===t.length?(s.show(),n.prop("disabled",!0),i.prop("disabled",!0)):(s.hide(),n.prop("disabled",!1)),wp_stream_regenerate_alt_rows(t)}var i=e(".stream-exclude-list tbody tr:not(.hidden)"),l=e(".stream-exclude-list tr.helper"),c=function(i){var l;e("select.select2-select.connector_or_context",i).each(function(s,n){e(n).select2({allowClear:!0,templateResult:function(t){return void 0===t.id?t.text:e(-1===t.id.indexOf("-")?'<span class="parent">'+t.text+"</span>":'<span class="child">'+t.text+"</span>")},matcher:function(t,s){var n=e.extend(!0,{},s);if(null===t.term||""===e.trim(t.term))return n;var i=t.term.toLowerCase();if(n.id=n.id.replace("blogs","sites"),n.id.toLowerCase().indexOf(i)>=0)return n;if(n.children){for(var l=n.children.length-1;l>=0;l--)-1===n.children[l].id.toLowerCase().indexOf(i)&&n.children.splice(l,1);if(n.children.length>0)return n}return null}}).on("change",function(){var s=e(this).closest("tr"),n=e(this).val();n&&0<n.indexOf("-")&&(n=n.split("-")[0]),t(s,n)})}),e("select.select2-select.action",i).each(function(t,s){e(s).select2({allowClear:!0})}),e("select.select2-select.author_or_role",i).each(function(t,s){(l=e(s)).select2({ajax:{type:"POST",url:ajaxurl,dataType:"json",quietMillis:500,data:function(e,t){return{find:e,limit:10,pager:t,action:"stream_get_users",nonce:l.data("nonce")}},processResults:function(t){var s={results:[{text:"",id:""},{text:"Roles",children:[]},{text:"Users",children:[]}]};if(!0!==t.success||void 0===t.data||!0!==t.data.status)return s;if(void 0===t.data.users||void 0===t.data.roles)return s;var n=[];return e.each(t.data.roles,function(e,t){n.push({id:e,text:t})}),s.results[1].children=n,s.results[2].children=t.data.users,s}},templateResult:function(t){var s=e("<div>").text(t.text);return void 0!==t.icon&&t.icon&&(s.prepend(e('<img src="'+t.icon+'" class="wp-stream-select2-icon">')),s.attr("title",t.tooltip)),void 0!==t.tooltip?s.attr("title",t.tooltip):void 0!==t.user_count&&s.attr("title",t.user_count),s},templateSelection:function(t){var s=e("<div>").text(t.text);return e.isNumeric(t.id)&&t.text.indexOf("icon-users")<0&&s.append(e('<i class="icon16 icon-users"></i>')),s},allowClear:!0,placeholder:l.data("placeholder")}).on("change",function(){var t=e(this).select2("data");e(this).data("selected-id",t.id),e(this).data("selected-text",t.text)})}),e("select.select2-select.ip_address",i).each(function(t,s){var n=e(s),i="";n.select2({ajax:{type:"POST",url:ajaxurl,dataType:"json",quietMillis:500,data:function(e){return i=e.term,{find:e,limit:10,action:"stream_get_ips",nonce:n.data("nonce")}},processResults:function(t){var s={results:[]},n=[];return!0===t.success&&void 0!==t.data&&e.each(t.data,function(e,t){s.results.push({id:t,text:t})}),void 0===i?s:null===(n=i.match(/^(\d{1,3})\.(\d{1,3})\.(\d{1,3})\.(\d{1,3})$/))?s:(n.shift(),(n=e.grep(n,function(e){var t=parseInt(e,10);return t<=255&&t.toString()===e})).length>=4&&s.results.push({id:i,text:i}),s)}},allowClear:!1,multiple:!0,maximumSelectionSize:1,placeholder:n.data("placeholder"),tags:!0})}).on("change",function(){e(this).prev(".select2-container").find("input.select2-input").blur()}),e("ul.select2-choices, ul.select2-choices li, input.select2-input",".stream-exclude-list tr:not(.hidden) .ip_address").on("mousedown click focus",function(){var t=e(this).closest(".select2-container"),s=t.find("input.select2-input");if(t.select2("data").length>=1)return s.blur(),!1}),e(".exclude_rules_remove_rule_row",i).on("click",function(t){e(this).closest("tr").remove(),n(),s(),t.preventDefault()})};c(i),e("select.select2-select.author_or_role",i).each(function(){var t=e("<option selected>"+e(this).data("selected-text")+"</option>").val(e(this).data("selected-id"));e(this).append(t).trigger("change")}),e("select.select2-select.connector_or_context",i).each(function(){var t=[e(this).siblings(".connector").val(),e(this).siblings(".context").val()];""===t[1]&&t.splice(1,1),e(this).val(t.join("-")).trigger("change")}),e("#exclude_rules_new_rule").on("click",function(){var e=l.clone();e.removeAttr("class"),e.insertBefore(l),c(e),n(),s()}),e("#exclude_rules_remove_rules").on("click",function(){var t=e("table.stream-exclude-list"),i=e("tbody input.cb-select:checked",t).closest("tr");e("tbody tr",t).length-i.length>=2?i.remove():(e(":input",i).val(""),e(i).not(":first").remove(),e(".select2-select",i).select2("val","")),t.find("input.cb-select").prop("checked",!1),n(),s()}),e(".stream-exclude-list").closest("form").submit(function(){e(".stream-exclude-list tbody tr.hidden",this).each(function(){e(this).find(":input").removeAttr("name")}),e(".stream-exclude-list tbody tr:not(.hidden) select.select2-select.connector_or_context",this).each(function(){var t=e(this).val().split("-");e(this).siblings(".connector").val(t[0]),e(this).siblings(".context").val(t[1]),e(this).removeAttr("name")}),e(".stream-exclude-list tbody tr:not(.hidden) select.select2-select.ip_address",this).each(function(){var t=e("option:selected",this).first();t.length||e(this).append('<option selected="selected"></option>'),e("option:selected:not(:first)",this).each(function(){t.attr("value",t.attr("value")+","+e(this).attr("value")),e(this).removeAttr("selected")})})}),e(".stream-exclude-list").closest("td").prev("th").hide(),e("table.stream-exclude-list").on("click","input.cb-select",function(){s()}),e(document).ready(function(){n(),s()})});
1
+ jQuery(function(a){function t(e){var s;a("select.select2-select.connector_or_context",e).each(function(e,t){a(t).select2({allowClear:!0,templateResult:function(e){return void 0===e.id?e.text:-1===e.id.indexOf("-")?a('<span class="parent">'+e.text+"</span>"):a('<span class="child">'+e.text+"</span>")},matcher:function(e,t){var s=a.extend(!0,{},t);if(null===e.term||""===a.trim(e.term))return s;var n=e.term.toLowerCase();if(s.id=s.id.replace("blogs","sites"),0<=s.id.toLowerCase().indexOf(n))return s;if(s.children){for(var i=s.children.length-1;0<=i;i--){-1===s.children[i].id.toLowerCase().indexOf(n)&&s.children.splice(i,1)}if(0<s.children.length)return s}return null}}).on("change",function(){var e=a(this).closest("tr"),t=a(this).val();t&&0<t.indexOf("-")&&(t=t.split("-")[0]);!function(e,t){var c=a(".select2-select.action",e),r=c.val();c.empty(),c.prop("disabled",!0);var s=a("<option/>",{value:"",text:""});c.append(s);var n={action:"get_actions",connector:t};a.post(window.ajaxurl,n,function(e){var t=e.success,s=e.data;if(t){for(var n in s)if(s.hasOwnProperty(n)){var i=s[n],l=a("<option/>",{value:n,text:i});c.append(l)}c.val(r),c.prop("disabled",!1),a(document).trigger("alert-actions-updated")}})}(e,t)})}),a("select.select2-select.action",e).each(function(e,t){a(t).select2({allowClear:!0})}),a("select.select2-select.author_or_role",e).each(function(e,t){(s=a(t)).select2({ajax:{type:"POST",url:ajaxurl,dataType:"json",quietMillis:500,data:function(e,t){return{find:e,limit:10,pager:t,action:"stream_get_users",nonce:s.data("nonce")}},processResults:function(e){var t={results:[{text:"",id:""},{text:"Roles",children:[]},{text:"Users",children:[]}]};if(!0!==e.success||void 0===e.data||!0!==e.data.status)return t;if(void 0===e.data.users||void 0===e.data.roles)return t;var s=[];return a.each(e.data.roles,function(e,t){s.push({id:e,text:t})}),t.results[1].children=s,t.results[2].children=e.data.users,t}},templateResult:function(e){var t=a("<div>").text(e.text);return void 0!==e.icon&&e.icon&&(t.prepend(a('<img src="'+e.icon+'" class="wp-stream-select2-icon">')),t.attr("title",e.tooltip)),void 0!==e.tooltip?t.attr("title",e.tooltip):void 0!==e.user_count&&t.attr("title",e.user_count),t},templateSelection:function(e){var t=a("<div>").text(e.text);return a.isNumeric(e.id)&&e.text.indexOf("icon-users")<0&&t.append(a('<i class="icon16 icon-users"></i>')),t},allowClear:!0,placeholder:s.data("placeholder")}).on("change",function(){var e=a(this).select2("data");a(this).data("selected-id",e.id),a(this).data("selected-text",e.text)})}),a("select.select2-select.ip_address",e).each(function(e,t){var s=a(t),n="";s.select2({ajax:{type:"POST",url:ajaxurl,dataType:"json",quietMillis:500,data:function(e){return n=e.term,{find:e,limit:10,action:"stream_get_ips",nonce:s.data("nonce")}},processResults:function(e){var s={results:[]},t=[];return!0===e.success&&void 0!==e.data&&a.each(e.data,function(e,t){s.results.push({id:t,text:t})}),void 0===n||null===(t=n.match(/^(\d{1,3})\.(\d{1,3})\.(\d{1,3})\.(\d{1,3})$/))||(t.shift(),4<=(t=a.grep(t,function(e){var t=parseInt(e,10);return t<=255&&t.toString()===e})).length&&s.results.push({id:n,text:n})),s}},allowClear:!1,multiple:!0,maximumSelectionSize:1,placeholder:s.data("placeholder"),tags:!0})}).on("change",function(){a(this).prev(".select2-container").find("input.select2-input").blur()}),a("ul.select2-choices, ul.select2-choices li, input.select2-input",".stream-exclude-list tr:not(.hidden) .ip_address").on("mousedown click focus",function(){var e=a(this).closest(".select2-container"),t=e.find("input.select2-input");if(1<=e.select2("data").length)return t.blur(),!1}),a(".exclude_rules_remove_rule_row",e).on("click",function(e){a(this).closest("tr").remove(),i(),n(),e.preventDefault()})}var e=a(".stream-exclude-list tbody tr:not(.hidden)"),s=a(".stream-exclude-list tr.helper");function n(){var e=a("table.stream-exclude-list tbody tr:not( .hidden ) input.cb-select:checked"),t=a("#exclude_rules_remove_rules");0===e.length?t.prop("disabled",!0):t.prop("disabled",!1)}function i(){var e=a("table.stream-exclude-list tbody tr:not( .hidden )"),t=a("table.stream-exclude-list tbody tr.no-items"),s=a(".check-column.manage-column input.cb-select"),n=a("#exclude_rules_remove_rules");0===e.length?(t.show(),s.prop("disabled",!0),n.prop("disabled",!0)):(t.hide(),s.prop("disabled",!1)),wp_stream_regenerate_alt_rows(e)}t(e),a("select.select2-select.author_or_role",e).each(function(){var e=a("<option selected>"+a(this).data("selected-text")+"</option>").val(a(this).data("selected-id"));a(this).append(e).trigger("change")}),a("select.select2-select.connector_or_context",e).each(function(){var e=[a(this).siblings(".connector").val(),a(this).siblings(".context").val()];""===e[1]&&e.splice(1,1),a(this).val(e.join("-")).trigger("change")}),a("#exclude_rules_new_rule").on("click",function(){var e=s.clone();e.removeAttr("class"),e.insertBefore(s),t(e),i(),n()}),a("#exclude_rules_remove_rules").on("click",function(){var e=a("table.stream-exclude-list"),t=a("tbody input.cb-select:checked",e).closest("tr");2<=a("tbody tr",e).length-t.length?t.remove():(a(":input",t).val(""),a(t).not(":first").remove(),a(".select2-select",t).select2("val","")),e.find("input.cb-select").prop("checked",!1),i(),n()}),a(".stream-exclude-list").closest("form").submit(function(){a(".stream-exclude-list tbody tr.hidden",this).each(function(){a(this).find(":input").removeAttr("name")}),a(".stream-exclude-list tbody tr:not(.hidden) select.select2-select.connector_or_context",this).each(function(){var e=a(this).val().split("-");a(this).siblings(".connector").val(e[0]),a(this).siblings(".context").val(e[1]),a(this).removeAttr("name")}),a(".stream-exclude-list tbody tr:not(.hidden) select.select2-select.ip_address",this).each(function(){var e=a("option:selected",this).first();e.length||a(this).append('<option selected="selected"></option>'),a("option:selected:not(:first)",this).each(function(){e.attr("value",e.attr("value")+","+a(this).attr("value")),a(this).removeAttr("selected")})})}),a(".stream-exclude-list").closest("td").prev("th").hide(),a("table.stream-exclude-list").on("click","input.cb-select",function(){n()}),a(document).ready(function(){i(),n()})});
ui/js/global.min.js CHANGED
@@ -1 +1 @@
1
- jQuery(function(t){function e(t){window.confirm(wp_stream_global.bulk_actions.i18n.confirm_action)||t.preventDefault()}t('.actions :submit:not([name="filter_action"])').on("click",function(n){t("table.widefat tbody :checkbox:checked").length>wp_stream_global.bulk_actions.threshold&&e(n)}),t("#delete_all").on("click",function(n){parseInt(t("ul.subsubsub li.trash .count").text().replace(/\D/g,""),10)>wp_stream_global.bulk_actions.threshold&&e(n)})});var wp_stream_regenerate_alt_rows=function(t){if(!t.length)return!1;t.removeClass("alternate"),t.each(function(t){jQuery(this).addClass(t%2?"":"alternate")})};
1
+ jQuery(function(e){function n(t){window.confirm(wp_stream_global.bulk_actions.i18n.confirm_action)||t.preventDefault()}e('.actions :submit:not([name="filter_action"])').on("click",function(t){e("table.widefat tbody :checkbox:checked").length>wp_stream_global.bulk_actions.threshold&&n(t)}),e("#delete_all").on("click",function(t){parseInt(e("ul.subsubsub li.trash .count").text().replace(/\D/g,""),10)>wp_stream_global.bulk_actions.threshold&&n(t)})});var wp_stream_regenerate_alt_rows=function(t){if(!t.length)return!1;t.removeClass("alternate"),t.each(function(t){jQuery(this).addClass(t%2?"":"alternate")})};
ui/js/live-updates.min.js CHANGED
@@ -1 +1 @@
1
- jQuery(function(e){e(document).ready(function(){if("toplevel_page_wp_stream"===wp_stream_live_updates.current_screen&&"1"===wp_stream_live_updates.current_page&&"asc"!==wp_stream_live_updates.current_order&&!(parseInt(wp_stream_live_updates.current_query_count,10)>1)){var t=".toplevel_page_wp_stream #the-list";wp.heartbeat.interval("fast"),e(document).on("heartbeat-send.stream",function(a,r){r["wp-stream-heartbeat"]="live-update";var s=e(t+" tr:first .column-date time"),n=1;0!==s.length&&(n=""===s.attr("datetime")?1:s.attr("datetime")),r["wp-stream-heartbeat-last-time"]=n,r["wp-stream-heartbeat-query"]=wp_stream_live_updates.current_query}),e(document).on("heartbeat-tick.stream",function(a,r){if(r["wp-stream-heartbeat"]&&0!==r["wp-stream-heartbeat"].length){var s=e("#edit_stream_per_page").val(),n=e(t+" tr"),l=e(r["wp-stream-heartbeat"]);l.addClass("new-row");var p=n.first().hasClass("alternate");if(1!==l.length||p){var i=0!=l.length%2||p?"odd":"even";l.filter(":nth-child("+i+")").addClass("alternate")}else l.addClass("alternate");e(t).prepend(l),e(".metabox-prefs input").each(function(){if(!0!==e(this).prop("checked")){var t=e(this).val();e("td.column-"+t).hide()}});var _=s-(l.length+n.length);_<0&&e(t+" tr").slice(_).remove(),e(t+" tr.no-items").remove();var d=r.total_items_i18n||"";d&&(e(".displaying-num").text(d),e(".total-pages").text(r.total_pages_i18n),e(".tablenav-pages").find(".next-page, .last-page").toggleClass("disabled",r.total_pages===e(".current-page").val()),e(".tablenav-pages .last-page").attr("href",r.last_page_link)),e(t).parent().trigger("updated"),wp_stream_regenerate_alt_rows(e(t+" tr")),setTimeout(function(){e(".new-row").addClass("fadeout"),setTimeout(function(){e(t+" tr").removeClass("new-row fadeout")},500)},3e3)}})}})});
1
+ jQuery(function(d){d(document).ready(function(){if("toplevel_page_wp_stream"===wp_stream_live_updates.current_screen&&"1"===wp_stream_live_updates.current_page&&"asc"!==wp_stream_live_updates.current_order&&!(1<parseInt(wp_stream_live_updates.current_query_count,10))){var _=".toplevel_page_wp_stream #the-list";wp.heartbeat.interval("fast"),d(document).on("heartbeat-send.stream",function(e,t){t["wp-stream-heartbeat"]="live-update";var a=d(_+" tr:first .column-date time"),r=1;0!==a.length&&(r=""===a.attr("datetime")?1:a.attr("datetime")),t["wp-stream-heartbeat-last-time"]=r,t["wp-stream-heartbeat-query"]=wp_stream_live_updates.current_query}),d(document).on("heartbeat-tick.stream",function(e,t){if(t["wp-stream-heartbeat"]&&0!==t["wp-stream-heartbeat"].length){var a=d("#edit_stream_per_page").val(),r=d(_+" tr"),s=d(t["wp-stream-heartbeat"]);s.addClass("new-row");var n=r.first().hasClass("alternate");if(1!==s.length||n){var l=0!=s.length%2||n?"odd":"even";s.filter(":nth-child("+l+")").addClass("alternate")}else s.addClass("alternate");d(_).prepend(s),d(".metabox-prefs input").each(function(){if(!0!==d(this).prop("checked")){var e=d(this).val();d("td.column-"+e).hide()}});var p=a-(s.length+r.length);p<0&&d(_+" tr").slice(p).remove(),d(_+" tr.no-items").remove();var i=t.total_items_i18n||"";i&&(d(".displaying-num").text(i),d(".total-pages").text(t.total_pages_i18n),d(".tablenav-pages").find(".next-page, .last-page").toggleClass("disabled",t.total_pages===d(".current-page").val()),d(".tablenav-pages .last-page").attr("href",t.last_page_link)),d(_).parent().trigger("updated"),wp_stream_regenerate_alt_rows(d(_+" tr")),setTimeout(function(){d(".new-row").addClass("fadeout"),setTimeout(function(){d(_+" tr").removeClass("new-row fadeout")},500)},3e3)}})}})});
ui/js/settings.min.js CHANGED
@@ -1 +1 @@
1
- jQuery(function(e){function a(){t.is(":checked")?(r.addClass("hidden"),i.addClass("hidden")):(r.removeClass("hidden"),i.removeClass("hidden"))}var n;n="wp_stream_network"===e('input[name="option_page"]').val()?"_network_affix":"";var t=e("#wp_stream"+n+"\\[general_keep_records_indefinitely\\]"),i=e("#wp_stream"+n+"_general_records_ttl"),r=i.closest("tr");t.on("change",function(){a()}),a(),e("#wp_stream_general_reset_site_settings").click(function(e){confirm(wp_stream.i18n.confirm_defaults)||e.preventDefault()});var o=e(".nav-tab-wrapper"),s=e(".nav-tab-content table.form-table"),c=o.find(".nav-tab-active"),l=c.length>0?o.find("a").index(c):0,d=window.location.hash.match(/^#(\d+)$/),h=null!==d?d[1]:l,_=function(a){var n=e('input[name="option_page"][value^="wp_stream"]').closest("form");if(0!==n.length){var t=n.attr("action");n.prop("action",t.replace(/(^[^#]*).*$/,"$1#"+a))}};o.on("click","a",function(){var a=o.find("a").index(e(this)),n=window.location.hash.match(/^#(\d+)$/);return s.hide().eq(a).show(),o.find("a").removeClass("nav-tab-active").filter(e(this)).addClass("nav-tab-active"),""!==window.location.hash&&null===n||(window.location.hash=a),_(a),!1}),o.children().eq(h).trigger("click")});
1
+ jQuery(function(t){var e;e="wp_stream_network"===t('input[name="option_page"]').val()?"_network_affix":"";var a=t("#wp_stream"+e+"\\[general_keep_records_indefinitely\\]"),n=t("#wp_stream"+e+"_general_records_ttl"),i=n.closest("tr");function r(){a.is(":checked")?(i.addClass("hidden"),n.addClass("hidden")):(i.removeClass("hidden"),n.removeClass("hidden"))}a.on("change",function(){r()}),r(),t("#wp_stream_general_reset_site_settings").click(function(e){confirm(wp_stream.i18n.confirm_defaults)||e.preventDefault()});var o=t(".nav-tab-wrapper"),s=t(".nav-tab-content table.form-table"),c=o.find(".nav-tab-active"),l=0<c.length?o.find("a").index(c):0,d=window.location.hash.match(/^#(\d+)$/),h=null!==d?d[1]:l;o.on("click","a",function(){var e=o.find("a").index(t(this)),a=window.location.hash.match(/^#(\d+)$/);return s.hide().eq(e).show(),o.find("a").removeClass("nav-tab-active").filter(t(this)).addClass("nav-tab-active"),""!==window.location.hash&&null===a||(window.location.hash=e),function(e){var a=t('input[name="option_page"][value^="wp_stream"]').closest("form");if(0!==a.length){var n=a.attr("action");a.prop("action",n.replace(/(^[^#]*).*$/,"$1#"+e))}}(e),!1}),o.children().eq(h).trigger("click")});