value for the ADMINKEEP_SMTP_* constants in force; null * reads the real ones. A parameter so a test can supply some. */ public function __construct( $constants = null ) { $this->constants = null === $constants ? SmtpConfig::defined_constants() : array_intersect_key( (array) $constants, SmtpConfig::CONSTANTS ); } /** * The sources the command and the screen know, by the name the command takes. * * @return array */ public static function sources() { return array( 'wp-mail-smtp' => WpMailSmtpSource::from_environment(), ); } /** * What run() would do, without writing anything. * * @param Source $source Where from. * @return array{source: string, written: string[], kept: string[], password: string}|\WP_Error */ public function preview( Source $source ) { $read = $this->readable( $source ); return is_wp_error( $read ) ? $read : $this->report( $source, $read ); } /** * Copy the source's connection, replacing Adminkeep's own. * * @param Source $source Where from. * @return array|\WP_Error The same report preview() gives. */ public function run( Source $source ) { $read = $this->readable( $source ); if ( is_wp_error( $read ) ) { return $read; } $report = $this->report( $source, $read ); $input = $read['settings']; // Left out of the input, the password is kept by sanitize(): that is what should happen // when the source has none, or has one that could not be opened. if ( self::PASSWORD_COPIED === $report['password'] ) { $input['password'] = $read['password']; } update_option( SmtpConfig::OPTION, SmtpConfig::sanitize( $input, SmtpConfig::stored(), $this->constants, SecretBox::from_salts() ), false ); return $report; } /** * The source's connection, or why it cannot be copied. * * @param Source $source Where from. * @return array|\WP_Error */ private function readable( Source $source ) { if ( ! $source->available() ) { return new \WP_Error( 'adminkeep_smtp_import_unavailable', sprintf( 'No %s settings on this site (option %s).', $source->label(), $source->location() ) ); } $mailer = $source->mailer(); if ( '' === $mailer ) { return new \WP_Error( 'adminkeep_smtp_import_mailer', sprintf( '%s has no mailer chosen, so there is nothing to copy.', $source->label() ) ); } if ( 'smtp' !== $mailer ) { return new \WP_Error( 'adminkeep_smtp_import_mailer', sprintf( '%1$s is set to send through %2$s, which is not an SMTP connection, so there is nothing to copy. Only a host, port and username setup can be copied.', $source->label(), $mailer ) ); } $read = $source->read(); if ( '' === trim( (string) $read['settings']['host'] ) ) { return new \WP_Error( 'adminkeep_smtp_import_no_host', sprintf( '%s has no SMTP host set, so there is nothing to copy.', $source->label() ) ); } return $read; } /** * Which fields are written, which wp-config.php keeps, and what becomes of the password. * * @param Source $source Where from. * @param array $read What the source read. * @return array{source: string, written: string[], kept: string[], password: string} */ private function report( Source $source, array $read ) { $written = array(); $kept = array(); foreach ( array_keys( $read['settings'] ) as $field ) { if ( array_key_exists( $field, $this->constants ) ) { $kept[] = $field; } else { $written[] = $field; } } if ( array_key_exists( 'password', $this->constants ) ) { $kept[] = 'password'; $password = self::PASSWORD_LOCKED; } elseif ( ! $read['password_readable'] ) { $password = self::PASSWORD_UNREADABLE; } elseif ( '' === $read['password'] ) { $password = self::PASSWORD_KEPT; } else { $written[] = 'password'; $password = self::PASSWORD_COPIED; } return array( 'source' => $source->label(), 'written' => $written, 'kept' => $kept, 'password' => $password, ); } }