$severities, 'change_status' => 'new', 'per_page' => 15, ) ); } if ( ! (int) Settings::get( 'notify_on_complete' ) && empty( $important ) ) { return; } $type = 'integrity' === $scan->scan_type ? __( 'Integrity scan', 'siteaudithub' ) : __( 'Site audit', 'siteaudithub' ); $subject = $important /* translators: 1: site name, 2: scan type */ ? sprintf( __( '[%1$s] %2$s: new important findings', 'siteaudithub' ), wp_specialchars_decode( get_bloginfo( 'name' ), ENT_QUOTES ), $type ) /* translators: 1: site name, 2: scan type */ : sprintf( __( '[%1$s] %2$s completed', 'siteaudithub' ), wp_specialchars_decode( get_bloginfo( 'name' ), ENT_QUOTES ), $type ); self::send( $subject, self::scan_body( $scan, $important ) ); } /** * Plain-text summary of a scan. * * @param object $scan Scan. * @param array $important Important new findings. * @return string */ private static function scan_body( $scan, array $important ) { $lines = array(); $lines[] = sprintf( /* translators: 1: scan id, 2: site URL */ __( 'SiteAuditHub scan #%1$d finished for %2$s.', 'siteaudithub' ), $scan->id, home_url( '/' ) ); $lines[] = ''; $matrix = isset( $scan->summary['matrix'] ) ? (array) $scan->summary['matrix'] : array(); foreach ( Catalog::modules() as $module => $label ) { if ( empty( $matrix[ $module ] ) ) { continue; } $parts = array(); foreach ( Catalog::severities() as $sev => $sev_label ) { if ( ! empty( $matrix[ $module ][ $sev ] ) ) { $parts[] = $sev_label . ': ' . (int) $matrix[ $module ][ $sev ]; } } $lines[] = $label . ': ' . implode( ', ', $parts ); } if ( isset( $scan->summary['changes'] ) ) { $lines[] = ''; /* translators: 1: new, 2: recurring, 3: resolved */ $lines[] = sprintf( __( 'New: %1$d · Recurring: %2$d · Resolved since previous scan: %3$d', 'siteaudithub' ), (int) $scan->summary['changes']['new'], (int) $scan->summary['changes']['recurring'], (int) $scan->summary['resolved'] ); } if ( $important ) { $lines[] = ''; $lines[] = __( 'Important new findings:', 'siteaudithub' ); foreach ( $important as $f ) { $lines[] = '- [' . Catalog::label( 'severity', $f->severity ) . '] ' . $f->title . ( $f->item_key ? ': ' . $f->item_key : '' ); } } $lines[] = ''; $lines[] = __( 'Full report:', 'siteaudithub' ) . ' ' . admin_url( 'admin.php?page=siteaudithub-reports&scan=' . (int) $scan->id ); $lines[] = ''; $lines[] = __( 'Scores and findings are SiteAuditHub estimates based on automated checks, not certifications.', 'siteaudithub' ); return implode( "\n", $lines ); } /** * Weekly summary email. */ public static function weekly_summary() { $site = Repository::latest_completed( 'site' ); $integrity = Repository::latest_completed( 'integrity' ); $score = Scoring::overall(); $lines = array(); /* translators: %s: site URL */ $lines[] = sprintf( __( 'Weekly SiteAuditHub summary for %s', 'siteaudithub' ), home_url( '/' ) ); $lines[] = ''; if ( null !== $score['overall'] ) { /* translators: %d: score */ $lines[] = sprintf( __( 'Overall estimate: %d/100', 'siteaudithub' ), $score['overall'] ); } /* translators: %s: date or "never" */ $lines[] = sprintf( __( 'Last site audit: %s', 'siteaudithub' ), $site ? $site->finished_at . ' UTC (' . (int) $site->findings_count . ' findings)' : __( 'never', 'siteaudithub' ) ); /* translators: %s: date or "never" */ $lines[] = sprintf( __( 'Last integrity scan: %s', 'siteaudithub' ), $integrity ? $integrity->finished_at . ' UTC (' . (int) $integrity->findings_count . ' findings)' : __( 'never', 'siteaudithub' ) ); $lines[] = ''; $lines[] = admin_url( 'admin.php?page=siteaudithub' ); /* translators: %s: site name */ self::send( sprintf( __( '[%s] Weekly SiteAuditHub summary', 'siteaudithub' ), wp_specialchars_decode( get_bloginfo( 'name' ), ENT_QUOTES ) ), implode( "\n", $lines ) ); } /** * Send a test email. * * @return bool */ public static function test() { return self::send( /* translators: %s: site name */ sprintf( __( '[%s] SiteAuditHub test email', 'siteaudithub' ), wp_specialchars_decode( get_bloginfo( 'name' ), ENT_QUOTES ) ), __( 'This is a test message from SiteAuditHub. If you received it, WordPress can deliver notification emails from this site.', 'siteaudithub' ) ); } /** * Send and log. * * @param string $subject Subject. * @param string $body Body. * @return bool Whether wp_mail accepted the message (not proof of delivery). */ public static function send( $subject, $body ) { $to = Settings::recipients(); if ( ! $to ) { self::log( $subject, 0, false ); return false; } $ok = wp_mail( $to, $subject, $body ); self::log( $subject, count( $to ), $ok ); return (bool) $ok; } /** * Record a mail attempt. * * @param string $subject Subject. * @param int $recipients Count. * @param bool $accepted wp_mail result. */ private static function log( $subject, $recipients, $accepted ) { $log = get_option( self::LOG, array() ); $log = is_array( $log ) ? $log : array(); array_unshift( $log, array( 't' => time(), 's' => mb_substr( $subject, 0, 150 ), 'r' => (int) $recipients, 'a' => (bool) $accepted, ) ); update_option( self::LOG, array_slice( $log, 0, 20 ), false ); } /** * Mail log. * * @return array */ public static function log_entries() { $log = get_option( self::LOG, array() ); return is_array( $log ) ? $log : array(); } }