[a-f0-9]{10})'; /** * Monitor. * * @var Monitor */ private $monitor; /** * Sites. * * @var ProfileRepository */ private $sites; /** * Slack. * * @var Slack */ private $slack; /** * Constructor. * * @param Monitor $monitor Monitor. * @param ProfileRepository $sites Sites. * @param Slack $slack Slack. */ public function __construct( Monitor $monitor, ProfileRepository $sites, Slack $slack ) { $this->monitor = $monitor; $this->sites = $sites; $this->slack = $slack; } /** * Registers routes. * * @return void */ public function register_routes() { $can = static function () { return current_user_can( Capabilities::MANAGE ); }; $base = '/monitor/sites/' . ReportController::SITE_PATTERN; $site_args = array( 'site' => array( 'type' => 'string', 'required' => true, 'pattern' => '^[a-z0-9]{2,20}$', ), ); $alert_args = array_merge( $site_args, array( 'alert' => array( 'type' => 'string', 'required' => true, 'pattern' => '^[a-f0-9]{10}$', ), ) ); register_rest_route( ReportController::NAMESPACE_V1, '/monitor', array( 'methods' => \WP_REST_Server::READABLE, 'callback' => array( $this, 'index' ), 'permission_callback' => $can, ) ); register_rest_route( ReportController::NAMESPACE_V1, $base . '/check', array( 'methods' => \WP_REST_Server::CREATABLE, 'callback' => array( $this, 'check' ), 'permission_callback' => $can, 'args' => $site_args, ) ); register_rest_route( ReportController::NAMESPACE_V1, $base . '/alerts/' . self::ALERT_PATTERN . '/(?Phandle|snooze|restore)', array( 'methods' => \WP_REST_Server::CREATABLE, 'callback' => array( $this, 'act' ), 'permission_callback' => $can, 'args' => array_merge( $alert_args, array( 'action' => array( 'type' => 'string', 'required' => true, 'enum' => array( 'handle', 'snooze', 'restore' ), ), ) ), ) ); register_rest_route( ReportController::NAMESPACE_V1, $base . '/alerts/' . self::ALERT_PATTERN . '/slack', array( 'methods' => \WP_REST_Server::CREATABLE, 'callback' => array( $this, 'share' ), 'permission_callback' => $can, 'args' => array_merge( $alert_args, array( 'note' => array( 'type' => 'string', 'default' => '', 'maxLength' => 1000, 'sanitize_callback' => 'sanitize_textarea_field', ), ) ), ) ); } /** * The whole list. * * @return \WP_REST_Response */ public function index() { return rest_ensure_response( $this->payload() ); } /** * Checks one site now. * * @param \WP_REST_Request $request Request. * @return \WP_REST_Response|\WP_Error */ public function check( \WP_REST_Request $request ) { $site = $this->sites->find( (string) $request['site'] ); if ( ! $site || ! Monitor::checkable( $site ) ) { return self::not_found(); } if ( function_exists( 'set_time_limit' ) ) { set_time_limit( 120 ); // phpcs:ignore Squiz.PHP.DiscouragedFunctions.Discouraged -- Talks to Google for one site. } $this->monitor->check( $site ); return rest_ensure_response( $this->payload() ); } /** * Handles, snoozes or restores an alert. * * @param \WP_REST_Request $request Request. * @return \WP_REST_Response|\WP_Error */ public function act( \WP_REST_Request $request ) { $site = $this->sites->find( (string) $request['site'] ); if ( ! $site ) { return self::not_found(); } $store = $this->monitor->store(); $id = (string) $request['alert']; $user = get_current_user_id(); switch ( (string) $request['action'] ) { case 'handle': $alert = $store->handle( $site->id, $id, $user ); break; case 'snooze': $alert = $store->snooze( $site->id, $id, $user ); break; default: $alert = $store->restore( $site->id, $id, $user ); } if ( null === $alert ) { return self::not_found(); } return rest_ensure_response( $this->payload() ); } /** * Shares an alert to Slack. * * @param \WP_REST_Request $request Request. * @return \WP_REST_Response|\WP_Error */ public function share( \WP_REST_Request $request ) { $site = $this->sites->find( (string) $request['site'] ); $alert = $site ? $this->monitor->store()->find( $site->id, (string) $request['alert'] ) : null; if ( ! $site || ! $alert ) { return self::not_found(); } $user = wp_get_current_user(); $sender = ! empty( $user->display_name ) ? (string) $user->display_name : ''; $sent = $this->slack->send_alert( Presenter::present( $alert, $site ), (string) $request['note'], $sender ); if ( is_wp_error( $sent ) ) { return new \WP_Error( $sent->get_error_code(), $sent->get_error_message(), array( 'status' => 502 ) ); } $this->monitor->store()->shared( $site->id, $alert['id'], get_current_user_id() ); return rest_ensure_response( $this->payload() ); } /** * The screen's data. * * @return array */ private function payload() { $out = $this->monitor->payload( $this->sites->all() ); $out['slack'] = $this->slack->configured(); return $out; } /** * Same error for unknown sites and alerts. * * @return \WP_Error */ private static function not_found() { return new \WP_Error( 'turtlereport_not_found', __( 'That issue or site no longer exists. Reload the page.', 'turtlereport' ), array( 'status' => 404 ) ); } }