get_error_message() ); } else { $rating = Performance::rating( $result['score'] ); \WP_CLI::log( "{$url} ({$strategy}): {$rating['label']} ({$result['score']}/100)" ); } } } update_option( Performance::LAST_RUN_OPTION, time(), false ); \WP_CLI::success( 'Done.' ); } /** * Downloads the Wordfence Intelligence feed and lists vulnerable software. * * ## OPTIONS * * [--no-sync] * : Use the data already downloaded. * * @param array $args Positional args. * @param array $assoc_args Named args. */ public function vulnerabilities( $args, $assoc_args ) { if ( \WP_CLI\Utils\get_flag_value( $assoc_args, 'sync', true ) ) { $result = Vulnerabilities::sync_now(); if ( is_wp_error( $result ) ) { \WP_CLI::error( $result->get_error_message() ); } $state = Vulnerabilities::sync_state(); \WP_CLI::log( sprintf( '%d records read, %d relevant to this site.', $state['total'], $state['indexed'] ) ); } $exposures = Vulnerabilities::exposures(); if ( ! $exposures ) { \WP_CLI::success( 'No installed software has known vulnerabilities.' ); return; } foreach ( $exposures as $exposure ) { \WP_CLI::log( sprintf( '%s %s [%s] %s', $exposure['name'], $exposure['version'], $exposure['state'], Vulnerabilities::advice( $exposure ) ) ); foreach ( $exposure['vulns'] as $vuln ) { \WP_CLI::log( sprintf( ' [%s]%s %s', $vuln['score'], $vuln['mismatch'] ? ' (other edition?)' : '', $vuln['title'] ) ); } } \WP_CLI::warning( sprintf( '%d installed component(s) need attention.', count( Vulnerabilities::active_exposures() ) ) ); } /** * Adds a manual entry to the log. * * ## OPTIONS * * * : What was done. * * [--category=<category>] * : test, security, performance, backup, content, incident or other. * --- * default: other * --- * * [--minutes=<minutes>] * : Time spent. * * [--notes=<notes>] * : Longer description. * * ## EXAMPLES * * wp maintained-log add "Checked contact form delivery" --category=test --minutes=10 * * @param array $args Positional args. * @param array $assoc_args Named args. */ public function add( $args, $assoc_args ) { $category = isset( $assoc_args['category'] ) ? $assoc_args['category'] : 'other'; if ( ! array_key_exists( $category, Log::categories() ) ) { \WP_CLI::error( 'Unknown category. Use one of: ' . implode( ', ', array_keys( Log::categories() ) ) ); } $id = Log::add( array( 'type' => Log::TYPE_MANUAL, 'category' => $category, 'status' => Log::STATUS_SUCCESS, 'title' => $args[0], 'details' => array( 'notes' => isset( $assoc_args['notes'] ) ? sanitize_textarea_field( $assoc_args['notes'] ) : '' ), 'minutes' => isset( $assoc_args['minutes'] ) ? absint( $assoc_args['minutes'] ) : 0, 'source' => Log::SOURCE_CLI, ) ); $id ? \WP_CLI::success( "Entry #{$id} added." ) : \WP_CLI::error( 'Could not add the entry.' ); } /** * Lists log entries. * * ## OPTIONS * * [--type=<type>] * : update, check, manual, report, alert or system. * * [--limit=<limit>] * : Number of entries. * --- * default: 20 * --- * * [--format=<format>] * : table, json, csv or yaml. * --- * default: table * --- * * @subcommand list * * @param array $args Positional args. * @param array $assoc_args Named args. */ public function list_( $args, $assoc_args ) { $entries = Log::query( array( 'type' => isset( $assoc_args['type'] ) ? $assoc_args['type'] : '', 'per_page' => absint( $assoc_args['limit'] ), ) ); $items = array_map( static function ( $entry ) { return array( 'id' => $entry->id, 'created_at' => $entry->created_at, 'type' => $entry->type, 'status' => $entry->status, 'source' => $entry->source, 'minutes' => $entry->minutes, 'title' => $entry->title, ); }, $entries ); \WP_CLI\Utils\format_items( $assoc_args['format'], $items, array( 'id', 'created_at', 'type', 'status', 'source', 'minutes', 'title' ) ); } /** * Sends the client report for the period since the last report. * * ## OPTIONS * * [--to=<emails>] * : Send a test copy to these addresses instead of the client. * * @param array $args Positional args. * @param array $assoc_args Named args. */ public function report( $args, $assoc_args ) { $period = Reporter::manual_period(); $report = Reporter::build( $period['from'], $period['to'] ); $result = Reporter::send( $report, isset( $assoc_args['to'] ) ? $assoc_args['to'] : null ); if ( is_wp_error( $result ) ) { \WP_CLI::error( $result->get_error_message() ); } if ( ! isset( $assoc_args['to'] ) ) { update_option( Reporter::LAST_PERIOD_OPTION, $period['to']->format( 'Y-m-d H:i:s' ), false ); } \WP_CLI::success( 'Report sent.' ); } /** * Verifies that no log entry was altered or deleted. * * @param array $args Positional args. * @param array $assoc_args Named args. */ public function verify( $args, $assoc_args ) { $result = Log::verify_chain(); if ( $result['ok'] ) { \WP_CLI::success( sprintf( '%d entries verified. The log is intact.', $result['checked'] ) ); } else { \WP_CLI::error( sprintf( 'The log was altered at or before entry #%d.', $result['broken_at'] ) ); } } }