io = $io; } /** * Lists the WordPress core emails `send` can send on this site. * * These are the emails Nice Default Emails covers. The multisite ones are * listed only on a multisite network. * * ## OPTIONS * * [--format=] * : Output format. * --- * default: table * options: * - table * - json * - csv * - yaml * - ids * - count * --- * * ## EXAMPLES * * $ wp adminkeep emails list * $ wp adminkeep emails list --format=ids * * @subcommand list * * @param array $args Positional arguments. * @param array $assoc_args Flags. * @return void */ public function list_( $args, $assoc_args ) { $rows = array(); foreach ( CoreEmails::available() as $id => $sender ) { $rows[] = array( 'id' => $id, 'email' => $sender[0], 'sent_by' => $sender[1], ); } $this->io->items( $this->format( $assoc_args ), $rows, self::LIST_FIELDS ); } /** * Sends WordPress core emails to one address, to see how they look. * * Each email is sent by the core function that sends it for real, so it * arrives exactly as your site would send it: through your mailer (the * SMTP feature, when on), in the Nice Default Emails layout, and recorded * by Email Log when that is on. Only the recipient is changed: every * email goes to --to, and to nobody else. * * What the emails need is made for the run and deleted after it: a * throwaway user for the account emails (no real account's password or * reset link changes), a private post with two comments, personal data * requests. Settings core writes while sending, such as a pending admin * email change or a recovery mode key, are put back, so the links in * those emails do nothing. * * Needs Nice Default Emails switched on. Exits 1 if any email fails. * * ## OPTIONS * * [...] * : Which emails. Ids come from `wp adminkeep emails list`. * * [--all] * : Send every email in the list. * * --to= * : Address to send them to. * * [--format=] * : Output format. * --- * default: table * options: * - table * - json * - csv * - yaml * --- * * ## EXAMPLES * * $ wp adminkeep emails send password_reset --to=you@example.com * $ wp adminkeep emails send --all --to=you@example.com * * @param array $args Email ids. * @param array $assoc_args Flags. * @return void */ public function send( $args, $assoc_args ) { $to = isset( $assoc_args['to'] ) && is_string( $assoc_args['to'] ) ? trim( $assoc_args['to'] ) : ''; if ( '' === $to ) { $this->io->error( 'Say where to send them: --to=.' ); } if ( ! is_email( $to ) ) { $this->io->error( sprintf( '"%s" is not a valid email address.', $to ) ); } $ids = $this->ids( (array) $args, ! empty( $assoc_args['all'] ) ); if ( ! Settings::is_enabled( 'nice_emails' ) ) { $this->io->error( 'Nice Default Emails is off, so these would go out as plain text. Switch it on first: wp adminkeep feature enable nice_emails' ); } $sender = new CoreEmails(); $rows = $sender->send( $ids, $to ); $failed = 0; foreach ( $rows as $row ) { if ( 'sent' !== $row['status'] ) { ++$failed; $this->io->warning( $row['id'] . ': ' . $row['error'] ); } } foreach ( $sender->left_behind() as $what ) { $this->io->warning( sprintf( 'Could not clean up %s. Remove it by hand.', $what ) ); } $this->io->items( $this->format( $assoc_args ), $this->printable( $rows ), self::SEND_FIELDS ); if ( $failed > 0 ) { $this->io->error( sprintf( '%d of %d emails failed.', $failed, count( $rows ) ) ); } if ( $sender->left_behind() ) { $this->io->error( 'Every email was sent, but the run could not clean up after itself.' ); } $this->io->success( sprintf( 1 === count( $rows ) ? 'Sent %d email to %s.' : 'Sent %d emails to %s.', count( $rows ), $to ) ); } /** * The ids to send, checked: named ones or --all, not both, and each one this site can send. * * @param string[] $args Named ids. * @param bool $all Whether --all was given. * @return string[] */ private function ids( array $args, $all ) { $available = CoreEmails::available(); if ( $all === ! empty( $args ) ) { $this->io->error( 'Name the emails to send, or pass --all. Not both.' ); } if ( $all ) { return array_keys( $available ); } foreach ( $args as $id ) { if ( isset( $available[ $id ] ) ) { continue; } if ( in_array( $id, CoreEmails::MULTISITE, true ) ) { $this->io->error( sprintf( '"%s" is sent only on a multisite network, and this site is not one.', $id ) ); } $this->io->error( sprintf( 'No email "%s". Use one of: %s.', $id, implode( ', ', array_keys( $available ) ) ) ); } return array_values( array_unique( array_map( 'strval', $args ) ) ); } /** * The rows as `send` prints them. The error goes out as a warning, not a column. * * @param array[] $rows Rows from CoreEmails::send(). * @return array[] */ private function printable( array $rows ) { $printable = array(); foreach ( $rows as $row ) { $printable[] = array_intersect_key( $row, array_flip( self::SEND_FIELDS ) ); } return $printable; } /** * The --format flag, table by default. * * @param array $assoc_args Flags. * @return string */ private function format( array $assoc_args ) { return isset( $assoc_args['format'] ) ? (string) $assoc_args['format'] : 'table'; } }