outcome, $report->message, $result->httpStatus, $result->durationMs); } private static function sentence(PushResult $result, string $destination, string $target): self { if ($result->outcome === PushOutcome::Skipped) { // A skip carries its own reason and it is already a sentence — the // dispatcher's *"this Destination's type is not available on this // site"*, or a type's own *"the Lead carries no email address"*. return new self(PushOutcome::Skipped, (string) $result->reason); } if ($result->isFailure()) { return new self(PushOutcome::Failed, (string) $result->reason); } if ($target === '') { return new self(PushOutcome::Success, sprintf( /* translators: %s: the merchant's name for a destination. */ __('The test reached %s.', 'wconvert'), $destination )); } return new self(PushOutcome::Success, sprintf( /* translators: 1: the merchant's name for a destination, 2: what it was pointed at, such as a list name. */ __('The test reached %1$s, and landed on %2$s.', 'wconvert'), $destination, $target )); } /** * The answer to *are these credentials good* — which is a different * question from whether a push lands, and worth its own button. * * {@see DestinationType::testConnection()} throws or says nothing, which * is the convention `IntegrationInterface::connect()` set rather than a * second one invented here. */ public static function connected(string $destination): self { return new self(PushOutcome::Success, sprintf( /* translators: %s: the merchant's name for a destination. */ __('%s accepted the credentials.', 'wconvert'), $destination )); } /** * **A type with no [[Connection]] has nothing to check, and saying so is * the honest answer rather than a green tick.** * * Every free type is in this state: the MailPoet push and the lead-magnet * email both authenticate against nothing, because there is * no key to paste. Reporting success there would teach a merchant that the * button means *"this works"*, which is what the other button is for. */ public static function nothingToConnectTo(): self { return new self(PushOutcome::Skipped, __( 'This destination has no credentials to check — it runs on this site. Use “Send a test” to prove it works.', 'wconvert' )); } public static function failed(string $error): self { return new self(PushOutcome::Failed, $error); } /** * **A type this install cannot run**, which is the third state and not a * failure. * * Beside {@see self::nothingToConnectTo()} rather than assembled from a * fabricated {@see PushResult} at the call site: both buttons answer this * situation, and one of them never reaches a push at all. */ public static function unavailable(): self { return new self(PushOutcome::Skipped, PushDispatcher::unavailableHere()); } /** * `status` and `ms` only where a request was timed, so a report from a * type that makes none is byte-identical to what it always was. * * @return array{outcome: string, message: string, status?: int, ms?: int} */ public function toArray(): array { return ['outcome' => $this->outcome->value, 'message' => $this->message] + ($this->status === null ? [] : ['status' => $this->status]) + ($this->ms === null ? [] : ['ms' => $this->ms]); } }