dvadf
File manager - Edit - /home/centroca/public_html/WPCLI.tar
Back
Options/Help.php 0000644 00000013455 15252526413 0007615 0 ustar 00 <?php namespace WPMailSMTP\WPCLI\Options; /** * Renders the shared `## CONFIGURATION FLAGS` section that each WP-CLI * command appends to its own longdesc. * * @since 4.9.0 */ class Help { /** * Logical (not alphabetical) group order; mailers follow * `supported_mailers()` order, Pro groups follow their merge order. * * @since 4.9.0 * * @var string[] */ private static $group_order = [ 'mail', 'general', 'smtp', 'sendgrid', 'mailgun', 'postmark', 'sendlayer', 'resend', 'smtpcom', 'smtp2go', 'sparkpost', 'mailjet', 'mailersend', 'brevo', 'elasticemail', 'amazonses', 'mandrill', 'logs', 'rate_limit', 'control', 'alert', ]; /** * Render the `## CONFIGURATION FLAGS` section: every registered arg * enumerated under its top-level flag-segment heading. * * @since 4.9.0 * * @param Registry $registry Source of args (Lite + Pro via filter). * * @return string */ public static function configuration_flags( Registry $registry ) { // phpcs:ignore Generic.Metrics.CyclomaticComplexity.TooHigh $grouped = []; foreach ( $registry->get_args() as $arg ) { $group = explode( '.', $arg['flag'], 2 )[0]; $grouped[ $group ][] = $arg; } // Order known groups first, then anything else in registry order. $ordered = []; foreach ( self::$group_order as $group ) { if ( isset( $grouped[ $group ] ) ) { $ordered[ $group ] = $grouped[ $group ]; unset( $grouped[ $group ] ); } } foreach ( $grouped as $group => $args ) { $ordered[ $group ] = $args; } $lines = []; $lines[] = '## ' . __( 'CONFIGURATION FLAGS', 'wp-mail-smtp' ); $lines[] = ''; $lines[] = __( 'These flags accept their value as a literal (--flag=value), from a file (--flag-file=<path>), or from an environment variable (WPMS_<UPPER>).', 'wp-mail-smtp' ); $lines[] = ''; foreach ( $ordered as $group => $args ) { $lines[] = self::group_label( $group ) . ':'; $lines[] = ''; foreach ( $args as $arg ) { $lines[] = '[--' . $arg['flag'] . '=' . self::value_shape( $arg ) . ']'; $lines[] = ': ' . self::description( $arg ); $lines[] = ''; } } return rtrim( implode( "\n", $lines ) ) . "\n"; } /** * The `<value-shape>` placeholder for an arg's `--flag=...` form. * * Enum shapes stay `<enum>`; the allowed values are listed in the description. * * @since 4.9.0 * * @param array $arg Registry arg. * * @return string */ private static function value_shape( array $arg ) { $shapes = [ 'int' => '<int>', 'bool' => '<bool>', 'email' => '<email>', 'enum' => '<enum>', ]; return $shapes[ $arg['type'] ] ?? '<string>'; } /** * Assemble the description line: registry description, then any * required / required_if / sensitive notes appended in that order. * * @since 4.9.0 * * @param array $arg Registry arg. * * @return string */ private static function description( array $arg ) { $parts = [ wp_strip_all_tags( $arg['description'] ) ]; if ( ! empty( $arg['required'] ) ) { $parts[] = __( 'Required.', 'wp-mail-smtp' ); } if ( ! empty( $arg['required_if'] ) && is_array( $arg['required_if'] ) ) { $conditions = []; foreach ( $arg['required_if'] as $flag => $value ) { $conditions[] = '--' . $flag . '=' . self::format_required_if_value( $value ); } $parts[] = sprintf( /* translators: %s is a list of "--flag=value" conditions joined by " and " (e.g. "--mail.mailer=smtp and --smtp.auth=true"). Flags and values are not translated. */ __( 'Required when %s.', 'wp-mail-smtp' ), implode( ' ' . __( 'and', 'wp-mail-smtp' ) . ' ', $conditions ) ); } if ( ! empty( $arg['sensitive'] ) ) { $env_var = ! empty( $arg['env_var'] ) ? $arg['env_var'] : 'WPMS_' . strtoupper( str_replace( '.', '_', $arg['flag'] ) ); $parts[] = sprintf( /* translators: %1$s is the dotted CLI flag (e.g. smtp.pass). %2$s is the matching environment variable name (e.g. WPMS_SMTP_PASS). Flag and env var name are not translated. */ __( 'Sensitive: also accepts --%1$s-file=<path> or env var %2$s.', 'wp-mail-smtp' ), $arg['flag'], $env_var ); } return implode( ' ', $parts ); } /** * Map a group slug to its section-header label. * * Brand names stay literal (untranslated); generic labels are translatable; * unknown groups fall back to `ucfirst`. * * @since 4.9.0 * * @param string $group Group slug. * * @return string */ private static function group_label( $group ) { $labels = [ 'mail' => __( 'Mail', 'wp-mail-smtp' ), 'general' => __( 'General', 'wp-mail-smtp' ), 'smtp' => 'SMTP', 'sendgrid' => 'SendGrid', 'mailgun' => 'Mailgun', 'postmark' => 'Postmark', 'sendlayer' => 'SendLayer', 'resend' => 'Resend', 'smtpcom' => 'SMTP.com', 'smtp2go' => 'SMTP2GO', 'sparkpost' => 'SparkPost', 'mailjet' => 'Mailjet', 'mailersend' => 'MailerSend', 'brevo' => 'Brevo', 'elasticemail' => 'Elastic Email', 'amazonses' => 'Amazon SES', 'mandrill' => 'Mandrill', 'logs' => __( 'Email Logs', 'wp-mail-smtp' ), 'rate_limit' => __( 'Rate Limiting', 'wp-mail-smtp' ), 'control' => __( 'Email Controls', 'wp-mail-smtp' ), 'alert' => __( 'Alerts', 'wp-mail-smtp' ), ]; return $labels[ $group ] ?? ucfirst( $group ); } /** * Render a `required_if` value for display. Booleans become the literal * strings `true`/`false`; everything else passes through as-is. Matches * how operators type the value on the command line. * * @since 4.9.0 * * @param mixed $value Condition value. * * @return string */ private static function format_required_if_value( $value ) { if ( is_bool( $value ) ) { return $value ? 'true' : 'false'; } return (string) $value; } } Options/Registry.php 0000644 00000034200 15252526413 0010524 0 ustar 00 <?php namespace WPMailSMTP\WPCLI\Options; /** * Defines all Lite WP-CLI configuration args. Pro extends via the * `wp_mail_smtp_wpcli_options_registry_get_args` filter. * * @since 4.9.0 */ class Registry { /** * Get the full arg list (Lite + filter contributions). * * Each arg shape: * - flag (string) Operator-facing dotted flag, e.g. `smtp.host`. * - storage_path (string|null) Override for where the value lands in the * options array. Defaults to the flag. Supports dotted * notation for nesting, e.g. `alert_slack.connections.0.webhook_url`. * - type (string) string|int|bool|email|enum. * - enum (array|null) For type=enum. * - enum_storage_map (array|null) For enum types: map of operator-facing * value => storage value, applied on write and reversed on * read. Keys not in the map pass through unchanged. * - required (bool) Unconditionally required. * - required_if (array|null) Map of flag => value pairs (AND semantics). * - sensitive (bool) Masked in `option list`; accepts --flag-file / env var. * - env_var (string|null) Explicit override; else derived as WPMS_<FLAG_UPPER>. * - description (string) Help text. * * @since 4.9.0 * * @return array */ public function get_args() { $args = array_merge( $this->mail_args(), $this->general_args(), $this->smtp_args(), $this->sendgrid_args(), $this->mailgun_args(), $this->postmark_args(), $this->sendlayer_args(), $this->resend_args(), $this->smtpcom_args(), $this->smtp2go_args(), $this->sparkpost_args(), $this->mailjet_args(), $this->mailersend_args(), $this->sendinblue_args(), $this->elasticemail_args(), $this->amazonses_args(), $this->mandrill_args() ); /** * Filter the WP-CLI arg registry. Pro hooks here to register * its own flags (logs, alerts, additional connections, etc.). * * @since 4.9.0 * * @param array $args List of arg definitions. */ return apply_filters( 'wp_mail_smtp_wpcli_options_registry_get_args', $args ); // phpcs:ignore WPForms.PHP.ValidateHooks.InvalidHookName } /** * Look up a single arg by its dotted flag. * * @since 4.9.0 * * @param string $flag Dotted flag, e.g. `smtp.host`. * * @return array|null */ public function find( $flag ) { foreach ( $this->get_args() as $arg ) { if ( $arg['flag'] === $flag ) { return $arg; } } return null; } /** * The non-OAuth mailers selectable via `mail.mailer`. * * @since 4.9.0 * * @return array */ public static function supported_mailers() { return [ 'mail', 'smtp', 'sendgrid', 'mailgun', 'postmark', 'sendlayer', 'resend', 'smtpcom', 'smtp2go', 'sparkpost', 'mailjet', 'mailersend', 'brevo', 'elasticemail', 'amazonses', 'mandrill', ]; } /** * Args common to every mailer (`mail.*`). * * @since 4.9.0 * * @return array */ private function mail_args() { return [ [ 'flag' => 'mail.from_email', 'type' => 'email', 'required' => true, 'description' => __( 'From email address.', 'wp-mail-smtp' ), ], [ 'flag' => 'mail.from_name', 'type' => 'string', 'required' => true, 'description' => __( 'From name.', 'wp-mail-smtp' ), ], [ 'flag' => 'mail.mailer', 'type' => 'enum', 'enum' => self::supported_mailers(), 'enum_storage_map' => [ 'brevo' => 'sendinblue' ], 'required' => true, 'description' => sprintf( /* translators: %s is a comma-separated list of supported mailer slugs (e.g. "mail, smtp, sendgrid"). The slugs themselves are not translated. */ __( 'Mailer to use. One of: %s.', 'wp-mail-smtp' ), implode( ', ', self::supported_mailers() ) ), ], [ 'flag' => 'mail.return_path', 'type' => 'bool', 'description' => __( 'Set Return-Path to match From email.', 'wp-mail-smtp' ), ], [ 'flag' => 'mail.from_email_force', 'type' => 'bool', 'description' => __( 'Force From email on every outgoing message.', 'wp-mail-smtp' ), ], [ 'flag' => 'mail.from_name_force', 'type' => 'bool', 'description' => __( 'Force From name on every outgoing message.', 'wp-mail-smtp' ), ], ]; } /** * General plugin settings args (`general.*`). * * @since 4.9.0 * * @return array */ private function general_args() { return [ [ 'flag' => 'general.do_not_send', 'type' => 'bool', 'description' => __( 'Disable all outgoing email.', 'wp-mail-smtp' ), ], [ 'flag' => 'general.hide_am_notifications', 'storage_path' => 'general.am_notifications_hidden', 'type' => 'bool', 'description' => __( 'Hide Awesome Motive product notifications.', 'wp-mail-smtp' ), ], ]; } /** * Other SMTP mailer args (`smtp.*`). * * @since 4.9.0 * * @return array */ private function smtp_args() { $req = [ 'mail.mailer' => 'smtp' ]; $req_auth = [ 'mail.mailer' => 'smtp', 'smtp.auth' => true, ]; return [ [ 'flag' => 'smtp.host', 'type' => 'string', 'required_if' => $req, 'description' => __( 'SMTP server hostname.', 'wp-mail-smtp' ), ], [ 'flag' => 'smtp.port', 'type' => 'int', 'required_if' => $req, 'description' => __( 'SMTP server port (e.g. 25, 465, 587).', 'wp-mail-smtp' ), ], [ 'flag' => 'smtp.encryption', 'type' => 'enum', 'enum' => [ 'none', 'ssl', 'tls' ], 'description' => __( 'Encryption: none, ssl, or tls.', 'wp-mail-smtp' ), ], [ 'flag' => 'smtp.autotls', 'type' => 'bool', 'description' => __( 'Auto TLS when supported by server.', 'wp-mail-smtp' ), ], [ 'flag' => 'smtp.auth', 'type' => 'bool', 'description' => __( 'Whether the SMTP server requires authentication.', 'wp-mail-smtp' ), ], [ 'flag' => 'smtp.user', 'type' => 'string', 'required_if' => $req_auth, 'description' => __( 'SMTP username.', 'wp-mail-smtp' ), ], [ 'flag' => 'smtp.pass', 'type' => 'string', 'required_if' => $req_auth, 'sensitive' => true, 'description' => __( 'SMTP password.', 'wp-mail-smtp' ), ], ]; } /** * SendGrid mailer args (`sendgrid.*`). * * @since 4.9.0 * * @return array */ private function sendgrid_args() { $req = [ 'mail.mailer' => 'sendgrid' ]; return [ [ 'flag' => 'sendgrid.api_key', 'type' => 'string', 'required_if' => $req, 'sensitive' => true, 'description' => __( 'SendGrid API key.', 'wp-mail-smtp' ), ], [ 'flag' => 'sendgrid.domain', 'type' => 'string', 'description' => __( 'Optional sending domain.', 'wp-mail-smtp' ), ], ]; } /** * Mailgun mailer args (`mailgun.*`). * * @since 4.9.0 * * @return array */ private function mailgun_args() { $req = [ 'mail.mailer' => 'mailgun' ]; return [ [ 'flag' => 'mailgun.api_key', 'type' => 'string', 'required_if' => $req, 'sensitive' => true, 'description' => __( 'Mailgun API key.', 'wp-mail-smtp' ), ], [ 'flag' => 'mailgun.domain', 'type' => 'string', 'required_if' => $req, 'description' => __( 'Mailgun sending domain.', 'wp-mail-smtp' ), ], [ 'flag' => 'mailgun.region', 'type' => 'enum', 'enum' => [ 'US', 'EU' ], 'description' => __( 'Mailgun region (US or EU).', 'wp-mail-smtp' ), ], ]; } /** * Postmark mailer args (`postmark.*`). * * @since 4.9.0 * * @return array */ private function postmark_args() { $req = [ 'mail.mailer' => 'postmark' ]; return [ [ 'flag' => 'postmark.api_key', 'storage_path' => 'postmark.server_api_token', 'type' => 'string', 'required_if' => $req, 'sensitive' => true, 'description' => __( 'Postmark server API token.', 'wp-mail-smtp' ), ], [ 'flag' => 'postmark.message_stream', 'type' => 'string', 'description' => __( 'Optional Postmark message stream.', 'wp-mail-smtp' ), ], ]; } /** * SendLayer mailer args (`sendlayer.*`). * * @since 4.9.0 * * @return array */ private function sendlayer_args() { $req = [ 'mail.mailer' => 'sendlayer' ]; return [ [ 'flag' => 'sendlayer.api_key', 'type' => 'string', 'required_if' => $req, 'sensitive' => true, 'description' => __( 'SendLayer API key.', 'wp-mail-smtp' ), ], ]; } /** * Resend mailer args (`resend.*`). * * @since 4.9.0 * * @return array */ private function resend_args() { $req = [ 'mail.mailer' => 'resend' ]; return [ [ 'flag' => 'resend.api_key', 'type' => 'string', 'required_if' => $req, 'sensitive' => true, 'description' => __( 'Resend API key.', 'wp-mail-smtp' ), ], ]; } /** * SMTP.com mailer args (`smtpcom.*`). * * @since 4.9.0 * * @return array */ private function smtpcom_args() { $req = [ 'mail.mailer' => 'smtpcom' ]; return [ [ 'flag' => 'smtpcom.api_key', 'type' => 'string', 'required_if' => $req, 'sensitive' => true, 'description' => __( 'SMTP.com API key.', 'wp-mail-smtp' ), ], [ 'flag' => 'smtpcom.channel', 'type' => 'string', 'required_if' => $req, 'description' => __( 'SMTP.com sender channel name.', 'wp-mail-smtp' ), ], ]; } /** * SMTP2GO mailer args (`smtp2go.*`). * * @since 4.9.0 * * @return array */ private function smtp2go_args() { $req = [ 'mail.mailer' => 'smtp2go' ]; return [ [ 'flag' => 'smtp2go.api_key', 'type' => 'string', 'required_if' => $req, 'sensitive' => true, 'description' => __( 'SMTP2GO API key.', 'wp-mail-smtp' ), ], ]; } /** * SparkPost mailer args (`sparkpost.*`). * * @since 4.9.0 * * @return array */ private function sparkpost_args() { $req = [ 'mail.mailer' => 'sparkpost' ]; return [ [ 'flag' => 'sparkpost.api_key', 'type' => 'string', 'required_if' => $req, 'sensitive' => true, 'description' => __( 'SparkPost API key.', 'wp-mail-smtp' ), ], [ 'flag' => 'sparkpost.region', 'type' => 'enum', 'enum' => [ 'US', 'EU' ], 'description' => __( 'SparkPost region (US or EU).', 'wp-mail-smtp' ), ], ]; } /** * Mailjet mailer args (`mailjet.*`). * * @since 4.9.0 * * @return array */ private function mailjet_args() { $req = [ 'mail.mailer' => 'mailjet' ]; return [ [ 'flag' => 'mailjet.api_key', 'type' => 'string', 'required_if' => $req, 'sensitive' => true, 'description' => __( 'Mailjet API key.', 'wp-mail-smtp' ), ], [ 'flag' => 'mailjet.secret_key', 'type' => 'string', 'required_if' => $req, 'sensitive' => true, 'description' => __( 'Mailjet secret key.', 'wp-mail-smtp' ), ], ]; } /** * MailerSend mailer args (`mailersend.*`). * * @since 4.9.0 * * @return array */ private function mailersend_args() { $req = [ 'mail.mailer' => 'mailersend' ]; return [ [ 'flag' => 'mailersend.api_key', 'type' => 'string', 'required_if' => $req, 'sensitive' => true, 'description' => __( 'MailerSend API key.', 'wp-mail-smtp' ), ], [ 'flag' => 'mailersend.pro_plan', 'storage_path' => 'mailersend.has_pro_plan', 'type' => 'bool', 'description' => __( 'Set if your MailerSend account is on a paid plan.', 'wp-mail-smtp' ), ], ]; } /** * Brevo (formerly Sendinblue) mailer args (`brevo.*`). * * @since 4.9.0 * * @return array */ private function sendinblue_args() { $req = [ 'mail.mailer' => 'brevo' ]; return [ [ 'flag' => 'brevo.api_key', 'storage_path' => 'sendinblue.api_key', 'type' => 'string', 'required_if' => $req, 'sensitive' => true, 'description' => __( 'Brevo (formerly Sendinblue) API key.', 'wp-mail-smtp' ), ], [ 'flag' => 'brevo.domain', 'storage_path' => 'sendinblue.domain', 'type' => 'string', 'description' => __( 'Optional Brevo sending domain.', 'wp-mail-smtp' ), ], ]; } /** * Elastic Email mailer args (`elasticemail.*`). * * @since 4.9.0 * * @return array */ private function elasticemail_args() { $req = [ 'mail.mailer' => 'elasticemail' ]; return [ [ 'flag' => 'elasticemail.api_key', 'type' => 'string', 'required_if' => $req, 'sensitive' => true, 'description' => __( 'Elastic Email API key.', 'wp-mail-smtp' ), ], ]; } /** * Amazon SES mailer args (`amazonses.*`). * * @since 4.9.0 * * @return array */ private function amazonses_args() { $req = [ 'mail.mailer' => 'amazonses' ]; return [ [ 'flag' => 'amazonses.access_key_id', 'storage_path' => 'amazonses.client_id', 'type' => 'string', 'required_if' => $req, 'sensitive' => true, 'description' => __( 'AWS access key ID.', 'wp-mail-smtp' ), ], [ 'flag' => 'amazonses.secret_access_key', 'storage_path' => 'amazonses.client_secret', 'type' => 'string', 'required_if' => $req, 'sensitive' => true, 'description' => __( 'AWS secret access key.', 'wp-mail-smtp' ), ], [ 'flag' => 'amazonses.region', 'type' => 'string', 'required_if' => $req, 'description' => __( 'AWS region (e.g. us-east-1).', 'wp-mail-smtp' ), ], ]; } /** * Mandrill mailer args (`mandrill.*`). * * @since 4.9.0 * * @return array */ private function mandrill_args() { $req = [ 'mail.mailer' => 'mandrill' ]; return [ [ 'flag' => 'mandrill.api_key', 'type' => 'string', 'required_if' => $req, 'sensitive' => true, 'description' => __( 'Mandrill API key.', 'wp-mail-smtp' ), ], ]; } } Options/Writer.php 0000644 00000034163 15252526413 0010200 0 ustar 00 <?php namespace WPMailSMTP\WPCLI\Options; use WP_CLI; use WPMailSMTP\Helpers\Data; use WPMailSMTP\Options; /** * Resolves passed CLI args to values, validates them against the * registry, and writes them through Options::set(). * * @since 4.9.0 */ class Writer { /** * Registry of args this writer resolves against. * * @since 4.9.0 * * @var Registry */ private $registry; /** * Constructor. * * @since 4.9.0 * * @param Registry|null $registry Optional injected registry; defaults to a fresh instance. */ public function __construct( Registry $registry = null ) { $this->registry = $registry !== null ? $registry : new Registry(); } /** * Resolve every registry arg against the assoc args passed on the CLI. * * Precedence per arg: literal flag value > --<flag>-file=<path> > env var. * Returns a map of flag => value for flags that resolved to something. * * @since 4.9.0 * * @param array $assoc_args WP-CLI assoc args. * * @return array */ public function resolve( array $assoc_args ) { $resolved = []; foreach ( $this->registry->get_args() as $arg ) { $value = $this->resolve_one_arg( $arg, $assoc_args ); if ( $value !== null ) { $resolved[ $arg['flag'] ] = $this->coerce( $arg, $value ); } } return $resolved; } /** * Resolve a single flag by name. * * @since 4.9.0 * * @param string $flag Dotted flag (e.g. `smtp.host`). * @param array $assoc_args WP-CLI assoc args. * * @return mixed|null Coerced value, or null if not resolved. */ public function resolve_single( $flag, array $assoc_args ) { $arg = $this->registry->find( $flag ); if ( $arg === null ) { WP_CLI::error( sprintf( /* translators: %s is the unknown dotted CLI flag (e.g. smtp.host). The flag itself is not translated. */ __( 'Unknown flag: %s', 'wp-mail-smtp' ), $flag ) ); } $value = $this->resolve_one_arg( $arg, $assoc_args ); return $value === null ? null : $this->coerce( $arg, $value ); } /** * Validate the resolved map. Enforces required, required_if, type, enum. * Accumulates ALL errors and reports them in one WP_CLI::error call. * * @since 4.9.0 * * @param array $resolved Map of flag => coerced value. * * @return void */ public function validate( array $resolved ) { // phpcs:ignore Generic.Metrics.CyclomaticComplexity.MaxExceeded, Generic.Metrics.NestingLevel.MaxExceeded $errors = []; $reported_gates = []; // De-dup partial-chain "missing gate" messages across all rules. foreach ( $this->registry->get_args() as $arg ) { $flag = $arg['flag']; $present = array_key_exists( $flag, $resolved ); // Required. if ( ! empty( $arg['required'] ) && ! $present ) { $errors[] = sprintf( /* translators: %s is the dotted CLI flag (e.g. mail.from_email). The flag itself is not translated. */ __( 'Missing required flag: --%s', 'wp-mail-smtp' ), $flag ); continue; } // Required-if. if ( ! empty( $arg['required_if'] ) ) { $rule_match = $this->required_if_evaluate( $arg['required_if'], $resolved ); if ( $rule_match['all_match'] && ! $present ) { $errors[] = sprintf( /* translators: %1$s is the dotted CLI flag that is missing (e.g. smtp.host). %2$s is a human-readable condition (e.g. "--mail.mailer=smtp"). Flags and values are not translated. */ __( 'Missing required flag: --%1$s (required when %2$s)', 'wp-mail-smtp' ), $flag, $this->required_if_human( $arg['required_if'] ) ); continue; } // Partial-chain match: at least one gating flag matched but others are missing; report each missing gate once. if ( $rule_match['any_match'] && ! empty( $rule_match['missing'] ) ) { foreach ( $rule_match['missing'] as $missing_gate ) { if ( isset( $reported_gates[ $missing_gate ] ) ) { continue; } $reported_gates[ $missing_gate ] = true; $errors[] = sprintf( /* translators: %s is the dotted CLI flag that is missing (e.g. smtp.auth). The flag itself is not translated. */ __( 'Missing required flag: --%s (needed to fully specify the configuration when other gating flags are set)', 'wp-mail-smtp' ), $missing_gate ); } } } if ( ! $present ) { continue; } // Enum. if ( ( $arg['type'] ?? null ) === 'enum' && ! in_array( $resolved[ $flag ], $arg['enum'], true ) ) { $errors[] = sprintf( /* translators: %1$s is the dotted CLI flag (e.g. mail.mailer). %2$s is the value the operator provided. %3$s is a comma-separated list of allowed values. Flags and values are not translated. */ __( 'Invalid value for --%1$s: %2$s (allowed: %3$s)', 'wp-mail-smtp' ), $flag, $resolved[ $flag ], implode( ', ', $arg['enum'] ) ); } // Email type sanity check. if ( ( $arg['type'] ?? null ) === 'email' && ! is_email( $resolved[ $flag ] ) ) { $errors[] = sprintf( /* translators: %1$s is the dotted CLI flag (e.g. mail.from_email). %2$s is the value the operator provided. The flag is not translated. */ __( 'Invalid email for --%1$s: %2$s', 'wp-mail-smtp' ), $flag, $resolved[ $flag ] ); } // Int type sanity check. coerce() leaves non-numeric strings unmodified so they surface here instead of a silent 0. if ( ( $arg['type'] ?? null ) === 'int' && ! is_numeric( $resolved[ $flag ] ) ) { $errors[] = sprintf( /* translators: %1$s is the dotted CLI flag (e.g. smtp.port). %2$s is the value the operator provided. The flag is not translated. */ __( 'Invalid integer for --%1$s: %2$s', 'wp-mail-smtp' ), $flag, $resolved[ $flag ] ); } } if ( ! empty( $errors ) ) { WP_CLI::error( __( 'Configuration errors:', 'wp-mail-smtp' ) . "\n - " . implode( "\n - ", $errors ) ); } } /** * Validate a single resolved flag/value pair without applying required/required_if. * Used by `option set` where the operator is updating one key in isolation. * * @since 4.9.0 * * @param string $flag Dotted flag. * @param mixed $value Coerced value. * * @return void */ public function validate_single( $flag, $value ) { $arg = $this->registry->find( $flag ); if ( $arg === null ) { WP_CLI::error( sprintf( /* translators: %s is the unknown dotted CLI flag (e.g. smtp.host). The flag itself is not translated. */ __( 'Unknown flag: %s', 'wp-mail-smtp' ), $flag ) ); } if ( ( $arg['type'] ?? null ) === 'enum' && ! in_array( $value, $arg['enum'], true ) ) { WP_CLI::error( sprintf( /* translators: %1$s is the dotted CLI flag (e.g. mail.mailer). %2$s is the value the operator provided. %3$s is a comma-separated list of allowed values. Flags and values are not translated. */ __( 'Invalid value for --%1$s: %2$s (allowed: %3$s)', 'wp-mail-smtp' ), $flag, $value, implode( ', ', $arg['enum'] ) ) ); } if ( ( $arg['type'] ?? null ) === 'email' && ! is_email( $value ) ) { WP_CLI::error( sprintf( /* translators: %1$s is the dotted CLI flag (e.g. mail.from_email). %2$s is the value the operator provided. The flag is not translated. */ __( 'Invalid email for --%1$s: %2$s', 'wp-mail-smtp' ), $flag, $value ) ); } if ( ( $arg['type'] ?? null ) === 'int' && ! is_numeric( $value ) ) { WP_CLI::error( sprintf( /* translators: %1$s is the dotted CLI flag (e.g. smtp.port). %2$s is the value the operator provided. The flag is not translated. */ __( 'Invalid integer for --%1$s: %2$s', 'wp-mail-smtp' ), $flag, $value ) ); } } /** * Write the resolved map through Options::set(). * * Each flag is written to its `storage_path` (see ::storage_path()). Keys * shadowed by a wp-config constant are skipped and warned about: Options::set() * forces the stored value to '' whenever the constant is defined, which would * silently wipe the value. * * @since 4.9.0 * * @param array $resolved Map of flag => coerced value. * * @return array Map with two keys: 'written' (flags actually stored) and * 'shadowed' (flags skipped because a wp-config constant is set). */ public function write( array $resolved ) { // phpcs:ignore Generic.Metrics.CyclomaticComplexity.TooHigh $result = [ 'written' => [], 'shadowed' => [], ]; if ( empty( $resolved ) ) { return $result; } $options = Options::init(); $writable = []; foreach ( $resolved as $flag => $value ) { $arg = $this->registry->find( $flag ); $path = $this->storage_path( $arg !== null ? $arg : [ 'flag' => $flag ] ); // Translate operator-facing enum values to storage values before the shadow check, so it operates on storage values. if ( $arg !== null && ! empty( $arg['enum_storage_map'] ) && is_array( $arg['enum_storage_map'] ) && array_key_exists( $value, $arg['enum_storage_map'] ) ) { $value = $arg['enum_storage_map'][ $value ]; } // Shadow check is limited to the top-level group/key pair, matching WPMS's shallow WPMS_<GROUP>_<KEY> constants. $segments = explode( Data::KEY_SEPARATOR, $path, 3 ); if ( isset( $segments[0], $segments[1] ) && $options->is_const_defined( $segments[0], $segments[1] ) ) { $result['shadowed'][] = $flag; } else { $writable[ $flag ] = [ 'value' => $value, 'path' => $path, ]; } } foreach ( $result['shadowed'] as $flag ) { WP_CLI::warning( sprintf( /* translators: %s is the dotted CLI flag whose underlying option is overridden by a wp-config constant (e.g. smtp.host). The flag itself is not translated. */ __( 'A wp-config constant is defined for %s. The value was not stored. Remove the constant first, then re-run this command.', 'wp-mail-smtp' ), $flag ) ); } if ( empty( $writable ) ) { return $result; } $new = $options->get_all_raw(); foreach ( $writable as $entry ) { Data::set( $new, $entry['path'], $entry['value'] ); } $options->set( $new ); $result['written'] = array_keys( $writable ); return $result; } /** * Write a single key (used by `option set`). * * @since 4.9.0 * * @param string $flag Dotted flag. * @param mixed $value Coerced value. * * @return array See ::write(). */ public function write_single( $flag, $value ) { return $this->write( [ $flag => $value ] ); } /** * Resolve the storage path for an arg. * * Uses `storage_path` if set on the arg, otherwise falls back to the flag itself. * * @since 4.9.0 * * @param array $arg Registry arg shape. * * @return string Dotted storage path, e.g. `alert_slack_webhook.connections.0.webhook_url`. */ private function storage_path( array $arg ) { return ! empty( $arg['storage_path'] ) ? $arg['storage_path'] : $arg['flag']; } /** * Resolve a single arg's value from assoc args using * literal > --<flag>-file > env var precedence. * * @since 4.9.0 * * @param array $arg Registry arg. * @param array $assoc_args WP-CLI assoc args. * * @return string|null Raw string value, or null if not resolved. */ private function resolve_one_arg( array $arg, array $assoc_args ) { $flag = $arg['flag']; $file_flag = $flag . '-file'; if ( array_key_exists( $flag, $assoc_args ) ) { return (string) $assoc_args[ $flag ]; } if ( array_key_exists( $file_flag, $assoc_args ) ) { $path = $assoc_args[ $file_flag ]; if ( ! is_readable( $path ) ) { WP_CLI::error( sprintf( /* translators: %1$s is the dotted CLI flag with a -file suffix (e.g. smtp.pass-file). %2$s is the absolute file path that could not be read. */ __( 'Cannot read --%1$s file: %2$s', 'wp-mail-smtp' ), $file_flag, $path ) ); } return rtrim( (string) file_get_contents( $path ) ); } $env_var = $arg['env_var'] ?? ( 'WPMS_' . strtoupper( str_replace( '.', '_', $flag ) ) ); $env = getenv( $env_var ); if ( $env !== false && $env !== '' ) { return $env; } return null; } /** * Coerce a raw string value to the type declared by the arg. * * @since 4.9.0 * * @param array $arg Registry arg. * @param mixed $value Raw value. * * @return mixed Coerced value. */ private function coerce( array $arg, $value ) { // phpcs:ignore Generic.Metrics.CyclomaticComplexity.TooHigh $type = $arg['type'] ?? 'string'; if ( $type === 'bool' ) { return in_array( strtolower( (string) $value ), [ '1', 'true', 'yes', 'on' ], true ); } if ( $type === 'int' ) { // Non-numeric values returned as-is so validate() can report them instead of silently casting to 0. return is_numeric( $value ) ? (int) $value : (string) $value; } return (string) $value; } /** * Evaluate a required_if rule set against the resolved map. * * Returns: * - all_match: every gating flag is present AND equals its expected value. * - any_match: at least one gating flag is present AND equals its expected value. * - missing: gating flags that aren't present in the resolved map. * * Callers use any_match + missing to detect a partial-chain match (a likely forgotten gating flag). * * @since 4.9.0 * * @param array $rules Map of flag => expected value. * @param array $resolved Map of flag => resolved value. * * @return array */ private function required_if_evaluate( array $rules, array $resolved ) { $any_match = false; $all_match = true; $missing = []; foreach ( $rules as $flag => $expected ) { if ( ! array_key_exists( $flag, $resolved ) ) { $missing[] = $flag; $all_match = false; continue; } if ( $resolved[ $flag ] === $expected ) { $any_match = true; } else { $all_match = false; } } return [ 'all_match' => $all_match, 'any_match' => $any_match, 'missing' => $missing, ]; } /** * Render a required_if rule set as a human-readable "--flag=value and ..." string. * * @since 4.9.0 * * @param array $rules Map of flag => expected value. * * @return string */ private function required_if_human( array $rules ) { $parts = []; foreach ( $rules as $flag => $expected ) { $rendered = is_bool( $expected ) ? ( $expected ? 'true' : 'false' ) : (string) $expected; $parts[] = sprintf( '--%s=%s', $flag, $rendered ); } return implode( ' and ', $parts ); } } Commands/Manage.php 0000644 00000001322 15252526413 0010211 0 ustar 00 <?php namespace WPMailSMTP\WPCLI\Commands; use WP_CLI\Dispatcher\CommandNamespace; /** * Configure WP Mail SMTP from the command line. * * Use one of the subcommands listed below. See `wp help wp-mail-smtp <subcommand>` * for detailed help on each one. * * ## EXAMPLES * * wp wp-mail-smtp setup --mail.from_email=noreply@example.com --mail.from_name="Example" \ * --mail.mailer=smtp --smtp.host=mail.example.com --smtp.port=587 \ * --smtp.encryption=tls --smtp.auth=1 --smtp.user=foo --smtp.pass-file=/run/secret/smtp_pass * * wp wp-mail-smtp option get mail.from_email * * wp wp-mail-smtp test you@example.com * * @since 4.9.0 */ class Manage extends CommandNamespace { } Commands/Option.php 0000644 00000023656 15252526413 0010307 0 ustar 00 <?php namespace WPMailSMTP\WPCLI\Commands; use stdClass; use WP_CLI; use WP_CLI\Utils; use WPMailSMTP\Helpers\Data; use WPMailSMTP\Options; use WPMailSMTP\WPCLI\Options\Help; use WPMailSMTP\WPCLI\Options\Registry; use WPMailSMTP\WPCLI\Options\Writer; /** * Read and write individual WP Mail SMTP settings. * * @since 4.9.0 */ class Option { /** * Mask shown in place of a sensitive value's content. * * @since 4.9.0 * * @var string */ const MASK = '********'; /** * One-line summary passed to WP_CLI::add_command() as `shortdesc`. * * WP-CLI ignores the class docblock once a longdesc is passed and falls back * to boilerplate, so the summary is supplied explicitly. * * @since 4.9.0 * * @return string */ public static function shortdesc() { return __( 'Read and write individual WP Mail SMTP settings.', 'wp-mail-smtp' ); } /** * Build the longdesc passed to WP_CLI::add_command(). * * @since 4.9.0 * * @param Registry $registry Provides the configuration-flags enumeration. * * @return string */ public static function help( Registry $registry ) { $flags = Help::configuration_flags( $registry ); $action_desc = __( 'One of: get, set, list.', 'wp-mail-smtp' ); $flag_desc = __( 'Dotted flag (e.g. smtp.host). Required for get and set.', 'wp-mail-smtp' ); $value_desc = __( 'Value (required for set; can also be supplied via --value-file or env var).', 'wp-mail-smtp' ); $value_file_desc = __( 'Read a sensitive value from a file.', 'wp-mail-smtp' ); $show_sensitive_desc = __( 'Show sensitive values instead of masking them.', 'wp-mail-smtp' ); $format_desc = __( 'Output format for `list`. table | json | yaml. Default: table.', 'wp-mail-smtp' ); return <<<HELP ## OPTIONS <action> : {$action_desc} [<flag>] : {$flag_desc} [<value>] : {$value_desc} [--value-file=<path>] : {$value_file_desc} [--show-sensitive] : {$show_sensitive_desc} [--format=<format>] : {$format_desc} ## EXAMPLES wp wp-mail-smtp option get mail.from_email wp wp-mail-smtp option set smtp.host mail.example.com wp wp-mail-smtp option set sendgrid.api_key --value-file=/run/secret/sg wp wp-mail-smtp option list --format=json {$flags} HELP; } /** * Execute the `wp wp-mail-smtp option` command. * * @since 4.9.0 * * @param array $args Positional args. * @param array $assoc_args Associative args. * * @return void */ public function __invoke( $args, $assoc_args ) { $action = $args[0] ?? null; switch ( $action ) { case 'get': $this->cmd_get( $args, $assoc_args ); break; case 'set': $this->cmd_set( $args, $assoc_args ); break; case 'list': $this->cmd_list( $assoc_args ); break; default: WP_CLI::error( __( 'Action must be one of: get, set, list.', 'wp-mail-smtp' ) ); } } /** * Print a single key's value. * * `smtp.pass` is decrypted via Options::get() before display. Keys absent * from storage report "(not set)" via WP_CLI::log so empty-stdout scripts * still work. * * @since 4.9.0 * * @param array $args Positional args. * @param array $assoc_args Associative args. * * @return void */ private function cmd_get( array $args, array $assoc_args ) { // phpcs:ignore Generic.Metrics.CyclomaticComplexity.TooHigh $flag = $args[1] ?? null; if ( $flag === null ) { WP_CLI::error( __( 'Usage: wp wp-mail-smtp option get <group>.<key>', 'wp-mail-smtp' ) ); } $registry = new Registry(); $arg = $registry->find( $flag ); if ( $arg === null ) { WP_CLI::error( sprintf( /* translators: %s is the unknown dotted CLI flag (e.g. smtp.host). The flag itself is not translated. */ __( 'Unknown flag: %s', 'wp-mail-smtp' ), $flag ) ); } $storage_path = $this->storage_path( $arg ); $raw_options = get_option( Options::META_KEY, [] ); $sentinel = new stdClass(); $value = Data::get( $raw_options, $storage_path, $sentinel ); if ( $value === $sentinel ) { WP_CLI::log( __( '(not set)', 'wp-mail-smtp' ) ); return; } // smtp.pass is the only encrypted key; route it through Options::get() // so the stored ciphertext is decrypted before display. if ( $storage_path === 'smtp.pass' ) { $value = Options::init()->get( 'smtp', 'pass' ); } $value = $this->reverse_enum_storage( $arg, $value ); $display = $this->scalarize( $value ); $mask = ! empty( $arg['sensitive'] ) && ! isset( $assoc_args['show-sensitive'] ) && $display !== ''; WP_CLI::log( $mask ? self::MASK : $display ); } /** * Write a single key's value to the stored options. * * @since 4.9.0 * * @param array $args Positional args. * @param array $assoc_args Associative args. * * @return void */ private function cmd_set( array $args, array $assoc_args ) { // phpcs:ignore Generic.Metrics.CyclomaticComplexity.TooHigh $flag = $args[1] ?? null; if ( $flag === null ) { WP_CLI::error( __( 'Usage: wp wp-mail-smtp option set <group>.<key> <value>', 'wp-mail-smtp' ) ); } $registry = new Registry(); $arg = $registry->find( $flag ); if ( $arg === null ) { WP_CLI::error( sprintf( /* translators: %s is the unknown dotted CLI flag (e.g. smtp.host). The flag itself is not translated. */ __( 'Unknown flag: %s', 'wp-mail-smtp' ), $flag ) ); } // Source the value: positional > --value-file > env var. $assoc_args_for_writer = []; if ( isset( $args[2] ) ) { $assoc_args_for_writer[ $flag ] = $args[2]; } elseif ( isset( $assoc_args['value-file'] ) ) { $assoc_args_for_writer[ $flag . '-file' ] = $assoc_args['value-file']; } $writer = new Writer( $registry ); $value = $writer->resolve_single( $flag, $assoc_args_for_writer ); if ( $value === null ) { WP_CLI::error( sprintf( /* translators: %1$s is the dotted CLI flag (e.g. smtp.host). %2$s is the environment variable name the operator can use (e.g. WPMS_SMTP_HOST). Flag and env var name are not translated. */ __( 'No value provided for --%1$s (positional, --value-file, or env var %2$s).', 'wp-mail-smtp' ), $flag, $arg['env_var'] ?? ( 'WPMS_' . strtoupper( str_replace( '.', '_', $flag ) ) ) ) ); } $writer->validate_single( $flag, $value ); $result = $writer->write_single( $flag, $value ); // If the single flag we were asked to set is shadowed by a // wp-config constant, write_single() already warned and stored // nothing. Surface that as an error so shell pipelines like // `wp ... option set X Y && echo ok` don't falsely succeed. if ( empty( $result['written'] ) ) { WP_CLI::error( sprintf( /* translators: %s is the dotted CLI flag whose underlying option is overridden by a wp-config constant (e.g. smtp.host). The flag itself is not translated. */ __( 'Could not store %s — value is shadowed by a wp-config constant.', 'wp-mail-smtp' ), $flag ) ); } WP_CLI::success( sprintf( /* translators: %s is the dotted CLI flag that was updated (e.g. smtp.host). The flag itself is not translated. */ __( 'Updated %s.', 'wp-mail-smtp' ), $flag ) ); } /** * List stored option values under their operator-facing flag names. * * Only flags physically present in storage are surfaced, so output reflects * what the operator has actually set. `smtp.pass` is decrypted via * Options::get(). Sensitive values are masked unless --show-sensitive. * * @since 4.9.0 * * @param array $assoc_args Associative args. * * @return void */ private function cmd_list( array $assoc_args ) { $show_sensitive = isset( $assoc_args['show-sensitive'] ); $format = $assoc_args['format'] ?? 'table'; $registry = new Registry(); $rows = []; $raw_options = get_option( Options::META_KEY, [] ); $sentinel = new stdClass(); foreach ( $registry->get_args() as $arg ) { $storage_path = $this->storage_path( $arg ); $value = Data::get( $raw_options, $storage_path, $sentinel ); if ( $value === $sentinel ) { continue; } if ( $storage_path === 'smtp.pass' ) { $value = Options::init()->get( 'smtp', 'pass' ); } $value = $this->reverse_enum_storage( $arg, $value ); $display = $this->scalarize( $value ); if ( ! empty( $arg['sensitive'] ) && ! $show_sensitive && $display !== '' ) { $display = self::MASK; } $rows[] = [ 'flag' => $arg['flag'], 'value' => $display, ]; } Utils\format_items( $format, $rows, [ 'flag', 'value' ] ); } /** * Flatten a value to its string display form. * * @since 4.9.0 * * @param mixed $value Raw value. * * @return string */ private function scalarize( $value ) { if ( is_bool( $value ) ) { return $value ? '1' : '0'; } if ( is_array( $value ) ) { return wp_json_encode( $value ); } return (string) $value; } /** * Resolve the storage path for an arg. Mirrors Writer::storage_path() — * uses the arg's explicit `storage_path` if set, otherwise falls back to * the flag itself. * * @since 4.9.0 * * @param array $arg Registry arg. * * @return string */ private function storage_path( array $arg ) { return ! empty( $arg['storage_path'] ) ? $arg['storage_path'] : $arg['flag']; } /** * Reverse the `enum_storage_map` translation for reads: when the stored * value matches one of the map's storage values, return the corresponding * operator-facing value. Values not in the map (and non-enum args) pass * through unchanged, keeping operator-facing values consistent across * writes and reads. * * @since 4.9.0 * * @param array $arg Registry arg. * @param mixed $value Stored value. * * @return mixed */ private function reverse_enum_storage( array $arg, $value ) { if ( empty( $arg['enum_storage_map'] ) || ! is_array( $arg['enum_storage_map'] ) ) { return $value; } $reverse = array_flip( $arg['enum_storage_map'] ); if ( is_string( $value ) && array_key_exists( $value, $reverse ) ) { return $reverse[ $value ]; } return $value; } } Commands/Test.php 0000644 00000004740 15252526413 0007747 0 ustar 00 <?php namespace WPMailSMTP\WPCLI\Commands; use WP_CLI; use WPMailSMTP\Options; use WPMailSMTP\TestEmail\TestEmail; /** * Send a test email via the currently configured mailer. * * @since 4.9.0 */ class Test { /** * Send a test email via the currently configured mailer. * * ## OPTIONS * * <recipient> * : Email address to send the test message to. * * [--plain] * : Send as plain text instead of HTML. * * ## EXAMPLES * * wp wp-mail-smtp test you@example.com * wp wp-mail-smtp test you@example.com --plain * * @since 4.9.0 * * @param array $args Positional args. * @param array $assoc_args Associative args. * * @return void */ public function __invoke( $args, $assoc_args ) { // phpcs:ignore WPForms.PHP.HooksMethod.InvalidPlaceForAddingHooks -- The wp_mail_failed capture hook is paired add/remove and scoped to this single send. $recipient = $args[0] ?? null; if ( $recipient === null || ! is_email( $recipient ) ) { WP_CLI::error( __( 'Pass a valid recipient: wp wp-mail-smtp test <recipient>', 'wp-mail-smtp' ) ); } $mailer = Options::init()->get( 'mail', 'mailer' ); if ( $mailer === '' || $mailer === 'mail' ) { WP_CLI::error( __( 'No mailer is configured. Run `wp wp-mail-smtp setup ...` first.', 'wp-mail-smtp' ) ); } // Capture wp_mail_failed to surface the underlying WP_Error on failure. $captured_error = null; $capture = static function ( $wp_error ) use ( &$captured_error ) { $captured_error = $wp_error; }; add_action( 'wp_mail_failed', $capture ); $test = ( new TestEmail() )->as_html( ! isset( $assoc_args['plain'] ) ); $test->send( $recipient ); remove_action( 'wp_mail_failed', $capture ); if ( $test->is_successful() ) { WP_CLI::success( sprintf( /* translators: %1$s is the recipient email address. %2$s is the mailer slug (e.g. smtp, sendgrid). Recipient and mailer slug are not translated. */ __( 'Test email sent to %1$s via mailer "%2$s".', 'wp-mail-smtp' ), $recipient, $mailer ) ); return; } $reason = $captured_error instanceof \WP_Error ? $captured_error->get_error_message() : __( 'wp_mail() returned false (no further detail available).', 'wp-mail-smtp' ); WP_CLI::error( sprintf( /* translators: %s is the underlying error message returned by wp_mail() / the mailer (already localized or quoted verbatim from the mailer response). */ __( 'Test email failed: %s', 'wp-mail-smtp' ), $reason ) ); } } Commands/Setup.php 0000644 00000007162 15252526413 0010131 0 ustar 00 <?php namespace WPMailSMTP\WPCLI\Commands; use WP_CLI; use WPMailSMTP\Options; use WPMailSMTP\WPCLI\Options\Help; use WPMailSMTP\WPCLI\Options\Registry; use WPMailSMTP\WPCLI\Options\Writer; /** * Configure WP Mail SMTP from the command line. * * @since 4.9.0 */ class Setup { /** * One-line summary passed to WP_CLI::add_command() as `shortdesc`. * * Required because passing an explicit `longdesc` makes WP-CLI ignore the class docblock. * * @since 4.9.0 * * @return string */ public static function shortdesc() { return __( 'Configure WP Mail SMTP from the command line.', 'wp-mail-smtp' ); } /** * Build the longdesc passed to WP_CLI::add_command(). * * @since 4.9.0 * * @param Registry $registry Provides the configuration-flags enumeration. * * @return string */ public static function help( Registry $registry ) { $flags = Help::configuration_flags( $registry ); $force_desc = __( 'Skip the refusal that fires when the plugin is already configured. Does NOT wipe existing settings — only flags you pass are written.', 'wp-mail-smtp' ); return <<<HELP ## OPTIONS [--force] : {$force_desc} ## EXAMPLES wp wp-mail-smtp setup --mail.from_email=noreply@example.com --mail.from_name="Example" \\ --mail.mailer=smtp --smtp.host=mail.example.com --smtp.port=587 \\ --smtp.encryption=tls --smtp.auth=1 --smtp.user=foo \\ --smtp.pass-file=/run/secret/smtp_pass wp wp-mail-smtp setup --mail.from_email=noreply@example.com --mail.from_name="Example" \\ --mail.mailer=sendgrid --sendgrid.api_key=\$SG_KEY {$flags} HELP; } /** * Execute the `wp wp-mail-smtp setup` command. * * @since 4.9.0 * * @param array $args Positional args. * @param array $assoc_args Associative args. * * @return void */ public function __invoke( $args, $assoc_args ) { $force = isset( $assoc_args['force'] ); unset( $assoc_args['force'] ); $writer = new Writer( new Registry() ); $current_mailer = Options::init()->get( 'mail', 'mailer' ); if ( ! $force && $current_mailer !== '' && $current_mailer !== 'mail' ) { WP_CLI::error( sprintf( /* translators: %s is the currently configured mailer slug (e.g. smtp, sendgrid). The slug is not translated. */ __( "WP Mail SMTP is already configured (mailer: %s).\nUse `wp wp-mail-smtp option set <group>.<key> <value>` to change individual settings, or pass --force to override this check.", 'wp-mail-smtp' ), $current_mailer ) ); } $resolved = $writer->resolve( $assoc_args ); if ( empty( $resolved ) ) { WP_CLI::error( __( 'No configuration flags provided. Pass at least --mail.from_email, --mail.from_name, and --mail.mailer (plus the credentials for that mailer).', 'wp-mail-smtp' ) ); } $writer->validate( $resolved ); $result = $writer->write( $resolved ); // Nothing stored means every flag was shadowed by a wp-config constant. if ( empty( $result['written'] ) ) { WP_CLI::error( __( 'No settings were stored — every flag passed was shadowed by a wp-config constant. Remove the constants and re-run, or pass flags for non-shadowed settings.', 'wp-mail-smtp' ) ); } // Skip the admin Setup Wizard redirect, mirroring wizard completion. update_option( 'wp_mail_smtp_activation_prevent_redirect', true ); $mailer = $resolved['mail.mailer'] ?? Options::init()->get( 'mail', 'mailer' ); WP_CLI::success( sprintf( /* translators: %s is the configured mailer slug (e.g. smtp, sendgrid). The slug is not translated. */ __( 'Configured WP Mail SMTP (mailer: %s). Run `wp wp-mail-smtp test <recipient>` to verify.', 'wp-mail-smtp' ), $mailer ) ); } } Bootstrap.php 0000644 00000002752 15252526413 0007245 0 ustar 00 <?php namespace WPMailSMTP\WPCLI; use WP_CLI; /** * Registers WP Mail SMTP commands with WP-CLI. * * @since 4.9.0 */ class Bootstrap { /** * Register the `wp-mail-smtp` namespace and its subcommands with WP-CLI. * * @since 4.9.0 * * @return void */ public function register() { if ( ! defined( 'WP_CLI' ) || ! WP_CLI ) { return; } WP_CLI::add_command( 'wp-mail-smtp', Commands\Manage::class ); WP_CLI::add_command( 'wp-mail-smtp test', Commands\Test::class ); $setup = [ 'shortdesc' => Commands\Setup::shortdesc() ]; $option = [ 'shortdesc' => Commands\Option::shortdesc() ]; // longdesc is only displayed for help / our-namespace invocations, but // building it walks the full arg registry; skip that work otherwise. if ( $this->needs_longdesc() ) { $registry = new Options\Registry(); $setup['longdesc'] = Commands\Setup::help( $registry ); $option['longdesc'] = Commands\Option::help( $registry ); } WP_CLI::add_command( 'wp-mail-smtp setup', Commands\Setup::class, $setup ); WP_CLI::add_command( 'wp-mail-smtp option', Commands\Option::class, $option ); } /** * Whether this invocation will display a command longdesc: a * `wp wp-mail-smtp ...` command (including `--help`) or a * `wp help wp-mail-smtp ...` lookup. * * @since 4.9.0 * * @return bool */ private function needs_longdesc() { $args = WP_CLI::get_runner()->arguments; return ! empty( $args ) && ( $args[0] === 'wp-mail-smtp' || $args[0] === 'help' ); } }
dvadf
dvadf
| ver. 1.4 |
Github
|
.
| PHP 7.3.33 | Generation time: 0 |
proxy
|
phpinfo
|
Settings