← All changes
|
src/model/notification/class-malware-notification.php
+48
-29
6.0.1
→
6.3.0
View file →
| @@ -12,12 +12,10 @@ | ||
| 12 | 12 | use WP_Defender\Model\Scan; |
| 13 | 13 | use WP_Defender\Component\Mail; |
| 14 | 14 | use WP_Defender\Component\Notification; |
| 15 | 15 | use WP_Defender\Model\Scan_Item; |
| 16 | -use WP_Defender\Model\Notification\Malware_Report; | |
| 17 | 16 | use WP_Defender\Traits\Scan_Email_Template; |
| 18 | 17 | use WP_Defender\Traits\Scan_Upsell; |
| 19 | -use WP_Defender\Behavior\WPMUDEV; | |
| 20 | 18 | |
| 21 | 19 | /** |
| 22 | 20 | * Handles the scheduling and sending of malware-related notifications. |
| 23 | 21 | */ |
| @@ -111,8 +109,44 @@ | ||
| 111 | 109 | } |
| 112 | 110 | } |
| 113 | 111 | |
| 114 | 112 | /** |
| 113 | + * Sends a manual scan notification to the user who triggered the scan. | |
| 114 | + * | |
| 115 | + * @param Scan $scan The scan object. | |
| 116 | + * | |
| 117 | + * @return bool Whether the manual scan notification was handled. | |
| 118 | + */ | |
| 119 | + private function send_manual_scan( Scan $scan ): bool { | |
| 120 | + $user_id = (int) get_transient( 'defender_scan_triggered_by_' . $scan->id ); | |
| 121 | + delete_transient( 'defender_scan_triggered_by_' . $scan->id ); | |
| 122 | + if ( $user_id <= 0 ) { | |
| 123 | + return false; | |
| 124 | + } | |
| 125 | + | |
| 126 | + $user = get_userdata( $user_id ); | |
| 127 | + if ( ! $user ) { | |
| 128 | + return true; | |
| 129 | + } | |
| 130 | + | |
| 131 | + $issues = $scan->get_issues( null, Scan_Item::STATUS_ACTIVE ); | |
| 132 | + if ( in_array( $scan->status, array( Scan::STATUS_ERROR, Scan::STATUS_IDLE ), true ) ) { | |
| 133 | + $templates = $this->configs['template']['error']; | |
| 134 | + } elseif ( 0 === count( $issues ) ) { | |
| 135 | + return true; | |
| 136 | + } else { | |
| 137 | + $templates = $this->configs['template']['found']; | |
| 138 | + } | |
| 139 | + | |
| 140 | + $subject = $templates['subject']; | |
| 141 | + $content = nl2br( $templates['body'] ); | |
| 142 | + $service = wd_di()->get( Notification::class ); | |
| 143 | + $this->send_to_user( $user->user_email, $user->display_name, $subject, $content, $issues, $service ); | |
| 144 | + | |
| 145 | + return true; | |
| 146 | + } | |
| 147 | + | |
| 148 | + /** | |
| 115 | 149 | * Sends the malware notification email. |
| 116 | 150 | * Constructs and sends the malware notification email to the recipients. |
| 117 | 151 | * |
| 118 | 152 | * @param Scan $scan The scan object. |
| @@ -119,24 +153,11 @@ | ||
| 119 | 153 | * |
| 120 | 154 | * @return void |
| 121 | 155 | */ |
| 122 | 156 | public function send( Scan $scan ): void { |
| 123 | - // Manual scan: always notify only the triggering user, no opt-in or status check required. | |
| 124 | - if ( ! $scan->is_automation ) { | |
| 125 | - $user_id = (int) get_transient( 'defender_scan_triggered_by_' . $scan->id ); | |
| 126 | - delete_transient( 'defender_scan_triggered_by_' . $scan->id ); | |
| 127 | - if ( $user_id > 0 ) { | |
| 128 | - $user = get_userdata( $user_id ); | |
| 129 | - if ( $user ) { | |
| 130 | - $issues = $scan->get_issues( null, Scan_Item::STATUS_ACTIVE ); | |
| 131 | - $templates = count( $issues ) ? $this->configs['template']['found'] : $this->configs['template']['not_found']; | |
| 132 | - $subject = $templates['subject']; | |
| 133 | - $content = nl2br( $templates['body'] ); | |
| 134 | - $service = wd_di()->get( Notification::class ); | |
| 135 | - $this->send_to_user( $user->user_email, $user->display_name, $subject, $content, $issues, $service ); | |
| 136 | - } | |
| 137 | - return; | |
| 138 | - } | |
| 157 | + // Manual scan: notify only the triggering user when issues are found or the scan fails. | |
| 158 | + if ( ! $scan->is_automation && $this->send_manual_scan( $scan ) ) { | |
| 159 | + return; | |
| 139 | 160 | } |
| 140 | 161 | |
| 141 | 162 | $object = $this; |
| 142 | 163 | if ( $scan->is_automation ) { |
| @@ -148,19 +169,18 @@ | ||
| 148 | 169 | // @since 2.7.0 Remove 'dry_run'-condition. |
| 149 | 170 | } |
| 150 | 171 | $issues = $scan->get_issues( null, Scan_Item::STATUS_ACTIVE ); |
| 151 | 172 | /** |
| 152 | - * When the Defender is unable to scan files for some reason and the 'error_send' option is checked. | |
| 173 | + * When the Defender is unable to scan files for some reason. | |
| 174 | + * The 'error_send' option was removed in v6. Its stored value is preserved for backward | |
| 175 | + * compatibility (downgrade safety), but error notifications are now always sent regardless | |
| 176 | + * of what the legacy value is. | |
| 153 | 177 | * Possible reasons: |
| 154 | 178 | * - no connection to Scan API, |
| 155 | 179 | * - no checksums received from wp.org, |
| 156 | 180 | * - scan process stuck. |
| 157 | 181 | */ |
| 158 | - if ( | |
| 159 | - isset( $object->configs['error_send'] ) | |
| 160 | - && $object->configs['error_send'] | |
| 161 | - && in_array( $scan->status, array( Scan::STATUS_ERROR, Scan::STATUS_IDLE ), true ) | |
| 162 | - ) { | |
| 182 | + if ( in_array( $scan->status, array( Scan::STATUS_ERROR, Scan::STATUS_IDLE ), true ) ) { | |
| 163 | 183 | $subject = $object->configs['template']['error']['subject']; |
| 164 | 184 | $content = nl2br( $object->configs['template']['error']['body'] ); |
| 165 | 185 | |
| 166 | 186 | $this->email_engine( $scan, $object, $subject, $content, $issues ); |
| @@ -167,13 +187,12 @@ | ||
| 167 | 187 | |
| 168 | 188 | return; |
| 169 | 189 | } |
| 170 | 190 | |
| 171 | - // Sometimes value may be as empty string for disabled 'always_send'. | |
| 172 | - if ( | |
| 173 | - ( ! isset( $object->configs['always_send'] ) || true !== $object->configs['always_send'] ) | |
| 174 | - && 0 === count( $issues ) | |
| 175 | - ) { | |
| 191 | + // The 'always_send' option was removed in v6. Its stored value is preserved for backward | |
| 192 | + // compatibility (downgrade safety), but it must have no effect here — never send when | |
| 193 | + // there are no issues, regardless of what the legacy value is. | |
| 194 | + if ( 0 === count( $issues ) ) { | |
| 176 | 195 | return; |
| 177 | 196 | } |
| 178 | 197 | // For another case. |
| 179 | 198 | $templates = count( $issues ) ? $object->configs['template']['found'] : $object->configs['template']['not_found']; |