1 && ! Applier::bulk_enabled() ) { self::finish( array( 'message' => __( 'Applying many links at once is turned off on this site. Apply them one at a time.', 'linkcortex' ) ) ); } $res = Applier::apply( $ids ); self::finish( array( 'results' => $res['results'] ) ); } self::finish( array( 'message' => __( 'This confirmation expired. Please select the links again.', 'linkcortex' ) ) ); } elseif ( 'accept_above' === $post_action ) { check_admin_referer( 'ailsug_accept_above' ); $min = isset( $_POST['min'] ) ? max( 1, min( 100, (int) $_POST['min'] ) ) : 80; $res = self::accept_above( $min ); self::finish( array( 'results' => $res['results'] ) ); }//end if } /** * Integer list from the request. * * @param string $key Key. * @return int[] */ private static function request_ids( $key ) { // phpcs:ignore WordPress.Security.NonceVerification.Recommended, WordPress.Security.ValidatedSanitizedInput.InputNotSanitized -- Nonce checked by caller; values cast to int. $raw = isset( $_REQUEST[ $key ] ) ? wp_unslash( $_REQUEST[ $key ] ) : ( 'ids' === $key && isset( $_REQUEST['id'] ) ? wp_unslash( $_REQUEST['id'] ) : array() ); return array_values( array_filter( array_map( 'absint', is_array( $raw ) ? $raw : explode( ',', (string) $raw ) ) ) ); } /** * Perform an action. * * @param string $action Action. * @param int[] $ids Suggestion IDs. * @param int[] $applied_ids Applied record IDs. * @param string $batch Batch ID. * @return void */ private static function dispatch( $action, array $ids, array $applied_ids, $batch ) { switch ( $action ) { case 'accept': case 'apply': if ( ! $ids ) { self::finish( array( 'message' => __( 'Select at least one suggestion to accept.', 'linkcortex' ) ) ); } if ( count( $ids ) > 1 && ! Applier::bulk_enabled() ) { self::finish( array( 'message' => __( 'Applying many links at once is turned off on this site. Apply them one at a time.', 'linkcortex' ) ) ); } $res = Applier::apply( $ids ); self::finish( array( 'results' => $res['results'] ) ); break; case 'reject': $n = 0; foreach ( $ids as $id ) { $s = Store::get( $id ); if ( $s && 'applied' !== $s['status'] && current_user_can( 'edit_post', (int) $s['source_post_id'] ) ) { $n += Store::update( $id, array( 'status' => 'rejected' ) ) ? 1 : 0; } } self::finish( array( /* translators: %s: count. */ 'message' => sprintf( _n( '%s suggestion rejected. It will not be suggested again.', '%s suggestions rejected. They will not be suggested again.', $n, 'linkcortex' ), number_format_i18n( $n ) ), ) ); break; case 'revert': $records = Reverter::records( $applied_ids ); self::finish( array( 'results' => $records ? Reverter::revert( $records ) : array() ) ); break; case 'revert_batch': $records = Reverter::records( array(), $batch ); self::finish( array( 'results' => $records ? Reverter::revert( $records ) : array() ) ); break; }//end switch } /** * Accept and apply all pending suggestions at or above a score (that the user may edit). * * @param int $min Minimum score. * @return array{batch_id?:string,results:array[]} */ private static function accept_above( $min ) { global $wpdb; $t = Activator::tables(); // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching -- Own table. $rows = $wpdb->get_results( $wpdb->prepare( "SELECT s.id, s.source_post_id FROM %i s WHERE s.status = 'pending' AND s.score >= %d", $t['suggestions'], (int) $min ), ARRAY_A ); $ids = array(); foreach ( (array) $rows as $row ) { if ( current_user_can( 'edit_post', (int) $row['source_post_id'] ) ) { $ids[] = (int) $row['id']; } } if ( ! $ids ) { return array( 'results' => array( array( 'status' => 'skipped', 'post_id' => 0, 'message' => __( 'No pending suggestions met that relevance threshold.', 'linkcortex' ), ), ), ); } if ( count( $ids ) > 1 && ! Applier::bulk_enabled() ) { return array( 'results' => array( array( 'status' => 'error', 'post_id' => 0, 'message' => __( 'Applying many links at once is turned off on this site. Apply them one at a time.', 'linkcortex' ), ), ), ); } return Applier::apply( $ids ); } /** * Read and consume a confirmation token. * * @param string $token Token. * @return int[] */ private static function take_token( $token ) { $key = 'ailsug_apply_' . get_current_user_id() . '_' . $token; $ids = get_transient( $key ); delete_transient( $key ); return is_array( $ids ) ? array_map( 'intval', $ids ) : array(); } /** * Store a result notice and redirect back to the list. * * @param array $notice Notice data. * @return void */ private static function finish( array $notice ) { set_transient( 'ailsug_notice_' . get_current_user_id(), $notice, 5 * MINUTE_IN_SECONDS ); $referer = wp_get_referer(); $url = $referer && false !== strpos( $referer, 'page=' . Menu::SLUG . '-suggestions' ) ? remove_query_arg( array( 'ailsug_action', '_wpnonce', 'ids', 'applied_ids', 'batch', 'confirm' ), $referer ) : Menu::url( 'suggestions' ); wp_safe_redirect( $url ); exit; } /** * Render. * * @return void */ public static function render() { if ( ! current_user_can( 'edit_posts' ) ) { wp_die( esc_html__( 'You do not have permission to view this page.', 'linkcortex' ) ); } echo '
' . esc_html__( 'Review each idea and accept suggestions to instantly add links to your pages. Every change is saved as a page revision and can be undone here.', 'linkcortex' ) . '
'; self::render_notice(); Keywords_Page::progress_box( Queue::active_run( array( 'regenerate', 'scan' ) ) ); if ( 'pending' === $f['status'] ) { echo ''; } $table = new Suggestions_Table(); $table->prepare_items(); $table->views(); echo ''; } /** * Confirmation screen before changing pages. * * @param string $token Token. * @return void */ private static function render_confirm( $token ) { $ids = get_transient( 'ailsug_apply_' . get_current_user_id() . '_' . $token ); echo '' . esc_html__( 'This confirmation expired. Please select the links again.', 'linkcortex' ) . '
' . esc_html__( 'Back to suggestions', 'linkcortex' ) . '
'; return; } $preview = Applier::preview( $ids ); echo '' . esc_html( sprintf( __( '%1$s links will be added to %2$s pages.', 'linkcortex' ), number_format_i18n( $preview['links'] ), number_format_i18n( $preview['posts'] ) ) ) . '
'; echo '' . esc_html__( 'Only the link is added; nothing else in your pages changes. Each page is saved as a new revision, and you can undo every link from the Applied list.', 'linkcortex' ) . '
'; if ( $preview['links'] > 1 && ! Applier::bulk_enabled() ) { echo '' . esc_html__( 'Applying many links at once is turned off on this site. Apply them one at a time.', 'linkcortex' ) . '
'; } echo '' . esc_html( $notice['message'] ) . '
' . esc_html__( 'Links:', 'linkcortex' ) . ' ' . esc_html( $parts ? implode( ', ', $parts ) : __( 'nothing to do', 'linkcortex' ) ) . '
'; $details = array_filter( $notice['results'], static function ( $r ) { return ! in_array( $r['status'], array( 'applied', 'reverted' ), true ); } ); if ( $details ) { echo '