PluginProbe
Stream – Activity Log & Audit Trail / 3.7.0
Stream – Activity Log & Audit Trail v3.7.0
4.4.0 4.3.0 4.2.2 4.2.1 trunk 2.0.1 2.0.2 2.0.3 2.0.4 2.0.5 3.0.0 3.0.1 3.0.2 3.0.3 3.0.4 3.0.5 3.0.6 3.0.7 3.1 3.1.1 3.10.0 3.2.0 3.2.1 3.2.2 3.2.3 All 50 releases
← All changes | classes/class-settings.php +65 -336 trunk3.7.0 View file →
@@ -6,11 +6,11 @@
6 6 */
7 7
8 8 namespace WP_Stream;
9 9
10 -use WP_Roles;
11 -use WP_User;
12 -use WP_User_Query;
10 +use \WP_Roles;
11 +use \WP_User;
12 +use \WP_User_Query;
13 13
14 14 /**
15 15 * Class - Settings
16 16 */
@@ -111,9 +111,9 @@
111 111
112 112 $search = '';
113 113 $input = wp_stream_filter_input( INPUT_POST, 'find' );
114 114
115 - if ( isset( $input['term'] ) ) {
115 + if ( ! isset( $input['term'] ) ) {
116 116 $search = wp_unslash( trim( $input['term'] ) );
117 117 }
118 118
119 119 $request = (object) array(
@@ -354,10 +354,24 @@
354 354 'desc' => esc_html__( 'WordPress will automatically prevent duplicate comments from flooding the database. By default, Stream does not track these attempts unless you opt-in here. Enabling this is not necessary or recommended for most sites.', 'stream' ),
355 355 'after_field' => esc_html__( 'Enabled', 'stream' ),
356 356 'default' => 0,
357 357 ),
358 - $this->build_delete_all_records_field(),
359 - $this->build_clean_orphan_meta_field(),
358 + array(
359 + 'name' => 'delete_all_records',
360 + 'title' => esc_html__( 'Reset Stream Database', 'stream' ),
361 + 'type' => 'link',
362 + 'href' => add_query_arg(
363 + array(
364 + 'action' => 'wp_stream_reset',
365 + 'wp_stream_nonce_reset' => wp_create_nonce( 'stream_nonce_reset' ),
366 + ),
367 + admin_url( 'admin-ajax.php' )
368 + ),
369 + 'class' => 'warning',
370 + 'desc' => esc_html__( 'Warning: This will delete all activity records from the database.', 'stream' ),
371 + 'default' => 0,
372 + 'sticky' => 'bottom',
373 + ),
360 374 ),
361 375 ),
362 376 );
363 377
@@ -385,33 +399,8 @@
385 399 );
386 400
387 401 array_push( $fields['advanced']['fields'], $wp_cron_tracking );
388 402
389 - // Abilities API toggle is only meaningful on WordPress 6.9+. On
390 - // network-activated multisite, Abilities::is_enabled() reads the
391 - // network option (wp_stream_network), so a per-site checkbox on the
392 - // site's own settings screen would be a no-op and misleading. Hide
393 - // the field from per-site settings pages, but keep it available in
394 - // network admin and in REST/CLI contexts where update_all_setting_values()
395 - // routes writes to the network option correctly.
396 - $hide_per_site = $this->plugin->is_network_activated() && is_admin() && ! is_network_admin();
397 -
398 - if (
399 - class_exists( '\WP_Ability' )
400 - && ! $hide_per_site
401 - ) {
402 - $enable_abilities_api = array(
403 - 'name' => 'enable_abilities_api',
404 - 'title' => esc_html__( 'Enable Abilities API and MCP', 'stream' ),
405 - 'type' => 'checkbox',
406 - 'desc' => esc_html__( 'Expose Stream operations to AI agents via the WordPress Abilities API (and MCP when the MCP Adapter plugin is installed). Requires WordPress 6.9.', 'stream' ),
407 - 'after_field' => esc_html__( 'Enabled', 'stream' ),
408 - 'default' => 0,
409 - );
410 -
411 - array_push( $fields['advanced']['fields'], $enable_abilities_api );
412 - }
413 -
414 403 /**
415 404 * Filter allows for modification of options fields
416 405 *
417 406 * @return array Array of option fields
@@ -438,170 +427,8 @@
438 427 return $this->fields;
439 428 }
440 429
441 430 /**
442 - * Build the "Reset Stream Database" settings field definition.
443 - *
444 - * Extracted so the async-deletion running-state check
445 - * ({@see Admin::is_running_async_deletion()}) is evaluated once per render
446 - * instead of once per field property, and only in admin context.
447 - *
448 - * `Settings::__construct` populates `$this->options = $this->get_options()`
449 - * on the `init` hook for every pageload, which walks `get_fields()`. The
450 - * field is only ever rendered in admin, so outside admin the dynamic state
451 - * is irrelevant and the Action Scheduler query is skipped entirely.
452 - *
453 - * @return array
454 - */
455 - private function build_delete_all_records_field() {
456 - $is_running_deletion = is_admin() ? Admin::is_running_async_deletion() : false;
457 -
458 - return array(
459 - 'name' => 'delete_all_records',
460 - 'title' => esc_html__( 'Reset Stream Database', 'stream' ),
461 - 'type' => $is_running_deletion ? 'none' : 'link',
462 - 'href' => add_query_arg(
463 - array(
464 - 'action' => 'wp_stream_reset',
465 - 'wp_stream_nonce_reset' => wp_create_nonce( 'stream_nonce_reset' ),
466 - ),
467 - admin_url( 'admin-ajax.php' )
468 - ),
469 - 'class' => 'warning',
470 - 'desc' => esc_html( $this->get_deletion_warning( $is_running_deletion ) ),
471 - 'default' => 0,
472 - 'sticky' => 'bottom',
473 - );
474 - }
475 -
476 - /**
477 - * Build the "Clean Orphaned Meta" settings field definition.
478 - *
479 - * Extracted so the auto-purge running-state check
480 - * ({@see Admin::is_running_auto_purge()}) is evaluated once per render
481 - * instead of once per field property, and only in admin context — the
482 - * field is never rendered outside admin, so the Action Scheduler query
483 - * is skipped on front-end pageloads.
484 - *
485 - * @return array
486 - */
487 - private function build_clean_orphan_meta_field() {
488 - $is_running = is_admin() ? Admin::is_running_auto_purge() : false;
489 -
490 - return array(
491 - 'name' => 'clean_orphan_meta',
492 - 'title' => esc_html__( 'Clean Orphaned Meta', 'stream' ),
493 - 'type' => $is_running ? 'none' : 'link',
494 - 'href' => add_query_arg(
495 - array(
496 - 'action' => 'wp_stream_clean_orphan_meta',
497 - 'wp_stream_nonce_clean_orphan_meta' => wp_create_nonce( 'stream_nonce_clean_orphan_meta' ),
498 - ),
499 - admin_url( 'admin-ajax.php' )
500 - ),
501 - 'desc' => $is_running
502 - ? esc_html__( 'Auto-purge is currently running. The orphan reaper will execute as part of that cycle; the manual cleanup link is hidden to avoid duplicating the work.', 'stream' )
503 - : esc_html__( 'Schedules an immediate background cleanup of stream_meta rows whose parent record is missing. Safe to run while Stream is in use; runs once via Action Scheduler.', 'stream' ),
504 - 'default' => 0,
505 - 'sticky' => 'bottom',
506 - );
507 - }
508 -
509 - /**
510 - * Returns a single setting value, reading the network-level option when
511 - * Stream is network-activated on multisite.
512 - *
513 - * Settings::get_options() only loads from get_site_option() inside
514 - * is_network_admin() screens. In REST and frontend contexts on a
515 - * network-activated install, $this->options reflects the (typically empty)
516 - * per-site option, which would silently mask a network-admin-controlled
517 - * setting. This accessor handles that case so callers don't have to
518 - * duplicate the multisite branching.
519 - *
520 - * @param string $key Fully-qualified setting key (e.g. "advanced_enable_abilities_api").
521 - * @param mixed $default_value Value returned when the setting is not present.
522 - *
523 - * @return mixed
524 - */
525 - public function get_setting_value( $key, $default_value = null ) {
526 - if (
527 - is_multisite()
528 - && isset( $this->plugin )
529 - && $this->plugin->is_network_activated()
530 - ) {
531 - $options = (array) get_site_option( $this->network_options_key, array() );
532 - } else {
533 - $options = (array) $this->options;
534 - }
535 -
536 - return isset( $options[ $key ] ) ? $options[ $key ] : $default_value;
537 - }
538 -
539 - /**
540 - * Returns the full options array, reading the network-level option when
541 - * Stream is network-activated on multisite. Mirrors get_setting_value()
542 - * but returns the entire array.
543 - *
544 - * @return array
545 - */
546 - public function get_all_setting_values() {
547 - if (
548 - is_multisite()
549 - && isset( $this->plugin )
550 - && $this->plugin->is_network_activated()
551 - ) {
552 - return (array) get_site_option( $this->network_options_key, array() );
553 - }
554 -
555 - return (array) $this->options;
556 - }
557 -
558 - /**
559 - * Persists the options array, writing to the network-level option when
560 - * Stream is network-activated on multisite. Used by REST/ability writers
561 - * which run outside is_network_admin() but must respect the authoritative
562 - * store. Refreshes $this->options afterwards so in-request reads see the
563 - * new values.
564 - *
565 - * @param array $options Full options array to persist (caller is responsible
566 - * for merging over existing values when desired).
567 - *
568 - * @return bool True on a successful write, false on no-op or failure.
569 - */
570 - public function update_all_setting_values( array $options ) {
571 - $is_network = (
572 - is_multisite()
573 - && isset( $this->plugin )
574 - && $this->plugin->is_network_activated()
575 - );
576 -
577 - if ( $is_network ) {
578 - $result = update_site_option( $this->network_options_key, $options );
579 - } else {
580 - $result = update_option( $this->option_key, $options );
581 - }
582 -
583 - // Refresh the in-memory copy so subsequent reads in the same request
584 - // see the updated values. On network-activated installs we re-read
585 - // from the network option directly because Settings::get_options()
586 - // gates on is_network_admin() and would return the (now-stale)
587 - // per-site option in REST contexts. Merge defaults on top so callers
588 - // reading $plugin->settings->options keep seeing a fully-populated
589 - // array (matches get_options()'s historical contract).
590 - if ( $is_network ) {
591 - $defaults = $this->get_defaults( $this->option_key );
592 - $this->options = wp_parse_args(
593 - (array) get_site_option( $this->network_options_key, array() ),
594 - $defaults
595 - );
596 - } else {
597 - $this->options = $this->get_options();
598 - }
599 -
600 - return (bool) $result;
601 - }
602 -
603 - /**
604 431 * Returns a list of options based on the current screen.
605 432 *
606 433 * @return array
607 434 */
@@ -644,47 +471,8 @@
644 471 return (array) $defaults;
645 472 }
646 473
647 474 /**
648 - * Retrieves the deletion warning message based on the site type
649 - * and whether or not there is currently a process running to delete the tables.
650 - *
651 - * @param bool|null $is_running_deletion Optional pre-computed deletion state.
652 - * Pass to avoid a duplicate Action Scheduler
653 - * query when the caller has already checked.
654 - * Defaults to checking only in admin context.
655 - * Untyped parameter to remain compatible with
656 - * phpcs.xml.dist testVersion=7.0- (nullable
657 - * type declarations require PHP 7.1+).
658 - * @return string The deletion warning message.
659 - */
660 - public function get_deletion_warning( $is_running_deletion = null ): string {
661 -
662 - if ( null === $is_running_deletion ) {
663 - $is_running_deletion = is_admin() ? Admin::is_running_async_deletion() : false;
664 - }
665 -
666 - if ( $is_running_deletion ) {
667 -
668 - $warning = __( 'Currently deleting records. Please be patient, this can take a while.', 'stream' );
669 -
670 - } elseif ( $this->plugin->is_multisite_network_activated() ) {
671 -
672 - $warning = __( 'Warning: This will delete all activity records from the database for all sites.', 'stream' );
673 -
674 - } elseif ( $this->plugin->is_multisite_not_network_activated() ) {
675 -
676 - $warning = __( 'Warning: This will delete all activity records from the database for this site.', 'stream' );
677 -
678 - } else {
679 -
680 - $warning = __( 'Warning: This will delete all activity records from the database.', 'stream' );
681 - }
682 -
683 - return $warning;
684 - }
685 -
686 - /**
687 475 * Registers settings fields and sections
688 476 *
689 477 * @return void
690 478 */
@@ -725,8 +513,9 @@
725 513 $section_name,
726 514 $field + array(
727 515 'section' => $section_name,
728 516 'label_for' => sprintf( '%s_%s_%s', $this->option_key, $section_name, $field['name'] ),
517 + // xss ok.
729 518 )
730 519 );
731 520 }
732 521 }
@@ -755,50 +544,35 @@
755 544 if ( empty( $type ) || ! isset( $input[ $name ] ) || '' === $input[ $name ] ) {
756 545 continue;
757 546 }
758 547
759 - $output[ $name ] = $this->sanitize_setting_by_field_type( $input[ $name ], $type );
760 - }
761 - }
548 + // Sanitize depending on the type of field.
549 + switch ( $type ) {
550 + case 'number':
551 + $output[ $name ] = is_numeric( $input[ $name ] ) ? intval( trim( $input[ $name ] ) ) : '';
552 + break;
553 + case 'checkbox':
554 + $output[ $name ] = is_numeric( $input[ $name ] ) ? absint( trim( $input[ $name ] ) ) : '';
555 + break;
556 + default:
557 + if ( is_array( $input[ $name ] ) ) {
558 + $output[ $name ] = $input[ $name ];
762 559
763 - return $output;
764 - }
765 -
766 - /**
767 - * Sanitizes a setting value based on the field type.
768 - *
769 - * @param mixed $value The value to be sanitized.
770 - * @param string $field_type The type of field.
771 - *
772 - * @return mixed The sanitized value.
773 - */
774 - public function sanitize_setting_by_field_type( $value, $field_type ) {
775 -
776 - // Sanitize depending on the type of field.
777 - switch ( $field_type ) {
778 - case 'number':
779 - $sanitized_value = is_numeric( $value ) ? intval( trim( $value ) ) : '';
780 - break;
781 - case 'checkbox':
782 - $sanitized_value = is_numeric( $value ) ? absint( trim( $value ) ) : '';
783 - break;
784 - default:
785 - if ( is_array( $value ) ) {
786 - $sanitized_value = $value;
787 -
788 - // Support all values in multidimentional arrays too.
789 - array_walk_recursive(
790 - $sanitized_value,
791 - function ( &$v ) {
792 - $v = sanitize_text_field( trim( $v ) );
560 + // Support all values in multidimentional arrays too.
561 + array_walk_recursive(
562 + $output[ $name ],
563 + function ( &$v ) {
564 + $v = sanitize_text_field( trim( $v ) );
565 + }
566 + );
567 + } else {
568 + $output[ $name ] = sanitize_text_field( trim( $input[ $name ] ) );
793 569 }
794 - );
795 - } else {
796 - $sanitized_value = sanitize_text_field( trim( $value ) );
797 570 }
571 + }
798 572 }
799 573
800 - return $sanitized_value;
574 + return $output;
801 575 }
802 576
803 577 /**
804 578 * Compile HTML needed for displaying the field
@@ -827,12 +601,14 @@
827 601 $nonce = isset( $field['nonce'] ) ? $field['nonce'] : null;
828 602
829 603 if ( isset( $field['value'] ) ) {
830 604 $current_value = $field['value'];
831 - } elseif ( isset( $this->options[ $section . '_' . $name ] ) ) {
605 + } else {
606 + if ( isset( $this->options[ $section . '_' . $name ] ) ) {
832 607 $current_value = $this->options[ $section . '_' . $name ];
833 - } else {
834 - $current_value = null;
608 + } else {
609 + $current_value = null;
610 + }
835 611 }
836 612
837 613 $option_key = $this->option_key;
838 614
@@ -979,16 +755,8 @@
979 755 esc_attr( $href ),
980 756 esc_attr( $title )
981 757 );
982 758 break;
983 - case 'none':
984 - // Intentional no-op: callers set 'none' to hide a control's value
985 - // column while still letting the row label + description render
986 - // (e.g. Reset Stream Database while a deletion is running, or
987 - // Clean Orphaned Meta while the auto-purge chain is active).
988 - // The description string carries the running-state message.
989 - $output = '';
990 - break;
991 759 case 'select2':
992 760 if ( ! isset( $current_value ) ) {
993 761 $current_value = '';
994 762 }
@@ -1034,9 +802,9 @@
1034 802 '<input type="hidden" name="%1$s[%2$s_%3$s]" data-values=\'%4$s\' value="%5$s" class="select2-select %6$s" data-placeholder="%7$s" />',
1035 803 esc_attr( $option_key ),
1036 804 esc_attr( $section ),
1037 805 esc_attr( $name ),
1038 - esc_attr( wp_json_encode( $data_values ) ),
806 + esc_attr( wp_stream_json_encode( $data_values ) ),
1039 807 esc_attr( $current_value ),
1040 808 esc_attr( $class ),
1041 809 /* translators: %s: the title of the dropdown menu (e.g. "users") */
1042 810 sprintf( esc_html__( 'Any %s', 'stream' ), $title )
@@ -1138,17 +906,15 @@
1138 906 array(
1139 907 'name' => esc_attr( sprintf( '%1$s[%2$s_%3$s][%4$s][]', $option_key, $section, $name, 'author_or_role' ) ),
1140 908 'options' => $author_or_role_values,
1141 909 'classes' => 'author_or_role',
1142 - // Data attributes are escaped in Form_Generator::prepare_data_attributes_string().
1143 910 'data' => array(
1144 - 'placeholder' => __( 'Any Author or Role', 'stream' ),
1145 - 'nonce' => wp_create_nonce( 'stream_get_users' ),
1146 - 'selected-id' => isset( $author_or_role_selected['value'] ) ? $author_or_role_selected['value'] : '',
1147 - 'selected-text' => isset( $author_or_role_selected['text'] ) ? $author_or_role_selected['text'] : '',
911 + 'placeholder' => esc_html__( 'Any Author or Role', 'stream' ),
912 + 'nonce' => esc_attr( wp_create_nonce( 'stream_get_users' ) ),
913 + 'selected-id' => isset( $author_or_role_selected['value'] ) ? esc_attr( $author_or_role_selected['value'] ) : '',
914 + 'selected-text' => isset( $author_or_role_selected['text'] ) ? esc_attr( $author_or_role_selected['text'] ) : '',
1148 915 ),
1149 - ),
1150 - false
916 + )
1151 917 );
1152 918
1153 919 // Context dropdown menu.
1154 920 $context_values = array();
@@ -1186,15 +952,13 @@
1186 952 array(
1187 953 'name' => esc_attr( sprintf( '%1$s[%2$s_%3$s][%4$s][]', $option_key, $section, $name, 'connector_or_context' ) ),
1188 954 'options' => $context_values,
1189 955 'classes' => 'connector_or_context',
1190 - // Data attributes are escaped in Form_Generator::prepare_data_attributes_string().
1191 956 'data' => array(
1192 957 'group' => 'connector',
1193 958 'placeholder' => __( 'Any Context', 'stream' ),
1194 959 ),
1195 - ),
1196 - false
960 + )
1197 961 );
1198 962
1199 963 $connector_input = $form->render_field(
1200 964 'hidden',
@@ -1201,10 +965,9 @@
1201 965 array(
1202 966 'name' => esc_attr( sprintf( '%1$s[%2$s_%3$s][%4$s][]', $option_key, $section, $name, 'connector' ) ),
1203 967 'value' => $connector,
1204 968 'classes' => 'connector',
1205 - ),
1206 - false
969 + )
1207 970 );
1208 971
1209 972 $context_input = $form->render_field(
1210 973 'hidden',
@@ -1211,10 +974,9 @@
1211 974 array(
1212 975 'name' => esc_attr( sprintf( '%1$s[%2$s_%3$s][%4$s][]', $option_key, $section, $name, 'context' ) ),
1213 976 'value' => $context,
1214 977 'classes' => 'context',
1215 - ),
1216 - false
978 + )
1217 979 );
1218 980
1219 981 // Action dropdown menu.
1220 982 $action_values = array();
@@ -1232,14 +994,12 @@
1232 994 'name' => esc_attr( sprintf( '%1$s[%2$s_%3$s][%4$s][]', $option_key, $section, $name, 'action' ) ),
1233 995 'value' => $action,
1234 996 'options' => $action_values,
1235 997 'classes' => 'action',
1236 - // Data attributes are escaped in Form_Generator::prepare_data_attributes_string().
1237 998 'data' => array(
1238 999 'placeholder' => __( 'Any Action', 'stream' ),
1239 1000 ),
1240 - ),
1241 - false
1001 + )
1242 1002 );
1243 1003
1244 1004 // IP Address input.
1245 1005 $ip_address_input = $form->render_field(
@@ -1247,16 +1007,14 @@
1247 1007 array(
1248 1008 'name' => esc_attr( sprintf( '%1$s[%2$s_%3$s][%4$s][]', $option_key, $section, $name, 'ip_address' ) ),
1249 1009 'value' => $ip_address,
1250 1010 'classes' => 'ip_address',
1251 - // Data attributes are escaped in Form_Generator::prepare_data_attributes_string().
1252 1011 'data' => array(
1253 - 'placeholder' => __( 'Any IP Address', 'stream' ),
1254 - 'nonce' => wp_create_nonce( 'stream_get_ips' ),
1012 + 'placeholder' => esc_attr__( 'Any IP Address', 'stream' ),
1013 + 'nonce' => esc_attr( wp_create_nonce( 'stream_get_ips' ) ),
1255 1014 ),
1256 1015 'multiple' => true,
1257 - ),
1258 - false
1016 + )
1259 1017 );
1260 1018
1261 1019 // Hidden helper input.
1262 1020 $helper_input = sprintf(
@@ -1273,11 +1031,9 @@
1273 1031 <td>%5$s</td>
1274 1032 <td>%6$s %7$s %8$s</td>
1275 1033 <td>%9$s</td>
1276 1034 <td>%10$s</td>
1277 - <th scope="row" class="actions-column">
1278 - <a href="#" class="exclude_rules_remove_rule_row">%11$s</a>
1279 - </th>
1035 + <th scope="row" class="actions-column">%11$s</th>
1280 1036 </tr>',
1281 1037 ( 0 !== (int) $key % 2 ) ? 'alternate' : '',
1282 1038 ( 'helper' === (string) $key ) ? 'hidden helper' : '',
1283 1039 '<input class="cb-select" type="checkbox" />',
@@ -1287,9 +1043,9 @@
1287 1043 $connector_input,
1288 1044 $context_input,
1289 1045 $action_input,
1290 1046 $ip_address_input,
1291 - esc_html__( 'Delete', 'stream' )
1047 + '<a href="#" class="exclude_rules_remove_rule_row">Delete</a>'
1292 1048 );
1293 1049 }
1294 1050
1295 1051 $no_rules_found_row = sprintf(
@@ -1327,9 +1083,9 @@
1327 1083 }
1328 1084
1329 1085 $output = $this->render_field( $field );
1330 1086
1331 - echo $output; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
1087 + echo $output; // xss ok.
1332 1088 }
1333 1089
1334 1090 /**
1335 1091 * Get an array of user roles
@@ -1393,38 +1149,11 @@
1393 1149 $ttl_after = isset( $new_value['general_records_ttl'] ) ? (int) $new_value['general_records_ttl'] : - 1;
1394 1150
1395 1151 if ( $ttl_after < $ttl_before ) {
1396 1152 /**
1397 - * Fires when the records TTL is shortened.
1398 - *
1399 - * Preserved for backward compatibility with third-party code that
1400 - * hooked this action in Stream <= 4.1.x. The auto-purge itself
1401 - * no longer listens to this hook (it was migrated to Action
1402 - * Scheduler), so trigger the purge directly below.
1153 + * Action assists in purging when TTL is shortened
1403 1154 */
1404 1155 do_action( 'wp_stream_auto_purge' );
1405 -
1406 - // Trigger an immediate auto-purge cycle so the shortened TTL
1407 - // takes effect now instead of at the next 12h recurring tick.
1408 - //
1409 - // Enqueue the recurring action as a one-shot async action so the
1410 - // work serializes through the scheduler. Calling
1411 - // purge_scheduled_action() inline here would bypass the overlap
1412 - // guard's view of "in-flight" work (the current request is not a
1413 - // scheduled action) and could stack a parallel chain when a
1414 - // real chain is already running. Falls back to inline if no
1415 - // scheduler is available (defensive — Plugin::__construct() sets it).
1416 - if ( ! empty( $this->plugin->scheduler ) ) {
1417 - if ( ! \WP_Stream\Admin::is_running_auto_purge() ) {
1418 - $this->plugin->scheduler->enqueue_async(
1419 - \WP_Stream\Admin::AUTO_PURGE_ACTION,
1420 - array(),
1421 - \WP_Stream\Admin::AUTO_PURGE_GROUP
1422 - );
1423 - }
1424 - } elseif ( isset( $this->plugin->admin ) ) {
1425 - $this->plugin->admin->purge_scheduled_action();
1426 - }
1427 1156 }
1428 1157 }
1429 1158
1430 1159 /**