diff --git a/composer.json b/composer.json index 193f1c953a0e4950f3a15268957e772c20ee9513..672f320aa37e59bdd196d713529ff9fb25ce8e1a 100644 --- a/composer.json +++ b/composer.json @@ -41,16 +41,18 @@ "require-dev": { "10up/wp_mock": "*", "mockery/mockery": "*", - "phpunit/phpunit": "<7", - "wp-coding-standards/wpcs": "^2.3.0", - "squizlabs/php_codesniffer": "^3.0.2" + "phpunit/phpunit": "<7" }, "autoload": { "psr-4": { "WPDesk\\Library\\WPEmail\\": "src" } }, - "autoload-dev": {}, + "autoload-dev": { + "psr-4": { + "Tests\\Mailer\\": "tests/unit" + } + }, "extra": { "text-domain": "wp-email", "translations-folder": "lang", diff --git a/lang/pl_PL.po b/lang/pl_PL.po new file mode 100644 index 0000000000000000000000000000000000000000..b385208d0f537f4fb33c4267bf4f4bc2c6980a3a --- /dev/null +++ b/lang/pl_PL.po @@ -0,0 +1,357 @@ +msgid "" +msgstr "" +"Project-Id-Version: Plugin Template\n" +"Report-Msgid-Bugs-To: https://wordpress.org/support/plugin/flexible-" +"donation\n" +"POT-Creation-Date: 2023-02-02 09:05+0100\n" +"PO-Revision-Date: 2023-02-02 09:05+0100\n" +"Last-Translator: Krzysztof Dyszczyk <krzysztof.dyszczyk@gmail.com>\n" +"Language-Team: Polish\n" +"Language: pl_PL\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=3; plural=(n==1 ? 0 : n%10 >= 2 && n%10<=4 &&(n" +"%100<10||n%100 >= 20)? 1 : 2);\n" +"Plural-Forms: nplurals=3; plural=(n==1 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 " +"|| n%100>=20) ? 1 : 2);\n" +"X-Generator: Poedit 3.2.2\n" +"X-Loco-Version: 2.3.0; wp-5.2.2X-Poedit-Basepath: ..\n" +"X-Poedit-SourceCharset: UTF-8\n" +"X-Poedit-KeywordsList: __;_e;_n:1,2;_x:1,2c;_ex:1,2c;_nx:4c,1,2;esc_attr__;" +"esc_attr_e;esc_attr_x:1,2c;esc_html__;esc_html_e;esc_html_x:1,2c;_n_noop:1,2;" +"_nx_noop:3c,1,2;__ngettext_noop:1,2\n" +"X-Poedit-Basepath: ..\n" +"X-Poedit-SearchPath-0: .\n" +"X-Poedit-SearchPathExcluded-0: *.js\n" +"X-Poedit-SearchPathExcluded-1: vendor\n" +"X-Poedit-SearchPathExcluded-2: vendor_prefixed\n" + +#~ msgid "Flexible Donation" +#~ msgstr "Elastyczne Darowizny" + +#~ msgid "Create a donation form in conjunction with popular payment gateways" +#~ msgstr "" +#~ "Utwórz formularz darowizny w połączeniu z popularnymi bramkami płatności" + +#~ msgid "Settings" +#~ msgstr "Ustawienia" + +#~ msgid "Support" +#~ msgstr "Wsparcie" + +#~ msgid "Amount" +#~ msgstr "Kwota" + +#~ msgid "Payment status" +#~ msgstr "Status płatności" + +#~ msgid "Payment method" +#~ msgstr "Metoda płatności" + +#~ msgid "Form" +#~ msgstr "Formularz" + +#~ msgid "%s PLN" +#~ msgstr "%s PLN" + +#~ msgid "Unknown" +#~ msgstr "Nieznany" + +#~ msgid "Donation data" +#~ msgstr "Dane darowizny" + +#~ msgid "Form settings" +#~ msgstr "Ustawienia formularza" + +#~ msgid "I accept terms & conditions" +#~ msgstr "Akceptuję regulamin darowizn" + +#~ msgid "First name" +#~ msgstr "Imię" + +#~ msgid "Last name" +#~ msgstr "Nazwisko" + +#~ msgid "E-mail" +#~ msgstr "E-mail" + +#~ msgid "Comment" +#~ msgstr "Komentarz" + +#~ msgid "Terms" +#~ msgstr "Regulamin" + +#~ msgid "Send donation" +#~ msgstr "Wyślij darowiznę" + +#~ msgid "terms & conditions" +#~ msgstr "regulamin" + +#~ msgid "Bank transfer" +#~ msgstr "Przelew bankowy" + +#~ msgid "Bank Transfer Settings" +#~ msgstr "Ustawienia przelewu bankowego" + +#~ msgid "Recipient data" +#~ msgstr "Dane odbiorcy" + +#~ msgid "Company name, street, street number, post code, city etc." +#~ msgstr "Nazwa firmy, ulica, numer ulicy, kod pocztowy, miasto itp." + +#~ msgid "Account number" +#~ msgstr "Nr konta" + +#~ msgid "Bank name" +#~ msgstr "Nazwa banku" + +#~ msgid "Payment title" +#~ msgstr "Tytuł płatności" + +#~ msgid "SWIFT" +#~ msgstr "SWIFT" + +#~ msgid "Sort code" +#~ msgstr "Sort code" + +#~ msgid "Description" +#~ msgstr "Opis" + +#~ msgid "" +#~ "Please pay directly to our bank account. Please use defined payment title " +#~ "as the payment title. Your order will be processed after the payment is " +#~ "credited to our account." +#~ msgstr "" +#~ "Prosimy o wpłatę bezpośrednio na nasze konto bankowe. Jako tytuł " +#~ "płatności proszę użyć numeru zamówienia. Twoje zamówienie zostanie " +#~ "zrealizowane po zaksięgowaniu wpłaty na naszym koncie." + +#~ msgid "PayU" +#~ msgstr "PayU" + +#~ msgid "Niepoprawne zamówienie PayU!" +#~ msgstr "Niepoprawne zamówienie PayU!" + +#~ msgid "Payu Settings" +#~ msgstr "Ustawienia PayU" + +#~ msgid "POS ID" +#~ msgstr "POS ID" + +#~ msgid "MD5" +#~ msgstr "MD5" + +#~ msgid "Client ID" +#~ msgstr "Client ID" + +#~ msgid "Client secret" +#~ msgstr "Client secret" + +#~ msgid "Currency" +#~ msgstr "Waluta" + +#~ msgid "Is sandbox" +#~ msgstr "Włącz sanbox" + +#~ msgid "%1$s, Darowizna %2$s" +#~ msgstr "%1$s, Darowizna %2$s" + +#~ msgid "Darowizna nr %s" +#~ msgstr "Darowizna nr %s" + +#~ msgid "Donations" +#~ msgstr "Darowizny" + +#~ msgid "Donation" +#~ msgstr "Darowizna" + +#~ msgid "Not donations found." +#~ msgstr "Nie znaleziono darowizn." + +#~ msgid "Forms" +#~ msgstr "Formularze" + +#~ msgid "Not forms found." +#~ msgstr "Nie znaleziono formularzy." + +#~ msgid "Donation Summary" +#~ msgstr "Podsumowanie Darowizny" + +#~ msgid "Pending" +#~ msgstr "Oczekujący" + +#~ msgid "Completed" +#~ msgstr "Opłacone" + +#~ msgid "Failed" +#~ msgstr "Anulowane" + +#~ msgid "Save Changes" +#~ msgstr "Zapisz zmiany" + +#~ msgid "Summary Page" +#~ msgstr "Strona podsumowania" + +#~ msgid "Select or create summary page." +#~ msgstr "Wybierz stronę podsumowania." + +#~ msgid "Summary Page Content" +#~ msgstr "Treść strony podsumowania" + +#~ msgid "This content will be displayed on summary page." +#~ msgstr "Ta treść pojawi się na stronie podsumowania." + +#~ msgid "Customer e-mail" +#~ msgstr "E-mail darczyńcy" + +#~ msgid "Enable" +#~ msgstr "Włącz" + +#~ msgid "Subject" +#~ msgstr "Temat" + +#~ msgid "[{site_title}]: Your donation has been made" +#~ msgstr "[{site_title}]: Twoja darowizna została przekazana" + +#~ msgid "Email heading" +#~ msgstr "Nagłówek maila" + +#~ msgid "Thank you for donating" +#~ msgstr "Dziękujemy za darowiznę" + +#~ msgid "Email body" +#~ msgstr "Treść maila" + +#~ msgid "" +#~ "Hi {donation_first_name},<br/><br/>Thank you for your donation of " +#~ "£{donation_amount}.<br/><br/>{donate_summary_table}" +#~ msgstr "" +#~ "Cześć {donation_first_name},<br/><br/>Dziękujemy za darowiznę w kwocie " +#~ "{donation_amount}zł.<br/><br/>{donate_summary_table}" + +#~ msgid "Admin e-mail" +#~ msgstr "E-mail administratora" + +#~ msgid "" +#~ "Hi Admin,<br/><br/>A new donation in the amount of £{donation_amount} has " +#~ "been received.<br/><br/>You can check the details <a href=" +#~ "\"{donation_url}\">here</a>.<br/><br/>{donation_summary_table}" +#~ msgstr "" +#~ "Cześć Admin,<br/><br/>Nowa darowizna w kwocie {donation_amount}zł została " +#~ "przekazana.<br/><br/>Sprawdź szczegóły <a href=\"{donation_url}\">tutaj</" +#~ "a>.<br/><br/>{donation_summary_table}" + +#~ msgid "User Price" +#~ msgstr "Kwota użytkownika" + +#~ msgid "Minimum price:" +#~ msgstr "Kwota minimalna:" + +#~ msgid "Preset Prices" +#~ msgstr "Zdefiniowane ceny" + +#~ msgid "Add item" +#~ msgstr "Dodaj wartość" + +#~ msgid "Remove item" +#~ msgstr "Usuń wartość" + +#~ msgid "Terms and Conditions" +#~ msgstr "Regulamin" + +#~ msgid "Show terms and conditions" +#~ msgstr "Pokaż regulamin użytkownika" + +#~ msgid "Link label:" +#~ msgstr "Etykieta linku:" + +#~ msgid "Terms page:" +#~ msgstr "Strona z warunkami:" + +#~ msgid "Payment methods" +#~ msgstr "Metody płatności" + +#~ msgid "First name:" +#~ msgstr "Imię:" + +#~ msgid "Last name:" +#~ msgstr "Nazwisko:" + +#~ msgid "E-mail:" +#~ msgstr "E-mail:" + +#~ msgid "Amount:" +#~ msgstr "Kwota:" + +#~ msgid "Comment:" +#~ msgstr "Komentarz:" + +#~ msgid "Payment method:" +#~ msgstr "Metoda płatności:" + +#~ msgid "Payment status:" +#~ msgstr "Status płatności:" + +#~ msgid "Sort Code" +#~ msgstr "Sort Code" + +#~ msgid "Donation details" +#~ msgstr "Szczegóły darowizny" + +#~ msgid "Thank You Page" +#~ msgstr "Strona podziękowania" + +#~ msgid "Minimum amount" +#~ msgstr "Minimalna kwota" + +#~ msgid "Set minimum amount. Default: 1." +#~ msgstr "Ustaw kwotę minimalną. Domyślnie 10." + +#~ msgid "Maximum amount" +#~ msgstr "Maksymalna kwota" + +#~ msgid "Set maximum amount or leave empty." +#~ msgstr "Ustaw kwotę maksymalną lub pozostaw puste." + +#~ msgid "Purposes" +#~ msgstr "Cele" + +#~ msgid "Purpose" +#~ msgstr "Cek" + +#~ msgid "Search Purpose" +#~ msgstr "Szukaj celu" + +#~ msgid "Popular Purposes" +#~ msgstr "Popularne cele" + +#~ msgid "All Purposes" +#~ msgstr "Wszystki cele" + +#~ msgid "Edit Purposes" +#~ msgstr "Edytuj cel" + +#~ msgid "Update Purposes" +#~ msgstr "Aktualizuj cel" + +#~ msgid "Add New Purposes" +#~ msgstr "Dodaj nowy cel" + +#~ msgid "New Purpose Name" +#~ msgstr "Nazwa celu" + +#~ msgid "Add or remove purposes" +#~ msgstr "Dodaj lub usuń cele" + +#~ msgid "Choose from the most used purposes" +#~ msgstr "Wybierz jeden z najczęściej używanych celów" + +#~ msgid "No purposes found." +#~ msgstr "Nie znaleziono celów." + +#~ msgid "Enable email." +#~ msgstr "Włącz powiadomienie." + +#~ msgid "Define prices:" +#~ msgstr "Zdefiniuj ceny" diff --git a/phpunit-unit.xml b/phpunit-unit.xml index f3b7ead97601294e87575236952d21711e0cec07..74290fab09e79ac5a90ecbef0fb675d363c99992 100644 --- a/phpunit-unit.xml +++ b/phpunit-unit.xml @@ -1,21 +1,17 @@ <phpunit bootstrap="tests/unit/bootstrap.php"> <testsuites> - <testsuite> - <directory prefix="Test_" suffix=".php">./tests/unit/</directory> + <testsuite name="unit"> + <directory suffix="Test.php">./tests/unit/</directory> </testsuite> </testsuites> <filter> <whitelist> <directory suffix=".php">src</directory> + <exclude> + <directory suffix=".php">src/templates</directory> + </exclude> </whitelist> </filter> - <logging> - <log type="junit" target="build-coverage/report.junit.xml"/> - <log type="coverage-html" target="build-coverage/coverage" charset="UTF-8" yui="true" highlight="true"/> - <log type="coverage-text" target="build-coverage/coverage.txt"/> - <log type="coverage-clover" target="build-coverage/clover.xml"/> - </logging> - </phpunit> diff --git a/src/Abstracts/Email.php b/src/Abstracts/Email.php new file mode 100644 index 0000000000000000000000000000000000000000..d21f2bb7ec8f7d3bc2af47af6a784e82d8444959 --- /dev/null +++ b/src/Abstracts/Email.php @@ -0,0 +1,213 @@ +<?php + +namespace WPDesk\Library\WPEmail\Abstracts; + +use Exception; + +class Email { + + /** + * @var array + */ + private $recipients = []; + + /** + * @var string + */ + private $subject = ''; + + /** + * @var array + */ + private $attachments = []; + + /** + * @var string + */ + private $content = ''; + + /** + * @var array + */ + private $headers = [ 'Content-Type' => 'text/html' ]; + + /** + * @var string + */ + private $from_email; + + /** + * @var string + */ + private $from_name; + + /** + * @var array + */ + private $template_attributes; + + /** + * @param string $from_email + * + * @return self + */ + public function set_from( string $from_email ): self { + $this->from_email = $from_email; + + return $this; + } + + /** + * @return string + */ + public function get_from(): string { + return $this->from_email; + } + + /** + * @param string $from_name + * + * @return self + */ + public function set_from_name( string $from_name ): self { + $this->from_name = $from_name; + + return $this; + } + + /** + * @return string + */ + public function get_from_name(): string { + return wp_specialchars_decode( esc_html( $this->from_name ), ENT_QUOTES ); + } + + /** + * @param string $subject + * + * @return self + */ + public function set_subject( string $subject ): self { + $this->subject = $subject; + + return $this; + } + + /** + * @return string + * @throws Exception + */ + public function get_subject(): string { + return $this->subject; + } + + /** + * @param array $recipients + * + * @return self + */ + public function set_recipients( array $recipients = [] ): self { + $this->recipients = $recipients; + + return $this; + } + + /** + * @return string[] + */ + public function get_recipients(): array { + return $this->recipients; + } + + public function set_header( string $header, string $value ): self { + $this->headers[ $header ] = $value; + + return $this; + } + + /** @return string[] */ + public function get_headers(): array { + $result = []; + foreach ( $this->headers as $header => $value ) { + $result[] = "$header: $value"; + } + + return $result; + } + + public function get_header( string $header ): string { + return $this->headers[ $header ] ?? ''; + } + + /** + * @param array $attachments + * + * @return self + */ + public function set_attachments( array $attachments ): self { + $this->attachments = $attachments; + + return $this; + } + + /** + * @return array + */ + public function get_attachments(): array { + return $this->attachments; + } + + public function is_html(): bool { + return $this->get_header( 'Content-Type' ) === 'text/html'; + } + + /** + * @return string + */ + public function set_content_type( $type = 'html' ): self { + switch ( $type ) { + case 'plain': + $content_type = 'text/plain'; + break; + case 'multipart': + $content_type = 'multipart/alternative'; + break; + default: + $content_type = 'text/html'; + } + + $this->set_header( 'Content-Type', $content_type ); + + return $this; + } + + /** + * @param string $content + * + * @return self + */ + public function set_content( string $content ): self { + $this->content = $content; + + return $this; + } + + /** + * @return string + * @throws Exception + */ + public function get_content(): string { + return $this->content; + } + + public function set_template_attributes( string $name, string $value ): self { + $this->template_attributes[ $name ] = $value; + + return $this; + } + + public function get_template_attributes(): array { + return $this->template_attributes; + } + +} diff --git a/src/Abstracts/EmailAbstract.php b/src/Abstracts/EmailAbstract.php deleted file mode 100644 index 5aba38c803aee18da6a6a7df37bbbf178e5f4e80..0000000000000000000000000000000000000000 --- a/src/Abstracts/EmailAbstract.php +++ /dev/null @@ -1,122 +0,0 @@ -<?php - -namespace WPDesk\Library\WPEmail\Abstracts; - -use WPDesk\View\Renderer\Renderer; - -abstract class EmailAbstract implements EmailInterface { - - /** - * @var Renderer - */ - private $renderer; - - public function __construct( Renderer $renderer, array $recipients ) { - $this->renderer = $renderer; - $this->recipients = $recipients; - } - - /** - * Define unique email ID. - * - * @return string - */ - abstract public function get_id(): string; - - /** - * Get defined placeholders. - * - * @return string[] - */ - public function get_placeholders(): array { - return []; - } - - /** - * Get email subject. - * - * @return string - */ - public function get_subject(): string { - if ( ! $this->subject ) { - throw new \Exception( 'Empty email subject' ); - } - - return ''; - } - - /** - * Get email heading. - * - * @return string - */ - public function get_heading(): string { - return ''; - } - - /** - * Get valid recipients. - * - * @return string[] - */ - public function get_recipients(): array { - return $this->recipients; - } - - /** - * Get email headers. - * - * @return string[] - */ - public function get_headers(): array { - return []; - } - - /** - * Get email attachments. - * - * @return array - */ - public function get_attachments(): array { - return []; - } - - /** - * Get email type. - * - * @return string - */ - public function get_type(): string { - return 'text/html'; - } - - /** - * Get email content. - * - * @return string - */ - public function get_content(): string { - if ( ! $this->content ) { - throw new \Exception( 'Empty email subject' ); - } - - return ''; - } - - /** - * @return mixed - */ - public function get_object() { - return ''; - } - - /** - * Get email content. - * - * @return string - */ - public function render(): string { - return $this->renderer->render( dirname( __DIR__ ) . '/html/default.php', [ 'content' => $this->get_content(), 'heading' => $this->get_heading(), 'object' => $this->get_object() ] ); - } - -} diff --git a/src/Abstracts/EmailInterface.php b/src/Abstracts/EmailInterface.php deleted file mode 100644 index 8439a4472b69b22af289730473a349ea92c62e52..0000000000000000000000000000000000000000 --- a/src/Abstracts/EmailInterface.php +++ /dev/null @@ -1,70 +0,0 @@ -<?php - -namespace WPDesk\Library\WPEmail\Abstracts; - -interface EmailInterface { - - /** - * Define unique email ID. - * - * @return string - */ - public function get_id(): string; - - /** - * Get defined placeholders. - * - * @return array - */ - public function get_placeholders(): array; - - /** - * Get email subject. - * - * @return string - */ - public function get_subject(): string; - - /** - * Get email heading. - * - * @return string - */ - public function get_heading(): string; - - /** - * Get valid recipients. - * - * @return string[] - */ - public function get_recipients(): array; - - /** - * Get email headers. - * - * @return string[] - */ - public function get_headers(): array; - - /** - * Get email attachments. - * - * @return array - */ - public function get_attachments(): array; - - /** - * Get email type. - * - * @return string - */ - public function get_type(): string; - - /** - * Get email content. - * - * @return string - */ - public function get_content(): string; - -} diff --git a/src/Abstracts/Mailer.php b/src/Abstracts/Mailer.php new file mode 100644 index 0000000000000000000000000000000000000000..0602ff20db09f65bf87632c259a677d28c75a367 --- /dev/null +++ b/src/Abstracts/Mailer.php @@ -0,0 +1,15 @@ +<?php + +namespace WPDesk\Library\WPEmail\Abstracts; + +use WPDesk\Library\WPEmail\Exceptions\MailerException; + +interface Mailer { + + /** + * @throws MailerException + */ + public function send( Email $email ): void; + +} + diff --git a/src/EmailSender.php b/src/EmailSender.php deleted file mode 100644 index f249ad9c4e4f2d88214480633992db1186942492..0000000000000000000000000000000000000000 --- a/src/EmailSender.php +++ /dev/null @@ -1,101 +0,0 @@ -<?php - -namespace WPDesk\Library\WPEmail\Emails; - -use WPDesk\Library\WPEmail\Abstracts\EmailInterface; - -class EmailSender { - - /** - * @var EmailInterface[] - */ - private $emails = []; - - /** - * @var string - */ - private $from; - - /** - * @var string - */ - private $from_name; - - /** - * @param $from - * @param $from_name - */ - public function __construct( $from = '', $from_name = '' ) { - $this->from = $from; - $this->from_name = $from_name; - } - - public function add_email( EmailInterface $email ) { - $this->emails[ $email->get_id() ] = $email; - } - - public function get_emails(): array { - return $this->emails; - } - - /** - * WordPress callback for setting the from email - * - * @param string $email - * - * @return string - */ - public function from( $email ) { - if ( ! empty( $this->from ) && is_email( $this->from ) ) { - $email = $this->from; - } - - return $email; - } - - /** - * WordPress callback for setting the from name - * - * @param string $name - * - * @return string - */ - public function from_name( $name ) { - if ( ! empty( $this->from_name ) ) { - $name = html_entity_decode( sanitize_text_field( $this->from_name ) ); - } - - return $name; - } - - /** - * Add filters before fire wp_mail. - * - * @return void - */ - private function before_wp_mail() { - add_filter( 'wp_mail_from', array( $this, 'from' ) ); - add_filter( 'wp_mail_from_name', array( $this, 'from_name' ) ); - } - - public function send() { - foreach ( $this->get_emails() as $email ) { - $this->before_wp_mail(); - wp_mail( - $email->get_recipients(), $email->get_subject(), $email->render(), $email->get_headers(), $email->get_attachments() - ); - $this->after_wp_mail(); - } - } - - /** - * Remove filters after fire wp_mail. - * - * @return void - */ - private function after_wp_mail() { - remove_filter( 'wp_mail_from', array( $this, 'from' ) ); - remove_filter( 'wp_mail_from_name', array( $this, 'from_name' ) ); - } - -} diff --git a/src/Emails/Email.php b/src/Emails/Email.php deleted file mode 100644 index e5b499128cb50c323db83f3d943df6edfc417d51..0000000000000000000000000000000000000000 --- a/src/Emails/Email.php +++ /dev/null @@ -1,20 +0,0 @@ -<?php - -namespace WPDesk\Library\WPEmail\Emails; - -use WPDesk\Library\WPEmail\Abstracts\EmailAbstract; - -class Email extends EmailAbstract { - - const ID = 'email'; - - /** - * Define unique email ID. - * - * @return string - */ - public function get_id(): string { - return self::ID; - } - -} diff --git a/src/Exceptions/MailerException.php b/src/Exceptions/MailerException.php new file mode 100644 index 0000000000000000000000000000000000000000..6c005cd4975cdb253742004f5b71ce244db0c1b5 --- /dev/null +++ b/src/Exceptions/MailerException.php @@ -0,0 +1,16 @@ +<?php + +declare( strict_types=1 ); + +namespace WPDesk\Library\WPEmail\Exceptions; + +class MailerException extends \RuntimeException { + + public static function with_wp_error( \WP_Error $error ): self { + $errors = $error->get_error_messages( 'wp_mail_failed' ); + $message = implode( "\n", $errors ); + + return new self( sprintf( 'wp_mail() failure. Message [%s]', $message ) ); + } +} + diff --git a/src/Helpers/ColorConversion.php b/src/Helpers/ColorConversion.php new file mode 100644 index 0000000000000000000000000000000000000000..e8242ee402eaa058e124241c4dbda8d4a13337d5 --- /dev/null +++ b/src/Helpers/ColorConversion.php @@ -0,0 +1,125 @@ +<?php + +namespace WPDesk\Library\WPEmail\Helpers; + +class ColorConversion { + + /** + * Determine whether a hex color is light. + * + * @param mixed $color Color. + * + * @return bool True if a light color. + */ + public static function is_hex_light( $color ) { + $hex = str_replace( '#', '', $color ); + + $c_r = hexdec( substr( $hex, 0, 2 ) ); + $c_g = hexdec( substr( $hex, 2, 2 ) ); + $c_b = hexdec( substr( $hex, 4, 2 ) ); + + $brightness = ( ( $c_r * 299 ) + ( $c_g * 587 ) + ( $c_b * 114 ) ) / 1000; + + return $brightness > 155; + } + + public static function light_or_dark( $color, $dark = '#000000', $light = '#FFFFFF' ) { + return self::is_hex_light( $color ) ? $dark : $light; + } + + + /** + * Convert RGB to HEX. + * + * @param mixed $color Color. + * + * @return array + */ + public static function rgb_from_hex( $color ) { + $color = str_replace( '#', '', $color ); + // Convert shorthand colors to full format, e.g. "FFF" -> "FFFFFF". + $color = preg_replace( '~^(.)(.)(.)$~', '$1$1$2$2$3$3', $color ); + + $rgb = []; + $rgb['R'] = hexdec( $color[0] . $color[1] ); + $rgb['G'] = hexdec( $color[2] . $color[3] ); + $rgb['B'] = hexdec( $color[4] . $color[5] ); + + return $rgb; + } + + + /** + * Make HEX color darker. + * + * @param mixed $color Color. + * @param int $factor Darker factor. + * Defaults to 30. + * + * @return string + */ + public static function hex_darker( $color, $factor = 30 ) { + $base = self::rgb_from_hex( $color ); + $color = '#'; + + foreach ( $base as $k => $v ) { + $amount = $v / 100; + $amount = self::round( $amount * $factor ); + $new_decimal = $v - $amount; + + $new_hex_component = dechex( $new_decimal ); + if ( strlen( $new_hex_component ) < 2 ) { + $new_hex_component = '0' . $new_hex_component; + } + $color .= $new_hex_component; + } + + return $color; + } + + + /** + * Make HEX color lighter. + * + * @param mixed $color Color. + * @param int $factor Lighter factor. + * Defaults to 30. + * + * @return string + */ + public static function hex_lighter( $color, $factor = 30 ) { + $base = self::rgb_from_hex( $color ); + $color = '#'; + + foreach ( $base as $k => $v ) { + $amount = 255 - $v; + $amount = $amount / 100; + $amount = self::round( $amount * $factor ); + $new_decimal = $v + $amount; + + $new_hex_component = dechex( $new_decimal ); + if ( strlen( $new_hex_component ) < 2 ) { + $new_hex_component = '0' . $new_hex_component; + } + $color .= $new_hex_component; + } + + return $color; + } + + /** + * @param $val + * @param int $precision + * @param int $mode + * + * @return float + */ + public static function round( $val, int $precision = 0, int $mode = PHP_ROUND_HALF_UP ): float { + if ( ! is_numeric( $val ) ) { + $val = floatval( $val ); + } + + return round( $val, $precision, $mode ); + } + +} diff --git a/src/Helpers/StyleInliner.php b/src/Helpers/StyleInliner.php new file mode 100644 index 0000000000000000000000000000000000000000..9068deeddfad4b16d4da360d196d05c1035b2ae7 --- /dev/null +++ b/src/Helpers/StyleInliner.php @@ -0,0 +1,41 @@ +<?php + +namespace WPDesk\Library\WPEmail\Helpers; + +use Pelago\Emogrifier\CssInliner; +use Pelago\Emogrifier\HtmlProcessor\CssToAttributeConverter; +use Pelago\Emogrifier\HtmlProcessor\HtmlPruner; + +class StyleInliner { + + public static function inline( string $content, string $styles = '' ): string { + if ( class_exists( 'DOMDocument' ) ) { + try { + $css_inliner = CssInliner::fromHtml( $content )->inlineCss( $styles ); + $dom_document = $css_inliner->getDomDocument(); + HtmlPruner::fromDomDocument( $dom_document )->removeElementsWithDisplayNone(); + $content = CssToAttributeConverter::fromDomDocument( $dom_document ) + ->convertCssToVisualAttributes() + ->render(); + } catch ( \Exception $e ) { + error_log( $e->getMessage() ); + } + } else { + $content = '<style>' . strip_tags( $styles ) . '</style>' . $content; + } + + return $content; + } + + /** + * @return array|string|string[] + */ + protected function replace_placeholders( string $string ): string { + if ( empty( $this->placeholders ) ) { + return $string; + } + + return (string) str_replace( array_keys( $this->placeholders ), array_values( $this->placeholders ), $string ); + } + +} diff --git a/src/Integration.php b/src/Integration.php deleted file mode 100644 index 087e0fe892708d83ca74624d9bdc1fdff7388be6..0000000000000000000000000000000000000000 --- a/src/Integration.php +++ /dev/null @@ -1,31 +0,0 @@ -<?php - -namespace WPDesk\Library\WPEmail; - -use WPDesk\Library\WPEmail\Emails\AdminEmail; -use WPDesk\Library\WPEmail\Emails\Email; -use WPDesk\Library\WPEmail\Emails\EmailSender; -use WPDesk\Persistence\Adapter\WordPress\WordpressOptionsContainer; -use WPDesk\Persistence\Adapter\WordPress\WordpressTransientContainer; -use WPDesk\View\Renderer\SimplePhpRenderer; -use WPDesk\View\Resolver\ChainResolver; -use WPDesk\View\Resolver\DirResolver; -use WPDesk\View\Resolver\WPThemeResolver; - -class Integration { - - public function __construct() { - $chain_resolver = new ChainResolver(); - $chain_resolver->appendResolver( new WPThemeResolver( 'email_templates' ) ); - $chain_resolver->appendResolver( new DirResolver( __DIR__ . '/templates' ) ); - $renderer = new SimplePhpRenderer( $chain_resolver ); - - $email_sender = new EmailSender( 'email@mojastron.pl', 'Moj sklep' ); - $email = new Email( $renderer, [] ); - - $email_sender->add_email( $email ); - $email_sender->send(); - - } - -} diff --git a/src/Parser/HTMLDecorator.php b/src/Parser/HTMLDecorator.php deleted file mode 100644 index dd6bf5643386b7b71e4ccf715cecd38e42278af3..0000000000000000000000000000000000000000 --- a/src/Parser/HTMLDecorator.php +++ /dev/null @@ -1,39 +0,0 @@ -<?php - -namespace WPDesk\Library\WPEmail\Parser; - -class HTMLDecorator { - - public static function style_inline( $content ) { - if ( in_array( $this->get_content_type(), array( 'text/html', 'multipart/alternative' ), true ) ) { - ob_start(); - wc_get_template( 'emails/email-styles.php' ); - $css = apply_filters( 'woocommerce_email_styles', ob_get_clean(), $this ); - - $css_inliner_class = \Pelago\Emogrifier\CssInliner::class; - - if ( $this->supports_emogrifier() && class_exists( $css_inliner_class ) ) { - try { - $css_inliner = \Pelago\Emogrifier\CssInliner::fromHtml( $content )->inlineCss( $css ); - - do_action( 'woocommerce_emogrifier', $css_inliner, $this ); - - $dom_document = $css_inliner->getDomDocument(); - - HtmlPruner::fromDomDocument( $dom_document )->removeElementsWithDisplayNone(); - $content = CssToAttributeConverter::fromDomDocument( $dom_document ) - ->convertCssToVisualAttributes() - ->render(); - } catch ( Exception $e ) { - $logger = wc_get_logger(); - $logger->error( $e->getMessage(), array( 'source' => 'emogrifier' ) ); - } - } else { - $content = '<style type="text/css">' . $css . '</style>' . $content; - } - } - - return $content; - } - -} diff --git a/src/Template.php b/src/Template.php new file mode 100644 index 0000000000000000000000000000000000000000..c0c66bac330d0f71b66e69ed4a8d03f94b97eab2 --- /dev/null +++ b/src/Template.php @@ -0,0 +1,56 @@ +<?php + +namespace WPDesk\Library\WPEmail; + +use WPDesk\Library\WPEmail\Helpers\StyleInliner; +use WPDesk\View\Renderer\Renderer; + +class Template { + + /** + * @var Renderer + */ + private $renderer; + + /** + * @var array + */ + private $template_attributes; + + public function __construct( Renderer $renderer, array $template_attributes ) { + $this->renderer = $renderer; + $this->template_attributes = wp_parse_args( $template_attributes, $this->get_default_template_attributes() ); + } + + public function get_body( string $content ): string { + $output = $this->renderer->render( 'html/email-header', $this->template_attributes ); + $output .= $this->renderer->render( 'html/email-content', [ 'content' => $content ] ); + $output .= $this->renderer->render( 'html/email-footer', [ 'footer' => $this->template_attributes['footer'] ] ); + + return $this->css_inline( $output ); + } + + /** + * @param string $content + * + * @return mixed|string + */ + public function css_inline( string $content ): string { + $styles = $this->renderer->render( 'html/email-styles', $this->template_attributes ); + + return StyleInliner::inline( $content, $styles ); + } + + public function get_default_template_attributes(): array { + return [ + 'heading' => '', + 'logo' => '', + 'footer' => '', + 'primary' => '#d15291', + 'text' => '#303030', + 'bg' => '#f9f9f9', + 'body' => '#ffffff', + ]; + } + +} diff --git a/src/WPMailer.php b/src/WPMailer.php new file mode 100644 index 0000000000000000000000000000000000000000..9097fc757c20f9c4be16808d4d7d382b49a21ae1 --- /dev/null +++ b/src/WPMailer.php @@ -0,0 +1,87 @@ +<?php + +namespace WPDesk\Library\WPEmail; + +use Exception; +use WP_Error; +use WPDesk\Library\WPEmail\Abstracts\Email; +use WPDesk\Library\WPEmail\Abstracts\Mailer; +use WPDesk\Library\WPEmail\Exceptions\MailerException; +use WPDesk\View\Renderer\Renderer; +use WPDesk\View\Renderer\SimplePhpRenderer; +use WPDesk\View\Resolver\ChainResolver; +use WPDesk\View\Resolver\DirResolver; + +class WPMailer implements Mailer { + + /** + * @var Renderer + */ + private $renderer; + + public function __construct() { + $resolver = new ChainResolver(); + $resolver->appendResolver( new DirResolver( __DIR__ . '/templates' ) ); + $renderer = new SimplePhpRenderer( $resolver ); + $this->set_renderer( $renderer ); + } + + public function set_renderer( Renderer $renderer ) { + $this->renderer = $renderer; + } + + public function get_renderer(): Renderer { + return $this->renderer; + } + + /** @return void */ + public function send( Email $email ): void { + $mailer_from = $email->get_from(); + add_filter( + 'wp_mail_from', + $from_cb = static function ( $from ) use ( $mailer_from ) { + return $mailer_from; + } + ); + + $mailer_from_name = $email->get_from_name(); + add_filter( + 'wp_mail_from_name', + $from_name_cb = static function ( $from_name ) use ( $mailer_from_name ) { + return $mailer_from_name; + } + ); + add_action( 'wp_mail_failed', [ $this, 'catch_error' ] ); + + $email_template = new Template( $this->renderer, $email->get_template_attributes() ); + + try { + $success = wp_mail( + $email->get_recipients(), + $email->get_subject(), + $email_template->get_body( $email->get_content() ), + $email->get_headers(), + $email->get_attachments() + ); + if ( ! $success ) { + throw new MailerException( 'Count not send the mail with wp_mail()' ); + } + } catch ( Exception $e ) { + if ( $e instanceof MailerException ) { + throw $e; + } + + throw new MailerException( sprintf( 'wp_mail() failure. Original error: %s', $e->getMessage() ), 0, $e ); + } finally { + remove_action( 'wp_mail_failed', [ $this, 'catch_error' ], 99999 ); + remove_filter( 'wp_mail_from', $from_cb ); + remove_filter( 'wp_mail_from_name', $from_name_cb ); + } + } + + /** @return void */ + public function catch_error( WP_Error $error ) { + throw MailerException::with_wp_error( $error ); + } + +} diff --git a/src/tempates/html/default.php b/src/tempates/html/default.php deleted file mode 100644 index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..0000000000000000000000000000000000000000 diff --git a/src/tempates/plain/default.php b/src/tempates/plain/default.php deleted file mode 100644 index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..0000000000000000000000000000000000000000 diff --git a/templates/html/email-content.php b/templates/html/email-content.php new file mode 100644 index 0000000000000000000000000000000000000000..f9806149f14c04c3659c766ac675c6acddb3f540 --- /dev/null +++ b/templates/html/email-content.php @@ -0,0 +1,6 @@ +<?php + +$params = $params ?? []; + +?> +<?php echo wp_kses_post( $params['content'] ); ?> diff --git a/templates/html/email-footer.php b/templates/html/email-footer.php new file mode 100644 index 0000000000000000000000000000000000000000..c6b9aeaea464d764893c196bb12de68cf7d6be44 --- /dev/null +++ b/templates/html/email-footer.php @@ -0,0 +1,44 @@ +<?php +/** + * Email Footer + */ + +defined( 'ABSPATH' ) || exit; +?> + </div> + </td> + </tr> + </table> + <!-- End Content --> + </td> + </tr> + </table> + <!-- End Body --> + </td> + </tr> + </table> + </td> + </tr> + <tr> + <td align="center" valign="top"> + <!-- Footer --> + <table border="0" cellpadding="10" cellspacing="0" width="600" id="template_footer"> + <tr> + <td valign="top"> + <table border="0" cellpadding="10" cellspacing="0" width="100%"> + <tr> + <td colspan="2" valign="middle" id="credit"> + <?php echo $params['footer'] ?? ''; ?> + </td> + </tr> + </table> + </td> + </tr> + </table> + <!-- End Footer --> + </td> + </tr> + </table> + </div> + </body> +</html> diff --git a/templates/html/email-header.php b/templates/html/email-header.php new file mode 100644 index 0000000000000000000000000000000000000000..10b8088fd6d6640e3976474918f1899da872c530 --- /dev/null +++ b/templates/html/email-header.php @@ -0,0 +1,55 @@ +<?php +/** + * Email Header + */ + +if ( ! defined( 'ABSPATH' ) ) { + exit; // Exit if accessed directly +} + +$params = isset( $params ) ? $params : []; + +?> +<!DOCTYPE html> +<html <?php language_attributes(); ?>> +<head> + <meta http-equiv="Content-Type" content="text/html; charset=<?php bloginfo( 'charset' ); ?>"/> + <title><?php echo get_bloginfo( 'name', 'display' ); ?></title> +</head> +<body <?php echo is_rtl() ? 'rightmargin' : 'leftmargin'; ?>="0" marginwidth="0" topmargin="0" marginheight="0" offset="0"> +<div id="wrapper" dir="<?php echo is_rtl() ? 'rtl' : 'ltr'; ?>"> + <table border="0" cellpadding="0" cellspacing="0" height="100%" width="100%"> + <tr> + <td align="center" valign="top"> + <div id="template_header_image"> + <?php + if ( $params['logo'] ) { + echo '<p style="margin-top:0;"><img src="' . esc_url( $params['logo'] ) . '" alt="' . get_bloginfo( 'name', 'display' ) . '" /></p>'; + } + ?> + </div> + <table border="0" cellpadding="0" cellspacing="0" width="600" id="template_container"> + <tr> + <td align="center" valign="top"> + <!-- Header --> + <table border="0" cellpadding="0" cellspacing="0" width="100%" id="template_header"> + <tr> + <td id="header_wrapper"> + <h1><?php echo $params['heading'] ?? 'Header'; ?></h1> + </td> + </tr> + </table> + <!-- End Header --> + </td> + </tr> + <tr> + <td align="center" valign="top"> + <!-- Body --> + <table border="0" cellpadding="0" cellspacing="0" width="600" id="template_body"> + <tr> + <td valign="top" id="body_content"> + <!-- Content --> + <table border="0" cellpadding="20" cellspacing="0" width="100%"> + <tr> + <td valign="top"> + <div id="body_content_inner"> diff --git a/templates/html/email-styles.php b/templates/html/email-styles.php new file mode 100644 index 0000000000000000000000000000000000000000..5a204dc46b4f59fb70e272bd8733879c982db83f --- /dev/null +++ b/templates/html/email-styles.php @@ -0,0 +1,217 @@ +<?php + +use WPDesk\Library\WPEmail\Helpers\ColorConversion; + +$params = isset( $params ) ? $params : []; + +if ( ! defined( 'ABSPATH' ) ) { + exit; +} + +// Load colors. +$bg = $params['bg'] ?? '#f8f8f8'; +$body = $params['body'] ?? '#ffffff'; +$base = $params['primary'] ?? '#5c9a2c'; +$base_text = ColorConversion::light_or_dark( $base, '#171717', '#ffffff' ); +$text = $params['text'] ?? '#33333'; + +// Pick a contrasting color for links. +$link_color = ColorConversion::is_hex_light( $base ) ? $base : $base_text; + +if ( ColorConversion::is_hex_light( $body ) ) { + $link_color = ColorConversion::is_hex_light( $base ) ? $base_text : $base; +} + +$bg_darker_10 = ColorConversion::hex_darker( $bg, 10 ); +$body_darker_10 = ColorConversion::hex_darker( $body, 10 ); +$base_lighter_20 = ColorConversion::hex_lighter( $base, 20 ); +$base_lighter_40 = ColorConversion::hex_lighter( $base, 40 ); +$text_lighter_20 = ColorConversion::hex_lighter( $text, 20 ); +$text_lighter_40 = ColorConversion::hex_lighter( $text, 40 ); + +// !important; is a gmail hack to prevent styles being stripped if it doesn't like something. +// body{padding: 0;} ensures proper scale/positioning of the email in the iOS native email app. +?> + body { + padding: 0; + } + + #wrapper { + background-color: <?php echo esc_attr( $bg ); ?>; + margin: 0; + padding: 70px 0; + -webkit-text-size-adjust: none !important; + width: 100%; + } + + #template_container { + box-shadow: 0 1px 4px rgba(0, 0, 0, 0.1) !important; + background-color: <?php echo esc_attr( $body ); ?>; + border: 1px solid <?php echo esc_attr( $bg_darker_10 ); ?>; + border-radius: 3px !important; + } + + #template_header { + background-color: <?php echo esc_attr( $base ); ?>; + border-radius: 3px 3px 0 0 !important; + color: <?php echo esc_attr( $base_text ); ?>; + border-bottom: 0; + font-weight: bold; + line-height: 100%; + vertical-align: middle; + font-family: "Helvetica Neue", Helvetica, Roboto, Arial, sans-serif; + } + + #template_header h1, + #template_header h1 a { + color: <?php echo esc_attr( $base_text ); ?>; + background-color: inherit; + } + + #template_header_image img { + margin-left: 0; + margin-right: 0; + } + + #template_footer td { + padding: 0; + border-radius: 6px; + } + + #template_footer #credit { + border: 0; + color: <?php echo esc_attr( $text_lighter_40 ); ?>; + font-family: "Helvetica Neue", Helvetica, Roboto, Arial, sans-serif; + font-size: 12px; + line-height: 150%; + text-align: center; + padding: 24px 0; + } + + #template_footer #credit p { + margin: 0 0 16px; + } + + #body_content { + background-color: <?php echo esc_attr( $body ); ?>; + } + + #body_content table td { + padding: 48px 48px 32px; + } + + #body_content table td td { + padding: 12px; + } + + #body_content table td th { + padding: 12px; + } + + #body_content td ul.wc-item-meta { + font-size: small; + margin: 1em 0 0; + padding: 0; + list-style: none; + } + + #body_content td ul.wc-item-meta li { + margin: 0.5em 0 0; + padding: 0; + } + + #body_content td ul.wc-item-meta li p { + margin: 0; + } + + #body_content p { + margin: 0 0 16px; + } + + #body_content_inner { + color: <?php echo esc_attr( $text_lighter_20 ); ?>; + font-family: "Helvetica Neue", Helvetica, Roboto, Arial, sans-serif; + font-size: 14px; + line-height: 150%; + text-align: <?php echo is_rtl() ? 'right' : 'left'; ?>; + } + + .td { + color: <?php echo esc_attr( $text_lighter_20 ); ?>; + border: 1px solid <?php echo esc_attr( $body_darker_10 ); ?>; + vertical-align: middle; + } + + .address { + padding: 12px; + color: <?php echo esc_attr( $text_lighter_20 ); ?>; + border: 1px solid <?php echo esc_attr( $body_darker_10 ); ?>; + } + + .text { + color: <?php echo esc_attr( $text ); ?>; + font-family: "Helvetica Neue", Helvetica, Roboto, Arial, sans-serif; + } + + .link { + color: <?php echo esc_attr( $link_color ); ?>; + } + + #header_wrapper { + padding: 36px 48px; + display: block; + } + + h1 { + color: <?php echo esc_attr( $base ); ?>; + font-family: "Helvetica Neue", Helvetica, Roboto, Arial, sans-serif; + font-size: 30px; + font-weight: 300; + line-height: 150%; + margin: 0; + text-align: <?php echo is_rtl() ? 'right' : 'left'; ?>; + text-shadow: 0 1px 0 <?php echo esc_attr( $base_lighter_20 ); ?>; + } + + h2 { + color: <?php echo esc_attr( $base ); ?>; + display: block; + font-family: "Helvetica Neue", Helvetica, Roboto, Arial, sans-serif; + font-size: 18px; + font-weight: bold; + line-height: 130%; + margin: 0 0 18px; + text-align: <?php echo is_rtl() ? 'right' : 'left'; ?>; + } + + h3 { + color: <?php echo esc_attr( $base ); ?>; + display: block; + font-family: "Helvetica Neue", Helvetica, Roboto, Arial, sans-serif; + font-size: 16px; + font-weight: bold; + line-height: 130%; + margin: 16px 0 8px; + text-align: <?php echo is_rtl() ? 'right' : 'left'; ?>; + } + + a { + color: <?php echo esc_attr( $link_color ); ?>; + font-weight: normal; + text-decoration: underline; + } + + img { + border: none; + display: inline-block; + font-size: 14px; + font-weight: bold; + height: auto; + outline: none; + text-decoration: none; + text-transform: capitalize; + vertical-align: middle; + margin-<?php echo is_rtl() ? 'left' : 'right'; ?>: 10px; + max-width: 100%; + } +<?php diff --git a/templates/plain/email-content.php b/templates/plain/email-content.php new file mode 100644 index 0000000000000000000000000000000000000000..f9806149f14c04c3659c766ac675c6acddb3f540 --- /dev/null +++ b/templates/plain/email-content.php @@ -0,0 +1,6 @@ +<?php + +$params = $params ?? []; + +?> +<?php echo wp_kses_post( $params['content'] ); ?> diff --git a/tests/unit/Mailer/ColorTest.php b/tests/unit/Mailer/ColorTest.php new file mode 100644 index 0000000000000000000000000000000000000000..940c1b7929923abfff2dc6c915dee38f942e6721 --- /dev/null +++ b/tests/unit/Mailer/ColorTest.php @@ -0,0 +1,51 @@ +<?php + +namespace Tests\Mailer; + +use PHPUnit\Framework\TestCase; +use WPDesk\Library\WPEmail\Helpers\ColorConversion; + +class ColorTest extends TestCase { + + public function testShouldCheckHexConversion() { + $white_hex = ColorConversion::rgb_from_hex( '#FFFFFF' ); + $white_rgb = [ + 'R' => 255, + 'G' => 255, + 'B' => 255, + ]; + $this->assertSame( $white_hex, $white_rgb ); + + $black_hex = ColorConversion::rgb_from_hex( '#000000' ); + $black_rgb = [ + 'R' => 0, + 'G' => 0, + 'B' => 0, + ]; + $this->assertSame( $black_hex, $black_rgb ); + } + + + public function testShouldCheckIsHexIsDarker() { + $dark_hex = ColorConversion::is_hex_light( '#333333' ); + $this->assertFalse( $dark_hex ); + } + + + public function testShouldCheckIsHexIsLighter() { + $light_hex = ColorConversion::is_hex_light( '#f8f8f8' ); + $this->assertTrue( $light_hex ); + } + + public function testShouldMakeColorDarker() { + $dark_hex = ColorConversion::hex_darker( '#f8f8f8' ); + $this->assertSame( $dark_hex, '#aeaeae' ); + } + + + public function testShouldMakeColorLighter() { + $light_hex = ColorConversion::hex_lighter( '#f8f8f8' ); + $this->assertSame( $light_hex, '#fafafa' ); + } + +} diff --git a/tests/unit/Mailer/MailTest.php b/tests/unit/Mailer/MailTest.php new file mode 100644 index 0000000000000000000000000000000000000000..5397f3adcfed201559086f208a4a1d3ea21f0a01 --- /dev/null +++ b/tests/unit/Mailer/MailTest.php @@ -0,0 +1,87 @@ +<?php + +namespace Tests\Mailer; + +use PHPUnit\Framework\TestCase; +use WPDesk\Library\WPEmail\Abstracts\Email; + +class MailTest extends TestCase { + + const FROM = 'anna.nowak@gmail.com'; + const FROM_NAME = 'Anna Nowak'; + const RECIPIENTS = [ 'jan.nowak@gmail.com' ]; + const SUBJECT = 'Some Subject'; + const CONTENT = 'Lorem ipsum'; + + public $email; + + public function setUp(): void { + parent::setUp(); + \WP_Mock::setUp(); + $this->email = new Email(); + } + + public function testSetAndGetFromEmail(): void { + $data = \WP_Mock::userFunction('sanitize_email')->andReturn(''); + print_r( $data ); + exit; + \WP_Mock::passthruFunction( 'sanitize_email' ); + $this->email->set_from( 'john@example.com' ); + $this->assertEquals( 'john@example.com', $this->email->get_from() ); + } + + public function testSetAndGetFromName(): void { + \WP_Mock::passthruFunction( 'wp_specialchars_decode' ); + $this->email->set_from_name( 'John Doe' ); + $this->assertEquals( 'John Doe', $this->email->get_from_name() ); + } + + public function testSetAndGetSubject(): void { + $this->email->set_subject( 'Hello World' ); + $this->assertEquals( 'Hello World', $this->email->get_subject() ); + } + + public function testSetAndGetRecipients(): void { + $this->email->set_recipients( [ 'jane@example.com', 'mark@example.com' ] ); + $this->assertEquals( [ 'jane@example.com', 'mark@example.com' ], $this->email->get_recipients() ); + } + + public function testSetAndGetHeader(): void { + $this->email->set_header( 'Return-Path', 'mail@testsite.com' ); + $this->assertEquals( 'mail@testsite.com', $this->email->get_header( 'Return-Path' ) ); + } + + public function testSetAndGetAttachments(): void { + $this->email->set_attachments( [ 'file1.txt', 'file2.jpg' ] ); + $this->assertEquals( [ 'file1.txt', 'file2.jpg' ], $this->email->get_attachments() ); + } + + public function testIsHtml(): void { + $this->email->set_content_type(); + $this->assertTrue( $this->email->is_html() ); + + $this->email->set_content_type( 'plain' ); + $this->assertFalse( $this->email->is_html() ); + } + + public function testSetAndGetContentType(): void { + $this->email->set_content_type( 'html' ); + $this->assertEquals( 'text/html', $this->email->get_header( 'Content-Type' ) ); + + $this->email->set_content_type( 'plain' ); + $this->assertEquals( 'text/plain', $this->email->get_header( 'Content-Type' ) ); + + $this->email->set_content_type( 'multipart' ); + $this->assertEquals( 'multipart/alternative', $this->email->get_header( 'Content-Type' ) ); + } + + public function testSetAndGetContent(): void { + $this->email->set_content( 'Hello World' ); + $this->assertEquals( 'Hello World', $this->email->get_content() ); + } + + public function tearDown(): void { + \WP_Mock::tearDown(); + } + +} diff --git a/tests/unit/bootstrap.php b/tests/unit/bootstrap.php index 76b8109582ae17560b77a6e0499b232e09047810..38a4eb0d02d4281e3ff45d89ea6ee201737e2750 100644 --- a/tests/unit/bootstrap.php +++ b/tests/unit/bootstrap.php @@ -5,5 +5,22 @@ require_once __DIR__ . '/../../vendor/autoload.php'; +error_reporting( E_ALL ); + +if ( getenv( 'PLUGIN_PATH' ) !== false ) { + define( 'PLUGIN_PATH', getenv( 'PLUGIN_PATH' ) ); +} else { + define( 'PLUGIN_PATH', __DIR__ . DIRECTORY_SEPARATOR . '..' . DIRECTORY_SEPARATOR . '..' . DIRECTORY_SEPARATOR ); +} + +if ( getenv( 'ABSPATH' ) !== false ) { + define( 'ABSPATH', getenv( 'ABSPATH' ) ); +} else { + define( 'ABSPATH', PLUGIN_PATH . '..' . DIRECTORY_SEPARATOR . '..' . DIRECTORY_SEPARATOR ); +} + WP_Mock::setUsePatchwork( true ); WP_Mock::bootstrap(); + + +