| @@ -28,11 +28,12 @@ | ||
| 28 | 28 | |
| 29 | 29 | use IO; |
| 30 | 30 | use Plugin; |
| 31 | 31 | |
| 32 | - public const URL_PLUGIN_VCS = 'https://downloads.wordpress.org/plugin-checksums/'; | |
| 33 | - public const PLUGIN_SLUGS = 'wd_plugin_slugs_changes'; | |
| 34 | - public const PLUGIN_PREMIUM_SLUGS = 'wd_plugin_premium_slugs'; | |
| 32 | + public const URL_PLUGIN_VCS = 'https://downloads.wordpress.org/plugin-checksums/'; | |
| 33 | + public const PLUGIN_SLUGS = 'wd_plugin_slugs_changes'; | |
| 34 | + public const PLUGIN_SLUGS_CHECKPOINT = 'wd_plugin_slugs_changes_checkpoint'; | |
| 35 | + public const PLUGIN_PREMIUM_SLUGS = 'wd_plugin_premium_slugs'; | |
| 35 | 36 | /** |
| 36 | 37 | * List of premium plugin slugs. |
| 37 | 38 | * |
| 38 | 39 | * @var array |
| @@ -81,9 +82,8 @@ | ||
| 81 | 82 | * @return bool True if it's a WPMUDEV pro plugin, false otherwise. |
| 82 | 83 | */ |
| 83 | 84 | private function is_wpmudev_pro_plugin( $plugin_file ): bool { |
| 84 | 85 | $plugin_data = get_plugin_data( WP_PLUGIN_DIR . '/' . $plugin_file ); |
| 85 | - // @phpstan-ignore-next-line - WDP ID is a custom header used by WPMUDEV plugins. | |
| 86 | 86 | return array_key_exists( 'WDP ID', $plugin_data ) && '' !== $plugin_data['WDP ID']; |
| 87 | 87 | } |
| 88 | 88 | |
| 89 | 89 | /** |
| @@ -212,8 +212,11 @@ | ||
| 212 | 212 | $timer = new Timer(); |
| 213 | 213 | $model = $this->owner->scan; |
| 214 | 214 | $pos = (int) $model->task_checkpoint; |
| 215 | 215 | $plugin_files->seek( $pos ); |
| 216 | + if ( 0 === $pos ) { | |
| 217 | + delete_site_option( self::PLUGIN_SLUGS_CHECKPOINT ); | |
| 218 | + } | |
| 216 | 219 | $slugs_of_edited_plugins = array(); |
| 217 | 220 | $integration_smush = wd_di()->get( Smush::class ); |
| 218 | 221 | $exist_smush_images = $integration_smush->exist_image_table(); |
| 219 | 222 | while ( $plugin_files->valid() ) { |
| @@ -304,16 +307,15 @@ | ||
| 304 | 307 | // We will check if we have any ignore issue from last scan, so we can bring it here. |
| 305 | 308 | $last = Scan::get_last(); |
| 306 | 309 | if ( is_object( $last ) ) { |
| 307 | 310 | $ignored_issues = $last->get_issues( Scan_Item::TYPE_PLUGIN_CHECK, Scan_Item::STATUS_IGNORE ); |
| 308 | - foreach ( $ignored_issues as $issue ) { | |
| 309 | - $model->add_item( Scan_Item::TYPE_PLUGIN_CHECK, $issue->raw_data, Scan_Item::STATUS_IGNORE ); | |
| 310 | - } | |
| 311 | + $model->carry_forward_ignored_issues( Scan_Item::TYPE_PLUGIN_CHECK, $ignored_issues, 'file' ); | |
| 311 | 312 | } |
| 312 | 313 | // Done, reset this, so we can use later. |
| 313 | 314 | $model->task_checkpoint = ''; |
| 314 | 315 | } |
| 315 | 316 | $model->save(); |
| 317 | + | |
| 316 | 318 | /** |
| 317 | 319 | * Reduce false positive reports. Check it only if enabled 'Suspicious code' option. |
| 318 | 320 | * |
| 319 | 321 | * @since 2.4.10 |
| @@ -318,11 +320,9 @@ | ||
| 318 | 320 | * |
| 319 | 321 | * @since 2.4.10 |
| 320 | 322 | */ |
| 321 | 323 | if ( ( new Scan_Settings() )->scan_malware ) { |
| 322 | - if ( array() !== $slugs_of_edited_plugins ) { | |
| 323 | - update_site_option( self::PLUGIN_SLUGS, array_unique( $slugs_of_edited_plugins ) ); | |
| 324 | - } | |
| 324 | + $this->persist_changed_plugin_slugs( $slugs_of_edited_plugins, ! $plugin_files->valid() ); | |
| 325 | 325 | if ( array() !== $this->premium_slugs ) { |
| 326 | 326 | update_site_option( self::PLUGIN_PREMIUM_SLUGS, $this->premium_slugs ); |
| 327 | 327 | } |
| 328 | 328 | } |
| @@ -327,8 +327,28 @@ | ||
| 327 | 327 | } |
| 328 | 328 | } |
| 329 | 329 | |
| 330 | 330 | return ! $plugin_files->valid(); |
| 331 | + } | |
| 332 | + | |
| 333 | + /** | |
| 334 | + * Persist changed plugin slugs across checkpoint scan batches. | |
| 335 | + * | |
| 336 | + * @param array $batch_slugs Slugs found in the current batch. | |
| 337 | + * @param bool $is_complete Whether the plugin integrity task has completed. | |
| 338 | + * | |
| 339 | + * @return void | |
| 340 | + */ | |
| 341 | + private function persist_changed_plugin_slugs( array $batch_slugs, bool $is_complete ): void { | |
| 342 | + $checkpoint_slugs = (array) get_site_option( self::PLUGIN_SLUGS_CHECKPOINT, array() ); | |
| 343 | + $changed_slugs = array_values( array_unique( array_merge( $checkpoint_slugs, $batch_slugs ) ) ); | |
| 344 | + | |
| 345 | + if ( $is_complete ) { | |
| 346 | + update_site_option( self::PLUGIN_SLUGS, $changed_slugs ); | |
| 347 | + delete_site_option( self::PLUGIN_SLUGS_CHECKPOINT ); | |
| 348 | + } else { | |
| 349 | + update_site_option( self::PLUGIN_SLUGS_CHECKPOINT, $changed_slugs ); | |
| 350 | + } | |
| 331 | 351 | } |
| 332 | 352 | |
| 333 | 353 | /** |
| 334 | 354 | * Checks if given file is a valid image. |