Plugin Directory

Changeset 2981043


Ignore:
Timestamp:
10/19/2023 08:02:03 AM (2 years ago)
Author:
juvodesign
Message:

Update to version 3.1.0 from GitHub

Location:
juvo-mail-editor
Files:
2 added
2 deleted
82 edited
1 copied

Legend:

Unmodified
Added
Removed
  • juvo-mail-editor/tags/3.1.0/juvo-mail-editor.php

    r2793158 r2981043  
    88 * Text Domain:     juvo-mail-editor
    99 * Domain Path:     /languages
    10  * Version:         3.0.14
     10 * Version:         3.1.0
     11 * Requires at least: 6.2
     12 * Requires PHP: 7.4
    1113 */
    1214
     
    1618
    1719// If this file is called directly, abort.
    18 if ( ! defined( 'WPINC' ) ) {
     20if (!defined('WPINC')) {
    1921    die;
    2022}
     
    2325 * Plugin absolute path
    2426 */
    25 define( 'JUVO_MAIL_EDITOR_PATH', plugin_dir_path( __FILE__ ) );
    26 define( 'JUVO_MAIL_EDITOR_URL', plugin_dir_url( __FILE__ ) );
     27define('JUVO_MAIL_EDITOR_PATH', plugin_dir_path(__FILE__));
     28define('JUVO_MAIL_EDITOR_URL', plugin_dir_url(__FILE__));
    2729
    2830/**
     
    3032 * Add file check to avoid autoloading if included as sub-package
    3133 */
    32 $juvo_mail_editor_plugin_dir = plugin_dir_path( __FILE__ );
    33 if ( file_exists( $juvo_mail_editor_plugin_dir . 'vendor/autoload.php' ) ) {
    34     require plugin_dir_path( __FILE__ ) . 'vendor/autoload.php';
     34$juvo_mail_editor_plugin_dir = plugin_dir_path(__FILE__);
     35if (file_exists($juvo_mail_editor_plugin_dir . 'vendor/autoload.php')) {
     36    require plugin_dir_path(__FILE__) . 'vendor/autoload.php';
    3537}
    3638
     
    3840 * Load cmb2 manually and not by composer because file autoloading does not work
    3941 */
    40 if ( file_exists( $juvo_mail_editor_plugin_dir . 'vendor/cmb2/cmb2/init.php' ) ) {
     42if (file_exists($juvo_mail_editor_plugin_dir . 'vendor/cmb2/cmb2/init.php')) {
    4143    // Path for standalone plugin. Load from local vendor folder
    42     require plugin_dir_path( __FILE__ ) . 'vendor/cmb2/cmb2/init.php';
     44    require plugin_dir_path(__FILE__) . 'vendor/cmb2/cmb2/init.php';
    4345} else {
    4446    // Lookup vendor folder when included as library
    45     preg_match( '/(.*)vendor/U', $juvo_mail_editor_plugin_dir, $matches );
    46     if ( file_exists( $matches[1] . 'vendor/cmb2/cmb2/init.php' ) ) {
     47    preg_match('/(.*)vendor/U', $juvo_mail_editor_plugin_dir, $matches);
     48    if (file_exists($matches[1] . 'vendor/cmb2/cmb2/init.php')) {
    4749        require $matches[1] . 'vendor/cmb2/cmb2/init.php';
    4850    }
     
    5355 * This action is documented in includes/class-plugin-name-activator.php
    5456 */
    55 function juvo_mail_editor_activate() {
     57function juvo_mail_editor_activate()
     58{
    5659    Activator::activate();
    5760}
     
    6164 * This action is documented in includes/class-plugin-name-deactivator.php
    6265 */
    63 function juvo_mail_editor_deactivate() {
     66function juvo_mail_editor_deactivate()
     67{
    6468    Deactivator::deactivate();
    6569}
    6670
    67 register_activation_hook( __FILE__, 'juvo_mail_editor_activate' );
    68 register_deactivation_hook( __FILE__, 'juvo_mail_editor_deactivate' );
     71register_activation_hook(__FILE__, 'juvo_mail_editor_activate');
     72register_deactivation_hook(__FILE__, 'juvo_mail_editor_deactivate');
    6973
    7074
     
    7882 * @since    1.0.0
    7983 */
    80 function juvo_mail_editor_run() {
     84function juvo_mail_editor_run()
     85{
    8186
    82     if ( ! defined( 'ABSPATH' ) ) {
     87    if (!defined('ABSPATH')) {
    8388        return;
    8489    }
    8590
    8691    // Make sure only loaded once
    87     if ( class_exists( '\WP' ) && ! defined( 'JUVO_MAIL_EDITOR_LOADED' ) ) {
     92    if (class_exists('\WP') && !defined('JUVO_MAIL_EDITOR_LOADED')) {
    8893
    8994        $plugin = new Mail_Editor();
    9095        $plugin->run();
    9196
    92         define( 'JUVO_MAIL_EDITOR_LOADED', true );
     97        define('JUVO_MAIL_EDITOR_LOADED', true);
    9398    }
    9499
  • juvo-mail-editor/tags/3.1.0/readme.txt

    r2793158 r2981043  
    33Tags: mail,editor,framework
    44License: GPLv2 or later
    5 Tested up to: 5.9
    6 Stable tag: 3.0.14
     5Tested up to: 6.3
     6Stable tag: 3.1.0
    77
    88JUVO Mail Editor helps to modify the standard WordPress Mailings and allows adding dynamic mail triggers.
  • juvo-mail-editor/tags/3.1.0/src/Mail_Editor.php

    r2717851 r2981043  
    9595        $this->loader->add_action( 'admin_enqueue_scripts', $plugin_admin, 'enqueue_scripts' );
    9696
     97        // Init Trigger Registry
     98        Trigger_Registry::getInstance();
     99
    97100        /**
    98101         * Options
     
    121124         * Handle Sending
    122125         */
    123         add_action( "juvo_mail_editor_send", array( Relay::class, 'sendMails' ), 10, 2 );
     126        $relay = new Relay();
     127        $this->loader->add_action("juvo_mail_editor_send", $relay, 'send_mails_action_callback', 10, 2);
     128        $this->loader->add_filter("wp_mail", $relay, 'wpmail_filter_callback', 10, 1);
    124129
    125130        /**
     
    139144        $this->loader->add_action( 'wp_new_user_notification_email', new New_User(), 'prepareSend', 10, 2 );
    140145        $this->loader->add_action( 'rest_insert_user', new New_User_Rest(), 'prepareSend', 12, 1 ); // Rest
    141 
    142         /**
    143          * New User Notification Admin
    144          */
    145146        $this->loader->add_action( 'wp_new_user_notification_email_admin', new New_User_Admin(), 'prepareSend', 10, 2 );
    146147        $this->loader->add_action( 'rest_insert_user', new New_User_Admin_Rest(), 'prepareSend', 12, 1 ); // Rest
     
    149150         * Password Reset
    150151         */
    151         $this->loader->add_filter( 'retrieve_password_message', new Password_Reset(), 'prepareSend', 10, 4 );
    152 
    153         /**
    154          * Password Reset Admin
    155          */
    156         $this->loader->add_filter( 'retrieve_password_message', new Password_Reset_Admin(), 'prepareSend', 99, 4 );
     152        $this->loader->add_filter( 'retrieve_password_notification_email', new Password_Reset(), 'prepareSend', 10, 4 );
     153        $this->loader->add_filter( 'retrieve_password_notification_email', new Password_Reset_Admin(), 'prepareSend', 10, 4 );
    157154
    158155        /**
     
    160157         */
    161158        $this->loader->add_filter( 'password_change_email', new Password_Changed(), 'prepareSend', 10, 2 );
    162 
    163         /**
    164          * Password Changed Admin
    165          */
    166159        $this->loader->add_filter( 'wp_password_change_notification_email', new Password_Changed_Admin(), 'prepareSend', 10, 2 );
    167160
  • juvo-mail-editor/tags/3.1.0/src/Mail_Generator.php

    r2672700 r2981043  
    1212    public function __construct() {
    1313        add_filter( 'juvo_mail_editor_post_metabox', array( $this, 'addCustomFields' ) );
    14         add_filter( 'juvo_mail_editor_trigger', array( $this, 'registerTrigger' ) );
    1514
    1615        add_filter( "juvo_mail_editor_{$this->getTrigger()}_always_sent", array( $this, 'getAlwaysSent' ), 10, 0 );
     
    2827        );
    2928        add_filter( "juvo_mail_editor_{$this->getTrigger()}_language", array( $this, 'getLanguage' ), 1, 2 );
     29
     30        // Add current trigger to registry
     31        add_action('init', function() {
     32            Trigger_Registry::getInstance()->set( $this->getName(), $this->getTrigger(), $this->getMailArrayHook() );
     33        }, 20);
     34
     35    }
     36
     37    public function getSubject(string $subject) {
     38        return $subject;
     39    }
     40
     41    public function getMessage(string $message) {
     42        return $message;
     43    }
     44
     45    public function getRecipients(array $recipients) {
     46        return $recipients;
    3047    }
    3148
     
    4461     * This allows filters or other functions to fill or show the placeholder in the most dynamic way.
    4562     *
     63     * @param array $placeholders
    4664     * @param array|null $context
    4765     *
     
    5068    public function getPlaceholders( array $placeholders, ?array $context ): array {
    5169        return $placeholders;
    52     }
    53 
    54     /**
    55      * @param Trigger[] $triggers
    56      *
    57      * @return Trigger[]
    58      */
    59     public function registerTrigger( array $triggers ): array {
    60         $triggers[] = new Trigger( $this->getName(), $this->getTrigger() );
    61 
    62         return $triggers;
    6370    }
    6471
     
    8693
    8794    /**
     95     * Get the language an email should be sent in.
     96     *
    8897     * @param string $language
    89      * @param array $context
     98     * @param array $context the context array allows to adjust the language e.g. to the users language
    9099     *
    91100     * @return string
     
    117126
    118127    /**
     128     * WordPress has something of a default array structure that is used for wp_mail.
     129     * Often there is a hook to directly modify this array. If so set it here.
     130     *
     131     * @return string
     132     */
     133    protected function getMailArrayHook(): string {
     134        return "";
     135    }
     136
     137    /**
    119138     * Utility function that completely empties the often used mail array.
    120139     * This is most useful if hooking into native core function
  • juvo-mail-editor/tags/3.1.0/src/Mail_Trigger_TAX.php

    r2655718 r2981043  
    9292    public function registerTrigger() {
    9393
    94         $triggers = array();
    95         $errors   = new WP_Error();
     94        $errors = new WP_Error();
    9695
    97         $triggers = apply_filters( 'juvo_mail_editor_trigger', $triggers );
     96        $triggers = Trigger_Registry::getInstance()->getAll();
    9897
    9998        foreach ( $triggers as $trigger ) {
  • juvo-mail-editor/tags/3.1.0/src/Mails/Mail.php

    r2672700 r2981043  
    55interface Mail {
    66
    7     public function getSubject( string $subject ): string;
    8 
    9     public function getMessage( string $message ): string;
    10 
    11     public function getRecipients( array $recipients ): array;
    12 
    137    public function getAlwaysSent(): bool;
    148
  • juvo-mail-editor/tags/3.1.0/src/Mails/New_User.php

    r2717851 r2981043  
    44
    55use JUVO_MailEditor\Mail_Generator;
     6use JUVO_MailEditor\Trigger_Registry;
    67use WP_User;
    78
     
    1314
    1415    public function prepareSend( array $email, WP_User $user ): array {
    15         do_action( "juvo_mail_editor_send", $this->getTrigger(), [ "user" => $user ] );
    16         return $this->emptyMailArray( $email );
     16
     17        Trigger_Registry::getInstance()->get( $this->getTrigger() )
     18                        ->setContext( [ "user" => $user ] );
     19
     20        return $email;
     21    }
     22
     23    protected function getMailArrayHook(): string {
     24        return "wp_new_user_notification_email";
    1725    }
    1826
     
    3947    }
    4048
    41     public function getSubject( string $subject ): string {
    42 
    43         if ( ! empty( $subject ) ) {
    44             return $subject;
    45         }
    46 
    47         return sprintf( __( '%s Login Details', 'default' ), '{{site.name}}' );
    48     }
    49 
    50     public function getMessage( string $message ): string {
    51 
    52         if ( ! empty( $message ) ) {
    53             return $message;
    54         }
    55 
    56         $message = sprintf( __( 'Username: %s', 'default' ), '{{user.name}}' ) . "\r\n\r\n";
    57         $message .= __( 'To set your password, visit the following address:', 'default' ) . "\r\n\r\n";
    58         $message .= '{{password_reset_link}}' . "\r\n";
    59 
    60         return $message;
    61     }
    62 
    63     public function getRecipients( array $recipients ): array {
    64 
    65         if ( ! empty( $recipients ) ) {
    66             return $recipients;
    67         }
    68 
    69         return [ '{{user.user_email}}' ];
    70     }
    71 
    7249    protected function getName(): string {
    7350        return 'New User (User)';
  • juvo-mail-editor/tags/3.1.0/src/Mails/New_User_Admin.php

    r2672700 r2981043  
    44
    55use JUVO_MailEditor\Mail_Generator;
     6use JUVO_MailEditor\Trigger_Registry;
    67use WP_User;
    78
     
    1617
    1718    public function prepareSend( array $email, WP_User $user ): array {
    18         do_action( "juvo_mail_editor_send", $this->getTrigger(), [ "user" => $user ] );
     19        Trigger_Registry::getInstance()->get( $this->getTrigger() )
     20                        ->setContext( [ "user" => $user ] );
    1921
    20         return $this->emptyMailArray( $email );
     22        return $email;
    2123    }
    2224
    23     public function getSubject( string $subject ): string {
    24 
    25         if ( ! empty( $subject ) ) {
    26             return $subject;
    27         }
    28 
    29         return sprintf( __( '[%s] New User Registration', 'default' ), '{{site.name}}' );
    30     }
    31 
    32     public function getMessage( string $message ): string {
    33 
    34         if ( ! empty( $message ) ) {
    35             return $message;
    36         }
    37 
    38         $message = sprintf( __( 'New user registration on your site %s:', 'default' ), '{{site.name}}' ) . "\r\n\r\n";
    39         $message .= sprintf( __( 'Username: %s', 'default' ), '{{user.name}}' ) . "\r\n\r\n";
    40         $message .= sprintf( __( 'Email: %s', 'default' ), '{{user.user_email}}' ) . "\r\n";
    41 
    42         return $message;
    43     }
    44 
    45     public function getRecipients( array $recipients ): array {
    46 
    47         if ( ! empty( $recipients ) ) {
    48             return $recipients;
    49         }
    50 
    51         return [ '{{site.admin_email}}' ];
     25    protected function getMailArrayHook(): string {
     26        return "wp_new_user_notification_email_admin";
    5227    }
    5328
  • juvo-mail-editor/tags/3.1.0/src/Mails/Password_Changed.php

    r2791814 r2981043  
    88use JUVO_MailEditor\Mail_Trigger_TAX;
    99use JUVO_MailEditor\Mails_PT;
     10use JUVO_MailEditor\Trigger_Registry;
    1011use WP_User;
    1112
    1213class Password_Changed extends Mail_Generator {
    13 
    14     public function addCustomFields( CMB2 $cmb ): CMB2 {
    15 
    16         /** There are usecases to allow sending this mail to other recipients
    17         if ( $cmb->object_id() && has_term( $this->getTrigger(), Mail_Trigger_TAX::TAXONOMY_NAME, $cmb->object_id() ) ) {
    18 
    19             $recipients = $cmb->get_field( Mails_PT::POST_TYPE_NAME . '_recipients' );
    20             if (!empty( $recipients->value )) {
    21                 update_post_meta( $cmb->object_id(), Mails_PT::POST_TYPE_NAME . '_recipients', [] );
    22             }
    23             $cmb->remove_field( Mails_PT::POST_TYPE_NAME . '_recipients' );
    24 
    25             $cc = $cmb->get_field( Mails_PT::POST_TYPE_NAME . '_cc' );
    26             if (!empty( $cc->value )) {
    27                 update_post_meta( $cmb->object_id(), Mails_PT::POST_TYPE_NAME . '_cc', [] );
    28             }
    29             $cmb->remove_field( Mails_PT::POST_TYPE_NAME . '_cc' );
    30 
    31             $bcc = $cmb->get_field( Mails_PT::POST_TYPE_NAME . '_bcc' );
    32             if (!empty( $bcc->value )) {
    33                 update_post_meta( $cmb->object_id(), Mails_PT::POST_TYPE_NAME . '_bcc', [] );
    34             }
    35             $cmb->remove_field( Mails_PT::POST_TYPE_NAME . '_bcc' );
    36 
    37         }
    38         **/
    39 
    40         return $cmb;
    41     }
    4214
    4315    protected function getTrigger(): string {
     
    4517    }
    4618
    47     public function getSubject( string $subject ): string {
     19    public function prepareSend( array $email, array $user ): array {
    4820
    49         if ( ! empty( $subject ) ) {
    50             return $subject;
    51         }
     21        Trigger_Registry::getInstance()->get( $this->getTrigger() )
     22                        ->setContext( [ "user" => get_user_by( "ID", $user['ID'] ) ] );
    5223
    53         return sprintf( __( '%s Password Changed', 'default' ), '{{site.name}}' );
     24        return $email;
    5425    }
    5526
    56     public function getMessage( string $message ): string {
    57 
    58         if ( ! empty( $message ) ) {
    59             return $message;
    60         }
    61 
    62         $message = __(
    63             'Hi ###USERNAME###,
    64 
    65 This notice confirms that your password was changed on ###SITENAME###.
    66 
    67 If you did not change your password, please contact the Site Administrator at
    68 ###ADMIN_EMAIL###
    69 
    70 This email has been sent to ###EMAIL###
    71 
    72 Regards,
    73 All at ###SITENAME###
    74 ###SITEURL###',
    75             'default'
    76         );
    77 
    78         $message = str_replace(
    79             array(
    80                 '###USERNAME###',
    81                 '###SITENAME###',
    82                 '###ADMIN_EMAIL###',
    83                 '###SITEURL###',
    84                 '###EMAIL###',
    85             ),
    86             array( '{{user.name}}', '{{site.name}}', '{{site.admin_email}}', '{{site.url}}', '{{user.user_email}}' ),
    87             $message
    88         );
    89 
    90         return $message;
    91     }
    92 
    93     public function getRecipients( array $recipients ): array {
    94 
    95         if ( ! empty( $recipients ) ) {
    96             return $recipients;
    97         }
    98 
    99         return [ '{{user.user_email}}' ];
    100     }
    101 
    102     public function prepareSend( array $email, array $user ): array {
    103         do_action( "juvo_mail_editor_send", $this->getTrigger(), [ "user" => get_user_by( "ID", $user['ID'] ) ] );
    104 
    105         return $this->emptyMailArray( $email );
     27    protected function getMailArrayHook(): string {
     28        return "wp_password_change_notification_email";
    10629    }
    10730
  • juvo-mail-editor/tags/3.1.0/src/Mails/Password_Changed_Admin.php

    r2677983 r2981043  
    66use CMB2;
    77use JUVO_MailEditor\Mail_Generator;
     8use JUVO_MailEditor\Trigger_Registry;
    89use WP_User;
    910
     
    1819    }
    1920
    20     public function getSubject( string $subject ): string {
     21    public function prepareSend( array $email, WP_User $user ): array {
    2122
    22         if ( ! empty( $subject ) ) {
    23             return $subject;
    24         }
     23        Trigger_Registry::getInstance()->get( $this->getTrigger() )
     24                        ->setContext( [ "user" => $user ] );
    2525
    26         return sprintf( __( '%s Password Changed', 'default' ), '{{site.name}}' );
     26        return $email;
    2727    }
    2828
    29     public function getMessage( string $message ): string {
    30 
    31         if ( ! empty( $message ) ) {
    32             return $message;
    33         }
    34 
    35         return sprintf( __( 'Password changed for user: %s', 'default' ), '{{user.name}}' ) . "\r\n";
    36     }
    37 
    38     public function getRecipients( array $recipients ): array {
    39 
    40         if ( ! empty( $recipients ) ) {
    41             return $recipients;
    42         }
    43 
    44         return [ '{{site.admin_email}}' ];
    45     }
    46 
    47     public function prepareSend( array $email, WP_User $user ): array {
    48         do_action( "juvo_mail_editor_send", $this->getTrigger(), [ "user" => $user ] );
    49 
    50         return $this->emptyMailArray( $email );
     29    protected function getMailArrayHook(): string {
     30        return "retrieve_password_notification_email";
    5131    }
    5232
  • juvo-mail-editor/tags/3.1.0/src/Mails/Password_Reset.php

    r2791814 r2981043  
    44namespace JUVO_MailEditor\Mails;
    55
    6 use CMB2;
    76use JUVO_MailEditor\Mail_Generator;
    8 use JUVO_MailEditor\Mail_Trigger_TAX;
    9 use JUVO_MailEditor\Mails_PT;
     7use JUVO_MailEditor\Trigger_Registry;
    108use WP_User;
    119
     
    1614    }
    1715
    18     public function addCustomFields( CMB2 $cmb ): CMB2 {
     16    public function prepareSend( array $args, string $key, $user_login, WP_User $user ): array {
    1917
    20         /** There are usecases to allow sending this mail to other recipients
    21         if ( $cmb->object_id() && has_term( $this->getTrigger(), Mail_Trigger_TAX::TAXONOMY_NAME, $cmb->object_id() ) ) {
     18        Trigger_Registry::getInstance()->get( $this->getTrigger() )
     19            ->setContext( [ "user" => $user, 'key' => $key ] );
    2220
    23             $recipients = $cmb->get_field( Mails_PT::POST_TYPE_NAME . '_recipients' );
    24             if (!empty( $recipients->value )) {
    25                 update_post_meta( $cmb->object_id(), Mails_PT::POST_TYPE_NAME . '_recipients', [] );
    26             }
    27             $cmb->remove_field( Mails_PT::POST_TYPE_NAME . '_recipients' );
    28 
    29             $cc = $cmb->get_field( Mails_PT::POST_TYPE_NAME . '_cc' );
    30             if (!empty( $cc->value )) {
    31                 update_post_meta( $cmb->object_id(), Mails_PT::POST_TYPE_NAME . '_cc', [] );
    32             }
    33             $cmb->remove_field( Mails_PT::POST_TYPE_NAME . '_cc' );
    34 
    35             $bcc = $cmb->get_field( Mails_PT::POST_TYPE_NAME . '_bcc' );
    36             if (!empty( $bcc->value )) {
    37                 update_post_meta( $cmb->object_id(), Mails_PT::POST_TYPE_NAME . '_bcc', [] );
    38             }
    39             $cmb->remove_field( Mails_PT::POST_TYPE_NAME . '_bcc' );
    40 
    41         }
    42         **/
    43 
    44         return $cmb;
     21        return $args;
    4522    }
    4623
    47     public function prepareSend( $message, string $key, $user_login, WP_User $user ): string {
    48         do_action( "juvo_mail_editor_send", $this->getTrigger(), [ "user" => $user, 'key' => $key ] );
    49 
    50         return '';
    51     }
    52 
    53     public function getSubject( string $subject ): string {
    54 
    55         if ( ! empty( $subject ) ) {
    56             return $subject;
    57         }
    58 
    59         return __( 'Password Reset', 'juvo-mail-editor' );
    60     }
    61 
    62     public function getMessage( string $message ): string {
    63 
    64         if ( ! empty( $message ) ) {
    65             return $message;
    66         }
    67 
    68         $message = __( 'Someone has requested a password reset for the following account:', 'default' ) . "\r\n\r\n";
    69         $message .= sprintf( __( 'Site Name: %s', 'default' ), '{{ site.name }}' ) . "\r\n\r\n";
    70         $message .= sprintf( __( 'Username: %s', 'default' ), '{{ user.name }}' ) . "\r\n\r\n";
    71         $message .= __( 'If this was a mistake, ignore this email and nothing will happen.', 'default' ) . "\r\n\r\n";
    72         $message .= __( 'To reset your password, visit the following address:', 'default' ) . "\r\n\r\n";
    73         $message .= '{{password_reset_link}}' . "\r\n\r\n";
    74 
    75         return $message;
    76     }
    77 
    78     public function getRecipients( array $recipients ): array {
    79 
    80         if ( ! empty( $recipients ) ) {
    81             return $recipients;
    82         }
    83 
    84         return [ '{{user.user_email}}' ];
     24    protected function getMailArrayHook(): string {
     25        return "retrieve_password_notification_email";
    8526    }
    8627
  • juvo-mail-editor/tags/3.1.0/src/Mails/Password_Reset_Admin.php

    r2672700 r2981043  
    66use CMB2;
    77use JUVO_MailEditor\Mail_Generator;
     8use JUVO_MailEditor\Trigger_Registry;
    89use WP_User;
    910
     
    1213    public function addCustomFields( CMB2 $cmb ): CMB2 {
    1314        return $cmb;
     15    }
     16
     17    public function prepareSend( array $message, $key, $user_login, WP_User $user ): array {
     18
     19
     20        Trigger_Registry::getInstance()->get( $this->getTrigger() )
     21            ->setContext( [ "user" => $user, 'key' => $key ] );
     22
     23        // This is not a native wordpress mail. Therefore no mailhook is set and sending need to be added manually
     24        do_action( "juvo_mail_editor_send", $this->getTrigger(), [ "user" => $user ] );
     25
     26        return $message;
    1427    }
    1528
     
    4558    }
    4659
    47     public function prepareSend( $message, $key, $user_login, WP_User $user ): string {
    48         do_action( "juvo_mail_editor_send", $this->getTrigger(), [ "user" => $user, 'key' => $key ] );
    49 
    50         return '';
    51     }
    52 
    5360    protected function getTrigger(): string {
    5461        return 'password_reset_admin';
  • juvo-mail-editor/tags/3.1.0/src/Relay.php

    r2793158 r2981043  
    44namespace JUVO_MailEditor;
    55
    6 use JUVO_MailEditor\Mails\Generic;
     6use WP_HTML_Tag_Processor;
    77use WP_Post;
    8 use WP_Term;
    98
    109class Relay {
    1110
    12     /**
    13      * @var string
    14      */
    15     private $trigger;
    16 
    17     /**
    18      * @var array
    19      */
    20     private $placeholders;
    21 
    22     /**
    23      * @var WP_Term
    24      */
    25     private $term;
    26 
    27     /**
    28      * @var int[]|WP_Post[]
    29      */
    30     private $posts;
    31 
    32 
    33     private $context;
    34 
    35     /**
    36      * Relay constructor.
     11    private $args = [];
     12
     13    /**
     14     * This callback hooks into wp_mail and checks if the header indicates that this mail should be processed by juvo_mail_editor.
     15     * If so it will process the mail and return the mail array.
     16     * If multiple templates are set up for one trigger, the first one will be returned callback and all other mails will be send directly with wp_mail in "process_trigger".
     17     *
     18     * @param array $args {
     19     *      Array of the `wp_mail()` arguments.
     20     *
     21     * @return array
     22     */
     23    public function wpmail_filter_callback( array $args ): array {
     24
     25        // Trigger info lives in header. If no headers set exit early
     26        if ( empty( $args['headers'] ) ) {
     27            return $args;
     28        }
     29
     30        // Headers can be passed as array and as string
     31        if (!is_array($args['headers'])) {
     32            $args['headers'] = explode("\r\n", $args['headers']);
     33        }
     34
     35        $this->args = $args;
     36
     37        $mailArrays = [];
     38
     39        foreach ( $args['headers'] as $header ) {
     40            if ( strpos( $header, 'X-JUVO-ME-Trigger:' ) !== false ) {
     41                $value = trim( explode( ':', $header, 2 )[1] );
     42                $mailArrays = array_merge($mailArrays, $this->buildMailArrays( $value ));
     43            }
     44        }
     45
     46        // Return first mail array item;
     47        if (!empty($mailArrays)) {
     48            $this->process_trigger( $mailArrays, true );
     49            return reset($mailArrays);
     50        }
     51
     52        return $args;
     53
     54    }
     55
     56    /**
     57     * Some triggers might not use wp_mail natively. It is totally fine to directly send the mails with juvo_mail_editor.
     58     * In this case we do not hook into wp_mail but directly send the mails.
     59     *
     60     * Callback for the "juvo_mail_editor_send" action.
    3761     *
    3862     * @param string $trigger
    3963     * @param array $context
    40      * @param WP_Term $term
    41      */
    42     public function __construct( string $trigger, array $context, WP_Term $term ) {
    43         $this->trigger      = $trigger;
    44         $this->context      = $context;
    45         $this->term         = $term;
    46         $this->posts        = $this->setPostsForTrigger();
    47         $this->placeholders = $this->preparePlaceholders();
    48     }
    49 
    50     /**
    51      * @return WP_Post[]
    52      */
    53     private function setPostsForTrigger(): array {
    54 
    55         return get_posts(
    56             array(
    57                 'post_type'        => Mails_PT::POST_TYPE_NAME,
    58                 'post_status'      => 'publish',
    59                 'numberposts'      => - 1,
    60                 'suppress_filters' => false,
    61                 'tax_query'        => array(
    62                     array(
    63                         'taxonomy' => Mail_Trigger_TAX::TAXONOMY_NAME,
    64                         'field'    => 'id',
    65                         'terms'    => $this->term,
    66                     ),
    67                 ),
    68             )
    69         );
    70 
    71     }
    72 
    73     /**
    74      * @return array
    75      */
    76     public function preparePlaceholders(): array {
    77         return apply_filters( "juvo_mail_editor_{$this->trigger}_placeholders", array(), $this->context );
    78     }
    79 
    80     /**
    81      * Sends mails for all posts that are associated with the trigger.
    82      * To send mails even if not post is associated set the "alwaysSend" flag.
    83      *
    84      * If the flag is set the term defaults are used for the mailing
    85      */
    86     public static function sendMails( string $trigger, array $context = array() ) {
    87 
    88         $term = get_term_by( 'slug', $trigger, Mail_Trigger_TAX::TAXONOMY_NAME );
    89 
    90         if ( ! $term instanceof WP_Term ) {
    91             return false;
     64     *
     65     * @return void
     66     */
     67    public function send_mails_action_callback( string $trigger, array $context = array() ) {
     68
     69        // Add Context
     70        Trigger_Registry::getInstance()->get( $trigger )
     71                        ->setContext( $context );
     72
     73        $mailArrays = $this->buildMailArrays( $trigger );
     74        $this->process_trigger( $mailArrays, false );
     75    }
     76
     77    /**
     78     * Send the given mail array and optionally return the first mail array.
     79     *
     80     * @param array $mailArrays
     81     * @param bool $return_first
     82     *
     83     * @return array
     84     */
     85    public function process_trigger(  array $mailArrays, bool $return_first = false ): array {
     86
     87        // Exit early if no mails are set up
     88        if ( empty( $mailArrays ) ) {
     89            return [];
     90        }
     91
     92        // Avoid endless loop, so unhook
     93        remove_filter( 'wp_mail', array( $this, 'wpmail_filter_callback' ), 10 );
     94
     95        // Send all others
     96        $i = 0;
     97        foreach ( $mailArrays as $key => $mailArray ) {
     98
     99            // Send all but first one
     100            if ( $return_first && $i === 0 ) {
     101                $i ++;
     102                continue;
     103            }
     104
     105            // Avoid endless loop, so unhook
     106            remove_filter( 'wp_mail', array( $this, 'wpmail_filter_callback' ), 10 );
     107
     108            wp_mail( $mailArray['to'], $mailArray['subject'], $mailArray['message'], $mailArray['headers'], $mailArray['attachments'] );
     109
     110            // Add unhooked code again
     111            add_filter( 'wp_mail', array( $this, 'wpmail_filter_callback' ), 10, 1 );
     112
     113            // Remove mail from array so that either none or only one mail is returned
     114            unset( $mailArrays[ $key ] );
     115            $i ++;
     116        }
     117
     118        return $mailArrays;
     119    }
     120
     121    /**
     122     * Build mail array for each template and returns one combined array that contains all mails to be sent.
     123     * This function also takes care that translations are applied correctly for each template.
     124     *
     125     * @param string $slug
     126     *
     127     * @return array
     128     */
     129    public function buildMailArrays( string $slug ): array {
     130
     131        // Get Trigger from Registry
     132        $trigger = Trigger_Registry::getInstance()->get( $slug );
     133        if ( empty( $trigger ) ) {
     134            return [];
    92135        }
    93136
    94137        // Add Muted Capability
    95         if ( self::triggerIsMuted( $trigger ) ) {
    96             return false;
    97         }
    98 
    99         $relay = new self( $trigger, $context, $term );
     138        if ( $trigger->isMuted() ) {
     139            return [];
     140        }
    100141
    101142        // Store blog language defaults
     
    103144        $blogLocale = get_locale();
    104145
    105         if ( ! empty( $relay->posts ) ) {
    106             // If templates were created for trigger
    107 
    108             foreach ( $relay->posts as $post ) {
    109 
    110                 $locale = apply_filters( "juvo_mail_editor_{$trigger}_language", $blogLocale, $relay->context );
    111                 $lang   = locale_get_primary_language( $locale );
    112 
    113                 // Switch language context
    114                 $switched_locale = switch_to_locale( $locale );
     146        $mails     = [];
     147        $templates = $trigger->getRelatedPosts();
     148
     149        $locale = apply_filters( "juvo_mail_editor_{$trigger->getSlug()}_language", $blogLocale, $trigger->getContext() );
     150        $lang   = locale_get_primary_language( $locale );
     151
     152        // Switch language context
     153        $switched_locale = switch_to_locale( $locale );
     154
     155
     156        if ( ! $templates ) {
     157            // If not template is set up try to get mail array from hooks
     158            $mails[] = $this->buildMailArray( $trigger );
     159        } else {
     160
     161            // Build mail array for each template
     162            foreach ( $templates as $template ) {
    115163
    116164                // Get translated post with WPML
    117                 $translationId = apply_filters( 'wpml_object_id', $post->ID, Mails_PT::POST_TYPE_NAME, true, $lang );
    118                 if ( $translationId && $translationId !== $post->ID && get_post_status( $translationId ) === 'publish' ) {
    119                     $post = get_post( $translationId );
     165                $translationId = apply_filters( 'wpml_object_id', $template->ID, Mails_PT::POST_TYPE_NAME, true, $lang );
     166                if ( $translationId && $translationId !== $template->ID && get_post_status( $translationId ) === 'publish' ) {
     167                    $template = get_post( $translationId );
    120168                }
    121169
    122                 // Recipients
    123                 $recipients = $relay->prepareRecipients( $post );
    124 
    125                 // Content
    126                 $content = $relay->prepareContent( $post );
    127 
    128                 // Subject
    129                 $subject = $relay->prepareSubject( $post );
    130 
    131                 // Headers
    132                 $headers = $relay->prepareHeaders( $post );
    133 
    134                 // Attachments
    135                 $attachments = $relay->prepareAttachments( $post );
    136 
    137                 // Restore language context
    138                 if ( $switched_locale ) {
    139                     restore_previous_locale();
    140                 }
    141 
    142                 $mail = new Generic( $subject, $content, $recipients, $headers, $attachments );
    143                 $mail->send();
    144 
    145             }
    146         } else {
    147             // No templates created use trigger defaults
    148 
    149             // Some triggers might only send mails if a post is associated
    150             $alwaysSent = apply_filters( "juvo_mail_editor_{$trigger}_always_sent", false, $relay->context );
    151             if ( ! $alwaysSent ) {
    152                 return false;
    153             }
    154 
    155             $lang = apply_filters( "juvo_mail_editor_{$trigger}_language", $blogLocale, $relay->context );
    156 
    157             $switched_locale = switch_to_locale( $lang );
    158 
    159             // Fallback if not posts are found for configured trigger
    160             $content     = $relay->prepareContent();
    161             $subject     = $relay->prepareSubject();
    162             $recipients  = $relay->prepareRecipients();
    163             $headers     = $relay->prepareHeaders();
    164             $attachments = $relay->prepareAttachments();
    165 
    166             if ( $switched_locale ) {
    167                 restore_previous_locale();
    168             }
    169 
    170             $mail = new Generic( $subject, $content, $recipients, $headers, $attachments );
    171             $mail->send();
    172 
    173         }
    174 
    175         return true;
    176     }
    177 
    178     /**
    179      * Checks if the given trigger is globally muted.
    180      * Might be called manually if the mail is not send using the 'Relay' class but eg. with a filter.
    181      *
    182      * @param string $trigger
    183      *
    184      * @return bool
    185      */
    186     public static function triggerIsMuted( string $trigger ): bool {
    187         $pluginSettings = get_option( 'settings' );
    188 
    189         if ( isset( $pluginSettings['trigger_mute'] ) ) {
    190             return in_array( $trigger, $pluginSettings['trigger_mute'], true );
    191         }
    192 
    193         return false;
    194     }
    195 
    196     /**
     170                $mails[] = $this->buildMailArray( $trigger, $template );
     171            }
     172
     173        }
     174
     175        // Restore language context
     176        if ( $switched_locale ) {
     177            restore_previous_locale();
     178        }
     179
     180        return $mails;
     181
     182    }
     183
     184    /**
     185     * Builds an array with mail args in a way that WordPress uses internally
     186     *
     187     * @param Trigger $trigger
    197188     * @param WP_Post|null $post
    198189     *
    199190     * @return array
    200191     */
    201     public function prepareRecipients( WP_Post $post = null ): array {
     192    public function buildMailArray( Trigger $trigger, WP_Post $post = null ): array {
     193
     194        $new_args = [
     195            'to'          => $this->prepareRecipients( $trigger, $post ),
     196            'subject'     => $this->prepareSubject( $trigger, $post ),
     197            'message'     => $this->prepareContent( $trigger, $post ),
     198            'attachments' => $this->prepareAttachments( $trigger, $post ),
     199        ];
     200
     201        $new_args['headers'] = implode("\r\n", $this->prepareHeaders( $trigger, $post, $new_args['message'] ));
     202
     203        // Replace empty args with original args
     204        foreach ( $new_args as $key => $value ) {
     205            if ( empty( $value ) ) {
     206                $new_args[ $key ] = $this->args[ $key ] ?? "";
     207            }
     208        }
     209
     210        return $new_args;
     211    }
     212
     213    /**
     214     * @param WP_Post|null $post
     215     * @param Trigger $trigger
     216     *
     217     * @return array
     218     */
     219    public function prepareRecipients( Trigger $trigger, WP_Post $post = null ): array {
    202220
    203221        $recipients = [];
     
    208226        }
    209227
    210         $recipients = apply_filters( "juvo_mail_editor_{$this->trigger}_recipients", $recipients, $this->context );
    211 
    212         return apply_filters( 'juvo_mail_editor_after_recipients_placeholder', $this->parseToCcBcc( $recipients ), $this->trigger, $this->context );
     228        $recipients = apply_filters( "juvo_mail_editor_{$trigger->getSlug()}_recipients", $recipients, $trigger->getContext() );
     229
     230        return apply_filters( 'juvo_mail_editor_after_recipients_placeholder', $this->parseToCcBcc( $trigger, $recipients ), $trigger->getSlug(), $trigger->getContext() );
    213231    }
    214232
    215233    /**
    216234     * @param WP_Post|null $post
     235     * @param Trigger $trigger
    217236     *
    218237     * @return string
    219238     */
    220     public function prepareContent( WP_Post $post = null ): string {
     239    public function prepareContent( Trigger $trigger, WP_Post $post = null ): string {
    221240
    222241        $content = '';
     
    232251        }
    233252
    234         $content = apply_filters( "juvo_mail_editor_{$this->trigger}_message", $content, $this->context );
    235         $content = Placeholder::replacePlaceholder( $this->placeholders, $content, $this->context );
    236         $content = apply_filters( 'juvo_mail_editor_after_content_placeholder', $content, $this->trigger, $this->context );
    237 
    238         $content = $this->setContentType( $content );
     253        $content = apply_filters( "juvo_mail_editor_{$trigger->getSlug()}_message", $content, $trigger->getContext() );
     254        $content = Placeholder::replacePlaceholder( $this->preparePlaceholders( $trigger ), $content, $trigger->getContext() );
     255
     256        // If html tags present use wpautop to automagically fix linebreaks
     257        $p = new WP_HTML_Tag_Processor( $content );
     258        if ($p->next_tag()) {
     259            $content = wpautop( $content );
     260        }
     261
     262        $content = apply_filters( 'juvo_mail_editor_after_content_placeholder', $content, $trigger->getSlug(), $trigger->getContext() );
    239263
    240264        return $content;
    241265    }
    242266
    243     public function setContentType( string $message ): string {
    244 
    245         $type    = 'text/html';
    246 
    247         // If plaintext make linebreaks html compliant
    248         if($message == strip_tags($message)){
    249             $message = wpautop( $message );
    250         }
    251 
    252         add_filter(
    253             'wp_mail_content_type',
    254             function( $content_type ) use ( $type ) {
    255                 return $type;
    256             },
    257             10
    258         );
    259 
    260         return $message;
    261     }
    262 
    263267    /**
    264268     * @param WP_Post|null $post
     269     * @param Trigger $trigger
    265270     *
    266271     * @return string
    267272     */
    268     public function prepareSubject( WP_Post $post = null ): string {
     273    public function prepareSubject( Trigger $trigger, WP_Post $post = null ): string {
    269274
    270275        $subject = '';
     
    275280        }
    276281
    277         $subject = apply_filters( "juvo_mail_editor_{$this->trigger}_subject", $subject, $this->context );
    278         $subject = Placeholder::replacePlaceholder( $this->placeholders, $subject, $this->context );
    279 
    280         return apply_filters( 'juvo_mail_editor_after_subject_placeholder', $subject, $this->trigger, $this->context );
    281     }
    282 
    283     /**
    284      * @return array
    285      */
    286     public function getPlaceholders(): array {
    287         return $this->placeholders;
    288     }
    289 
    290     /**
    291      * @return WP_Term
    292      */
    293     public function getTerm() {
    294         return $this->term;
    295     }
    296 
    297     /**
    298      * @return WP_Post[]
    299      */
    300     public function getPosts(): array {
    301         return $this->posts;
     282        $subject = apply_filters( "juvo_mail_editor_{$trigger->getSlug()}_subject", $subject, $trigger->getContext() );
     283        $subject = Placeholder::replacePlaceholder( $this->preparePlaceholders( $trigger ), $subject, $trigger->getContext() );
     284
     285        return apply_filters( 'juvo_mail_editor_after_subject_placeholder', $subject, $trigger->getSlug(), $trigger->getContext() );
     286    }
     287
     288    /**
     289     * @param Trigger $trigger
     290     *
     291     * @return array
     292     */
     293    public function preparePlaceholders( Trigger $trigger ): array {
     294        return apply_filters( "juvo_mail_editor_{$trigger->getSlug()}_placeholders", array(), $trigger->getContext() );
    302295    }
    303296
    304297    /**
    305298     * Sets custom headers.
    306      * By defaults adds headers to identify mail-editor mails through wordpress
     299     * By defaults adds headers to identify mail-editor mails through WordPress
    307300     *
    308301     * @param WP_Post|null $post
     
    310303     * @return mixed|void
    311304     */
    312     private function prepareHeaders( WP_Post $post = null ) {
    313 
    314         $headers[] = "X-JUVO-ME-Trigger: {$this->trigger}";
     305    private function prepareHeaders( Trigger $trigger, WP_Post $post = null, string $content = "" ) {
     306
     307        $headers[] = "X-JUVO-ME-Trigger: {$trigger->getSlug()}";
    315308
    316309        if ( $post ) {
     
    318311        }
    319312
     313        // Use new Tag Processor API to dynamically set content type
     314        if (!empty($content)) {
     315            $p = new WP_HTML_Tag_Processor( $content );
     316            if ($p->next_tag()) {
     317                $headers[] = "Content-Type: text/html; charset=UTF-8";
     318            }
     319        }
     320
    320321        // Add CC and BCC
    321         $headers = $this->prepareCc( $headers, $post );
    322         $headers = $this->prepareBcc( $headers, $post );
    323 
    324         return apply_filters( "juvo_mail_editor_{$this->trigger}_headers", $headers, $this->context );
    325     }
    326 
    327     private function prepareAttachments( WP_Post $post = null ): array {
     322        $headers = array_merge($headers, $this->prepareCc( $headers, $trigger, $post ));
     323        $headers = array_merge($headers, $this->prepareBcc( $headers, $trigger, $post ));
     324
     325        return apply_filters( "juvo_mail_editor_{$trigger->getSlug()}_headers", $headers, $trigger->getContext() );
     326    }
     327
     328    private function prepareAttachments( Trigger $trigger, WP_Post $post = null ): array {
    328329
    329330        $attachments = [];
     
    342343        }
    343344
    344         return apply_filters( "juvo_mail_editor_{$this->trigger}_attachments", $attachments, $this->context );
    345     }
    346 
    347     private function prepareCc( array $headers, WP_Post $post = null ): array {
     345        return apply_filters( "juvo_mail_editor_{$trigger->getSlug()}_attachments", $attachments, $trigger->getContext() );
     346    }
     347
     348    private function prepareCc( array $headers, Trigger $trigger, WP_Post $post = null ): array {
    348349
    349350        $cc = [];
     
    351352        // phpcs:ignore Squiz.PHP.DisallowMultipleAssignments.FoundInControlStructure
    352353        if ( $post ) {
    353             $cc = get_post_meta( $post->ID, Mails_PT::POST_TYPE_NAME . '_cc', true ) ?: [] ;
    354         }
    355 
    356         $cc = apply_filters( "juvo_mail_editor_{$this->trigger}_cc", $cc, $this->context );
    357         $cc = apply_filters( 'juvo_mail_editor_after_cc_placeholder', $this->parseToCcBcc( $cc, "Cc:" ), $this->trigger, $this->context );
    358 
    359         return array_merge( $headers, $cc );
    360     }
    361 
    362     private function prepareBcc( array $headers, WP_Post $post = null ): array {
     354            $cc = get_post_meta( $post->ID, Mails_PT::POST_TYPE_NAME . '_cc', true ) ?: [];
     355        }
     356
     357        $cc = apply_filters( "juvo_mail_editor_{$trigger->getSlug()}_cc", $cc, $trigger->getContext() );
     358        $cc = apply_filters( 'juvo_mail_editor_after_cc_placeholder', $this->parseToCcBcc( $trigger, $cc, "Cc:" ), $trigger->getSlug(), $trigger->getContext() );
     359
     360        return $cc;
     361    }
     362
     363    private function prepareBcc( array $headers, Trigger $trigger, WP_Post $post = null ): array {
    363364
    364365        $bcc = [];
     
    369370        }
    370371
    371         $bcc = apply_filters( "juvo_mail_editor_{$this->trigger}_bcc", $bcc, $this->context );
    372         $bcc = apply_filters( 'juvo_mail_editor_after_bcc_placeholder', $this->parseToCcBcc( $bcc, "Bcc:" ), $this->trigger, $this->context );
    373 
    374         return array_merge( $headers, $bcc );
     372        $bcc = apply_filters( "juvo_mail_editor_{$trigger->getSlug()}_bcc", $bcc, $trigger->getContext() );
     373        $bcc = apply_filters( 'juvo_mail_editor_after_bcc_placeholder', $this->parseToCcBcc( $trigger, $bcc, "Bcc:" ), $trigger->getSlug(), $trigger->getContext() );
     374
     375        return $bcc;
    375376    }
    376377
     
    378379     * Parses cmb2 repeater groups or strings to wp_mail compatible array format for "to", "cc" and "bcc"
    379380     *
     381     * @param Trigger $trigger
    380382     * @param array|string $recipients
    381383     * @param string $prefix "Cc:" or "Bcc:"
     
    383385     * @return array
    384386     */
    385     private function parseToCcBcc( $recipients, string $prefix = "" ): array {
     387    private function parseToCcBcc( Trigger $trigger, $recipients, string $prefix = "" ): array {
    386388
    387389        if ( empty( $recipients ) ) {
     
    401403            }
    402404
    403             $recipient = Placeholder::replacePlaceholder( $this->placeholders, $recipient, $this->context );
     405            $recipient = Placeholder::replacePlaceholder( $this->preparePlaceholders( $trigger ), $recipient, $trigger->getContext() );
    404406
    405407            if ( ! empty( $prefix ) ) {
  • juvo-mail-editor/tags/3.1.0/src/Trigger.php

    r2644151 r2981043  
    33
    44namespace JUVO_MailEditor;
     5
     6use WP_Term;
    57
    68/**
     
    2426
    2527    /**
     28     * @var WP_Term|null
     29     */
     30    private ?WP_Term $term;
     31
     32    private array $context = [];
     33
     34    private string $mailHook;
     35
     36    /**
    2637     * Trigger constructor.
    2738     *
    2839     * @param string $name
    2940     * @param string $slug
     41     * @param string $mailHook
    3042     */
    31     public function __construct( string $name, string $slug ) {
    32         $this->name = $name;
    33         $this->slug = $slug;
     43    public function __construct( string $name, string $slug, string $mailHook = '' ) {
     44        $this->name     = $name;
     45        $this->slug     = $slug;
     46        $this->mailHook = $mailHook;
     47        $this->term     = get_term_by( 'slug', $slug, Mail_Trigger_TAX::TAXONOMY_NAME ) ?: null;
     48
     49        add_filter( $this->mailHook, array( $this, 'addTriggerToHeader' ), 9, 1 );
     50    }
     51
     52    public function getTerm(): ?WP_Term {
     53        return $this->term ?? null;
    3454    }
    3555
     
    4868    }
    4969
     70    /**
     71     * Check if a trigger is globally muted
     72     *
     73     * @return bool
     74     */
     75    public function isMuted(): bool {
     76        $pluginSettings = get_option( 'settings' );
     77
     78        if ( isset( $pluginSettings['trigger_mute'] ) ) {
     79            return in_array( $this->slug, $pluginSettings['trigger_mute'], true );
     80        }
     81
     82        return false;
     83    }
     84
     85    public function getRelatedPosts(): array {
     86
     87        if ( ! $this->getTerm() instanceof WP_Term ) {
     88            return [];
     89        }
     90
     91        return get_posts(
     92            array(
     93                'post_type'        => Mails_PT::POST_TYPE_NAME,
     94                'post_status'      => 'publish',
     95                'numberposts'      => - 1,
     96                'suppress_filters' => false,
     97                'tax_query'        => array(
     98                    array(
     99                        'taxonomy' => Mail_Trigger_TAX::TAXONOMY_NAME,
     100                        'field'    => 'id',
     101                        'terms'    => $this->term,
     102                    ),
     103                ),
     104            )
     105        );
     106    }
     107
     108    public function getMailHook(): string {
     109        return $this->mailHook;
     110    }
     111
     112    public function getContext(): array {
     113        return $this->context;
     114    }
     115
     116    public function setContext( array $context ): void {
     117        $this->context = $context;
     118    }
     119
     120    /**
     121     * Add trigger slug to mail header to identify throughout the process
     122     *
     123     * @param array $args
     124     *
     125     * @return array
     126     */
     127    public function addTriggerToHeader( array $args ): array {
     128
     129        // Enforce headers to be array
     130        if ( ! empty( $args['headers'] ) && is_string( $args['headers'] ) ) {
     131            $args['headers'] = explode( "\n", str_replace( "\r\n", "\n", $args['headers'] ) );
     132        } elseif(empty($args['headers'])) {
     133            $args['headers'] = [];
     134        }
     135
     136        $args['headers'][] = "X-JUVO-ME-Trigger: {$this->getSlug()}";
     137
     138        // Format back to string since some smtp plugins do not support arrays
     139        $args['headers'] = implode("\r\n", $args['headers']);
     140
     141        return $args;
     142
     143    }
     144
    50145}
  • juvo-mail-editor/tags/3.1.0/vendor/autoload.php

    r2793158 r2981043  
    44
    55if (PHP_VERSION_ID < 50600) {
    6     echo 'Composer 2.3.0 dropped support for autoloading on PHP <5.6 and you are running '.PHP_VERSION.', please upgrade PHP or use Composer 2.2 LTS via "composer self-update --2.2". Aborting.'.PHP_EOL;
    7     exit(1);
     6    if (!headers_sent()) {
     7        header('HTTP/1.1 500 Internal Server Error');
     8    }
     9    $err = 'Composer 2.3.0 dropped support for autoloading on PHP <5.6 and you are running '.PHP_VERSION.', please upgrade PHP or use Composer 2.2 LTS via "composer self-update --2.2". Aborting.'.PHP_EOL;
     10    if (!ini_get('display_errors')) {
     11        if (PHP_SAPI === 'cli' || PHP_SAPI === 'phpdbg') {
     12            fwrite(STDERR, $err);
     13        } elseif (!headers_sent()) {
     14            echo $err;
     15        }
     16    }
     17    trigger_error(
     18        $err,
     19        E_USER_ERROR
     20    );
    821}
    922
    1023require_once __DIR__ . '/composer/autoload_real.php';
    1124
    12 return ComposerAutoloaderInit9c6548f6eba24e2705cd7acb45e71c62::getLoader();
     25return ComposerAutoloaderInitf48a6f250b401e6a6afc3e88e6ee63ed::getLoader();
  • juvo-mail-editor/tags/3.1.0/vendor/composer/ClassLoader.php

    r2665450 r2981043  
    4343class ClassLoader
    4444{
    45     /** @var ?string */
     45    /** @var \Closure(string):void */
     46    private static $includeFile;
     47
     48    /** @var string|null */
    4649    private $vendorDir;
    4750
    4851    // PSR-4
    4952    /**
    50      * @var array[]
    51      * @psalm-var array<string, array<string, int>>
     53     * @var array<string, array<string, int>>
    5254     */
    5355    private $prefixLengthsPsr4 = array();
    5456    /**
    55      * @var array[]
    56      * @psalm-var array<string, array<int, string>>
     57     * @var array<string, list<string>>
    5758     */
    5859    private $prefixDirsPsr4 = array();
    5960    /**
    60      * @var array[]
    61      * @psalm-var array<string, string>
     61     * @var list<string>
    6262     */
    6363    private $fallbackDirsPsr4 = array();
     
    6565    // PSR-0
    6666    /**
    67      * @var array[]
    68      * @psalm-var array<string, array<string, string[]>>
     67     * List of PSR-0 prefixes
     68     *
     69     * Structured as array('F (first letter)' => array('Foo\Bar (full prefix)' => array('path', 'path2')))
     70     *
     71     * @var array<string, array<string, list<string>>>
    6972     */
    7073    private $prefixesPsr0 = array();
    7174    /**
    72      * @var array[]
    73      * @psalm-var array<string, string>
     75     * @var list<string>
    7476     */
    7577    private $fallbackDirsPsr0 = array();
     
    7981
    8082    /**
    81      * @var string[]
    82      * @psalm-var array<string, string>
     83     * @var array<string, string>
    8384     */
    8485    private $classMap = array();
     
    8889
    8990    /**
    90      * @var bool[]
    91      * @psalm-var array<string, bool>
     91     * @var array<string, bool>
    9292     */
    9393    private $missingClasses = array();
    9494
    95     /** @var ?string */
     95    /** @var string|null */
    9696    private $apcuPrefix;
    9797
    9898    /**
    99      * @var self[]
     99     * @var array<string, self>
    100100     */
    101101    private static $registeredLoaders = array();
    102102
    103103    /**
    104      * @param ?string $vendorDir
     104     * @param string|null $vendorDir
    105105     */
    106106    public function __construct($vendorDir = null)
    107107    {
    108108        $this->vendorDir = $vendorDir;
    109     }
    110 
    111     /**
    112      * @return string[]
     109        self::initializeIncludeClosure();
     110    }
     111
     112    /**
     113     * @return array<string, list<string>>
    113114     */
    114115    public function getPrefixes()
     
    122123
    123124    /**
    124      * @return array[]
    125      * @psalm-return array<string, array<int, string>>
     125     * @return array<string, list<string>>
    126126     */
    127127    public function getPrefixesPsr4()
     
    131131
    132132    /**
    133      * @return array[]
    134      * @psalm-return array<string, string>
     133     * @return list<string>
    135134     */
    136135    public function getFallbackDirs()
     
    140139
    141140    /**
    142      * @return array[]
    143      * @psalm-return array<string, string>
     141     * @return list<string>
    144142     */
    145143    public function getFallbackDirsPsr4()
     
    149147
    150148    /**
    151      * @return string[] Array of classname => path
    152      * @psalm-return array<string, string>
     149     * @return array<string, string> Array of classname => path
    153150     */
    154151    public function getClassMap()
     
    158155
    159156    /**
    160      * @param string[] $classMap Class to filename map
    161      * @psalm-param array<string, string> $classMap
     157     * @param array<string, string> $classMap Class to filename map
    162158     *
    163159     * @return void
     
    176172     * appending or prepending to the ones previously set for this prefix.
    177173     *
    178      * @param string          $prefix  The prefix
    179      * @param string[]|string $paths   The PSR-0 root directories
    180      * @param bool            $prepend Whether to prepend the directories
     174     * @param string              $prefix  The prefix
     175     * @param list<string>|string $paths   The PSR-0 root directories
     176     * @param bool                $prepend Whether to prepend the directories
    181177     *
    182178     * @return void
     
    184180    public function add($prefix, $paths, $prepend = false)
    185181    {
     182        $paths = (array) $paths;
    186183        if (!$prefix) {
    187184            if ($prepend) {
    188185                $this->fallbackDirsPsr0 = array_merge(
    189                     (array) $paths,
     186                    $paths,
    190187                    $this->fallbackDirsPsr0
    191188                );
     
    193190                $this->fallbackDirsPsr0 = array_merge(
    194191                    $this->fallbackDirsPsr0,
    195                     (array) $paths
     192                    $paths
    196193                );
    197194            }
     
    202199        $first = $prefix[0];
    203200        if (!isset($this->prefixesPsr0[$first][$prefix])) {
    204             $this->prefixesPsr0[$first][$prefix] = (array) $paths;
     201            $this->prefixesPsr0[$first][$prefix] = $paths;
    205202
    206203            return;
     
    208205        if ($prepend) {
    209206            $this->prefixesPsr0[$first][$prefix] = array_merge(
    210                 (array) $paths,
     207                $paths,
    211208                $this->prefixesPsr0[$first][$prefix]
    212209            );
     
    214211            $this->prefixesPsr0[$first][$prefix] = array_merge(
    215212                $this->prefixesPsr0[$first][$prefix],
    216                 (array) $paths
     213                $paths
    217214            );
    218215        }
     
    223220     * appending or prepending to the ones previously set for this namespace.
    224221     *
    225      * @param string          $prefix  The prefix/namespace, with trailing '\\'
    226      * @param string[]|string $paths   The PSR-4 base directories
    227      * @param bool            $prepend Whether to prepend the directories
     222     * @param string              $prefix  The prefix/namespace, with trailing '\\'
     223     * @param list<string>|string $paths   The PSR-4 base directories
     224     * @param bool                $prepend Whether to prepend the directories
    228225     *
    229226     * @throws \InvalidArgumentException
     
    233230    public function addPsr4($prefix, $paths, $prepend = false)
    234231    {
     232        $paths = (array) $paths;
    235233        if (!$prefix) {
    236234            // Register directories for the root namespace.
    237235            if ($prepend) {
    238236                $this->fallbackDirsPsr4 = array_merge(
    239                     (array) $paths,
     237                    $paths,
    240238                    $this->fallbackDirsPsr4
    241239                );
     
    243241                $this->fallbackDirsPsr4 = array_merge(
    244242                    $this->fallbackDirsPsr4,
    245                     (array) $paths
     243                    $paths
    246244                );
    247245            }
     
    253251            }
    254252            $this->prefixLengthsPsr4[$prefix[0]][$prefix] = $length;
    255             $this->prefixDirsPsr4[$prefix] = (array) $paths;
     253            $this->prefixDirsPsr4[$prefix] = $paths;
    256254        } elseif ($prepend) {
    257255            // Prepend directories for an already registered namespace.
    258256            $this->prefixDirsPsr4[$prefix] = array_merge(
    259                 (array) $paths,
     257                $paths,
    260258                $this->prefixDirsPsr4[$prefix]
    261259            );
     
    264262            $this->prefixDirsPsr4[$prefix] = array_merge(
    265263                $this->prefixDirsPsr4[$prefix],
    266                 (array) $paths
     264                $paths
    267265            );
    268266        }
     
    273271     * replacing any others previously set for this prefix.
    274272     *
    275      * @param string          $prefix The prefix
    276      * @param string[]|string $paths  The PSR-0 base directories
     273     * @param string              $prefix The prefix
     274     * @param list<string>|string $paths  The PSR-0 base directories
    277275     *
    278276     * @return void
     
    291289     * replacing any others previously set for this namespace.
    292290     *
    293      * @param string          $prefix The prefix/namespace, with trailing '\\'
    294      * @param string[]|string $paths  The PSR-4 base directories
     291     * @param string              $prefix The prefix/namespace, with trailing '\\'
     292     * @param list<string>|string $paths  The PSR-4 base directories
    295293     *
    296294     * @throws \InvalidArgumentException
     
    426424    {
    427425        if ($file = $this->findFile($class)) {
    428             includeFile($file);
     426            $includeFile = self::$includeFile;
     427            $includeFile($file);
    429428
    430429            return true;
     
    477476
    478477    /**
    479      * Returns the currently registered loaders indexed by their corresponding vendor directories.
    480      *
    481      * @return self[]
     478     * Returns the currently registered loaders keyed by their corresponding vendor directories.
     479     *
     480     * @return array<string, self>
    482481     */
    483482    public static function getRegisteredLoaders()
     
    556555        return false;
    557556    }
     557
     558    /**
     559     * @return void
     560     */
     561    private static function initializeIncludeClosure()
     562    {
     563        if (self::$includeFile !== null) {
     564            return;
     565        }
     566
     567        /**
     568         * Scope isolated include.
     569         *
     570         * Prevents access to $this/self from included files.
     571         *
     572         * @param  string $file
     573         * @return void
     574         */
     575        self::$includeFile = \Closure::bind(static function($file) {
     576            include $file;
     577        }, null, null);
     578    }
    558579}
    559 
    560 /**
    561  * Scope isolated include.
    562  *
    563  * Prevents access to $this/self from included files.
    564  *
    565  * @param  string $file
    566  * @return void
    567  * @private
    568  */
    569 function includeFile($file)
    570 {
    571     include $file;
    572 }
  • juvo-mail-editor/tags/3.1.0/vendor/composer/InstalledVersions.php

    r2791814 r2981043  
    9999        foreach (self::getInstalled() as $installed) {
    100100            if (isset($installed['versions'][$packageName])) {
    101                 return $includeDevRequirements || empty($installed['versions'][$packageName]['dev_requirement']);
     101                return $includeDevRequirements || !isset($installed['versions'][$packageName]['dev_requirement']) || $installed['versions'][$packageName]['dev_requirement'] === false;
    102102            }
    103103        }
     
    120120    public static function satisfies(VersionParser $parser, $packageName, $constraint)
    121121    {
    122         $constraint = $parser->parseConstraints($constraint);
     122        $constraint = $parser->parseConstraints((string) $constraint);
    123123        $provided = $parser->parseConstraints(self::getVersionRanges($packageName));
    124124
     
    329329                    $installed[] = self::$installedByVendor[$vendorDir];
    330330                } elseif (is_file($vendorDir.'/composer/installed.php')) {
    331                     $installed[] = self::$installedByVendor[$vendorDir] = require $vendorDir.'/composer/installed.php';
     331                    /** @var array{root: array{name: string, pretty_version: string, version: string, reference: string|null, type: string, install_path: string, aliases: string[], dev: bool}, versions: array<string, array{pretty_version?: string, version?: string, reference?: string|null, type?: string, install_path?: string, aliases?: string[], dev_requirement: bool, replaced?: string[], provided?: string[]}>} $required */
     332                    $required = require $vendorDir.'/composer/installed.php';
     333                    $installed[] = self::$installedByVendor[$vendorDir] = $required;
    332334                    if (null === self::$installed && strtr($vendorDir.'/composer', '\\', '/') === strtr(__DIR__, '\\', '/')) {
    333335                        self::$installed = $installed[count($installed) - 1];
     
    341343            // and not from its source location in the composer/composer package, see https://github.com/composer/composer/issues/9937
    342344            if (substr(__DIR__, -8, 1) !== 'C') {
    343                 self::$installed = require __DIR__ . '/installed.php';
     345                /** @var array{root: array{name: string, pretty_version: string, version: string, reference: string|null, type: string, install_path: string, aliases: string[], dev: bool}, versions: array<string, array{pretty_version?: string, version?: string, reference?: string|null, type?: string, install_path?: string, aliases?: string[], dev_requirement: bool, replaced?: string[], provided?: string[]}>} $required */
     346                $required = require __DIR__ . '/installed.php';
     347                self::$installed = $required;
    344348            } else {
    345349                self::$installed = array();
    346350            }
    347351        }
    348         $installed[] = self::$installed;
     352
     353        if (self::$installed !== array()) {
     354            $installed[] = self::$installed;
     355        }
    349356
    350357        return $installed;
  • juvo-mail-editor/tags/3.1.0/vendor/composer/autoload_real.php

    r2793158 r2981043  
    33// autoload_real.php @generated by Composer
    44
    5 class ComposerAutoloaderInit9c6548f6eba24e2705cd7acb45e71c62
     5class ComposerAutoloaderInitf48a6f250b401e6a6afc3e88e6ee63ed
    66{
    77    private static $loader;
     
    2323        }
    2424
    25         spl_autoload_register(array('ComposerAutoloaderInit9c6548f6eba24e2705cd7acb45e71c62', 'loadClassLoader'), true, true);
     25        spl_autoload_register(array('ComposerAutoloaderInitf48a6f250b401e6a6afc3e88e6ee63ed', 'loadClassLoader'), true, true);
    2626        self::$loader = $loader = new \Composer\Autoload\ClassLoader(\dirname(__DIR__));
    27         spl_autoload_unregister(array('ComposerAutoloaderInit9c6548f6eba24e2705cd7acb45e71c62', 'loadClassLoader'));
     27        spl_autoload_unregister(array('ComposerAutoloaderInitf48a6f250b401e6a6afc3e88e6ee63ed', 'loadClassLoader'));
    2828
    2929        require __DIR__ . '/autoload_static.php';
    30         call_user_func(\Composer\Autoload\ComposerStaticInit9c6548f6eba24e2705cd7acb45e71c62::getInitializer($loader));
     30        call_user_func(\Composer\Autoload\ComposerStaticInitf48a6f250b401e6a6afc3e88e6ee63ed::getInitializer($loader));
    3131
    3232        $loader->register(true);
    3333
    34         $includeFiles = \Composer\Autoload\ComposerStaticInit9c6548f6eba24e2705cd7acb45e71c62::$files;
    35         foreach ($includeFiles as $fileIdentifier => $file) {
    36             composerRequire9c6548f6eba24e2705cd7acb45e71c62($fileIdentifier, $file);
     34        $filesToLoad = \Composer\Autoload\ComposerStaticInitf48a6f250b401e6a6afc3e88e6ee63ed::$files;
     35        $requireFile = \Closure::bind(static function ($fileIdentifier, $file) {
     36            if (empty($GLOBALS['__composer_autoload_files'][$fileIdentifier])) {
     37                $GLOBALS['__composer_autoload_files'][$fileIdentifier] = true;
     38
     39                require $file;
     40            }
     41        }, null, null);
     42        foreach ($filesToLoad as $fileIdentifier => $file) {
     43            $requireFile($fileIdentifier, $file);
    3744        }
    3845
     
    4047    }
    4148}
    42 
    43 /**
    44  * @param string $fileIdentifier
    45  * @param string $file
    46  * @return void
    47  */
    48 function composerRequire9c6548f6eba24e2705cd7acb45e71c62($fileIdentifier, $file)
    49 {
    50     if (empty($GLOBALS['__composer_autoload_files'][$fileIdentifier])) {
    51         $GLOBALS['__composer_autoload_files'][$fileIdentifier] = true;
    52 
    53         require $file;
    54     }
    55 }
  • juvo-mail-editor/tags/3.1.0/vendor/composer/autoload_static.php

    r2793158 r2981043  
    55namespace Composer\Autoload;
    66
    7 class ComposerStaticInit9c6548f6eba24e2705cd7acb45e71c62
     7class ComposerStaticInitf48a6f250b401e6a6afc3e88e6ee63ed
    88{
    99    public static $files = array (
     
    100100    {
    101101        return \Closure::bind(function () use ($loader) {
    102             $loader->prefixLengthsPsr4 = ComposerStaticInit9c6548f6eba24e2705cd7acb45e71c62::$prefixLengthsPsr4;
    103             $loader->prefixDirsPsr4 = ComposerStaticInit9c6548f6eba24e2705cd7acb45e71c62::$prefixDirsPsr4;
    104             $loader->fallbackDirsPsr4 = ComposerStaticInit9c6548f6eba24e2705cd7acb45e71c62::$fallbackDirsPsr4;
    105             $loader->prefixesPsr0 = ComposerStaticInit9c6548f6eba24e2705cd7acb45e71c62::$prefixesPsr0;
    106             $loader->classMap = ComposerStaticInit9c6548f6eba24e2705cd7acb45e71c62::$classMap;
     102            $loader->prefixLengthsPsr4 = ComposerStaticInitf48a6f250b401e6a6afc3e88e6ee63ed::$prefixLengthsPsr4;
     103            $loader->prefixDirsPsr4 = ComposerStaticInitf48a6f250b401e6a6afc3e88e6ee63ed::$prefixDirsPsr4;
     104            $loader->fallbackDirsPsr4 = ComposerStaticInitf48a6f250b401e6a6afc3e88e6ee63ed::$fallbackDirsPsr4;
     105            $loader->prefixesPsr0 = ComposerStaticInitf48a6f250b401e6a6afc3e88e6ee63ed::$prefixesPsr0;
     106            $loader->classMap = ComposerStaticInitf48a6f250b401e6a6afc3e88e6ee63ed::$classMap;
    107107
    108108        }, null, ClassLoader::class);
  • juvo-mail-editor/tags/3.1.0/vendor/composer/installed.json

    r2793157 r2981043  
    276276        {
    277277            "name": "symfony/polyfill-ctype",
    278             "version": "v1.26.0",
    279             "version_normalized": "1.26.0.0",
     278            "version": "v1.28.0",
     279            "version_normalized": "1.28.0.0",
    280280            "source": {
    281281                "type": "git",
    282282                "url": "https://github.com/symfony/polyfill-ctype.git",
    283                 "reference": "6fd1b9a79f6e3cf65f9e679b23af304cd9e010d4"
    284             },
    285             "dist": {
    286                 "type": "zip",
    287                 "url": "https://api.github.com/repos/symfony/polyfill-ctype/zipball/6fd1b9a79f6e3cf65f9e679b23af304cd9e010d4",
    288                 "reference": "6fd1b9a79f6e3cf65f9e679b23af304cd9e010d4",
     283                "reference": "ea208ce43cbb04af6867b4fdddb1bdbf84cc28cb"
     284            },
     285            "dist": {
     286                "type": "zip",
     287                "url": "https://api.github.com/repos/symfony/polyfill-ctype/zipball/ea208ce43cbb04af6867b4fdddb1bdbf84cc28cb",
     288                "reference": "ea208ce43cbb04af6867b4fdddb1bdbf84cc28cb",
    289289                "shasum": ""
    290290            },
     
    298298                "ext-ctype": "For best performance"
    299299            },
    300             "time": "2022-05-24T11:49:31+00:00",
     300            "time": "2023-01-26T09:26:14+00:00",
    301301            "type": "library",
    302302            "extra": {
    303303                "branch-alias": {
    304                     "dev-main": "1.26-dev"
     304                    "dev-main": "1.28-dev"
    305305                },
    306306                "thanks": {
     
    341341            ],
    342342            "support": {
    343                 "source": "https://github.com/symfony/polyfill-ctype/tree/v1.26.0"
     343                "source": "https://github.com/symfony/polyfill-ctype/tree/v1.28.0"
    344344            },
    345345            "funding": [
     
    444444        {
    445445            "name": "symfony/polyfill-php72",
    446             "version": "v1.26.0",
    447             "version_normalized": "1.26.0.0",
     446            "version": "v1.28.0",
     447            "version_normalized": "1.28.0.0",
    448448            "source": {
    449449                "type": "git",
    450450                "url": "https://github.com/symfony/polyfill-php72.git",
    451                 "reference": "bf44a9fd41feaac72b074de600314a93e2ae78e2"
    452             },
    453             "dist": {
    454                 "type": "zip",
    455                 "url": "https://api.github.com/repos/symfony/polyfill-php72/zipball/bf44a9fd41feaac72b074de600314a93e2ae78e2",
    456                 "reference": "bf44a9fd41feaac72b074de600314a93e2ae78e2",
     451                "reference": "70f4aebd92afca2f865444d30a4d2151c13c3179"
     452            },
     453            "dist": {
     454                "type": "zip",
     455                "url": "https://api.github.com/repos/symfony/polyfill-php72/zipball/70f4aebd92afca2f865444d30a4d2151c13c3179",
     456                "reference": "70f4aebd92afca2f865444d30a4d2151c13c3179",
    457457                "shasum": ""
    458458            },
     
    460460                "php": ">=7.1"
    461461            },
    462             "time": "2022-05-24T11:49:31+00:00",
     462            "time": "2023-01-26T09:26:14+00:00",
    463463            "type": "library",
    464464            "extra": {
    465465                "branch-alias": {
    466                     "dev-main": "1.26-dev"
     466                    "dev-main": "1.28-dev"
    467467                },
    468468                "thanks": {
     
    503503            ],
    504504            "support": {
    505                 "source": "https://github.com/symfony/polyfill-php72/tree/v1.26.0"
     505                "source": "https://github.com/symfony/polyfill-php72/tree/v1.28.0"
    506506            },
    507507            "funding": [
     
    523523        {
    524524            "name": "timber/timber",
    525             "version": "1.20.0",
    526             "version_normalized": "1.20.0.0",
     525            "version": "1.22.1",
     526            "version_normalized": "1.22.1.0",
    527527            "source": {
    528528                "type": "git",
    529529                "url": "https://github.com/timber/timber.git",
    530                 "reference": "3ac8c7629656009b9e0d6d9e4ccda202aad3b8e0"
    531             },
    532             "dist": {
    533                 "type": "zip",
    534                 "url": "https://api.github.com/repos/timber/timber/zipball/3ac8c7629656009b9e0d6d9e4ccda202aad3b8e0",
    535                 "reference": "3ac8c7629656009b9e0d6d9e4ccda202aad3b8e0",
     530                "reference": "57fc582c42519f1b05fff5fb2ebf4291b5cd638f"
     531            },
     532            "dist": {
     533                "type": "zip",
     534                "url": "https://api.github.com/repos/timber/timber/zipball/57fc582c42519f1b05fff5fb2ebf4291b5cd638f",
     535                "reference": "57fc582c42519f1b05fff5fb2ebf4291b5cd638f",
    536536                "shasum": ""
    537537            },
    538538            "require": {
    539539                "composer/installers": "^1.0 || ^2.0",
    540                 "php": ">=5.3.0 || 7.*",
     540                "php": ">=7.2.5 || ^8.0",
    541541                "twig/cache-extension": "^1.5",
    542                 "twig/twig": "^1.41 || ^2.10",
    543                 "upstatement/routes": "0.9.*"
     542                "twig/twig": "^1.44.7 || ^2.10",
     543                "upstatement/routes": "^0.9"
    544544            },
    545545            "require-dev": {
    546                 "dealerdirect/phpcodesniffer-composer-installer": "^0.7.0",
    547                 "johnpbloch/wordpress": "*",
    548                 "phpunit/phpunit": "5.7.21 || 6.*",
    549                 "squizlabs/php_codesniffer": "3.*",
    550                 "wp-coding-standards/wpcs": "^2.0",
    551                 "wpackagist-plugin/advanced-custom-fields": "5.*",
    552                 "wpackagist-plugin/co-authors-plus": "3.2.* || 3.4.*",
    553                 "yoast/phpunit-polyfills": "^1.0"
     546                "wpackagist-plugin/advanced-custom-fields": "^5.0",
     547                "wpackagist-plugin/co-authors-plus": "^3.2 || ^3.4",
     548                "yoast/wp-test-utils": "^1.0"
    554549            },
    555550            "suggest": {
    556551                "satooshi/php-coveralls": "1.0.* for code coverage"
    557552            },
    558             "time": "2022-06-22T19:42:09+00:00",
     553            "time": "2022-11-24T03:42:29+00:00",
    559554            "type": "library",
    560555            "installation-source": "dist",
     
    672667        {
    673668            "name": "twig/twig",
    674             "version": "v2.15.3",
    675             "version_normalized": "2.15.3.0",
     669            "version": "v2.15.5",
     670            "version_normalized": "2.15.5.0",
    676671            "source": {
    677672                "type": "git",
    678673                "url": "https://github.com/twigphp/Twig.git",
    679                 "reference": "ab402673db8746cb3a4c46f3869d6253699f614a"
    680             },
    681             "dist": {
    682                 "type": "zip",
    683                 "url": "https://api.github.com/repos/twigphp/Twig/zipball/ab402673db8746cb3a4c46f3869d6253699f614a",
    684                 "reference": "ab402673db8746cb3a4c46f3869d6253699f614a",
     674                "reference": "fc02a6af3eeb97c4bf5650debc76c2eda85ac22e"
     675            },
     676            "dist": {
     677                "type": "zip",
     678                "url": "https://api.github.com/repos/twigphp/Twig/zipball/fc02a6af3eeb97c4bf5650debc76c2eda85ac22e",
     679                "reference": "fc02a6af3eeb97c4bf5650debc76c2eda85ac22e",
    685680                "shasum": ""
    686681            },
     
    695690                "symfony/phpunit-bridge": "^4.4.9|^5.0.9|^6.0"
    696691            },
    697             "time": "2022-09-28T08:40:08+00:00",
     692            "time": "2023-05-03T17:49:41+00:00",
    698693            "type": "library",
    699694            "extra": {
     
    739734            "support": {
    740735                "issues": "https://github.com/twigphp/Twig/issues",
    741                 "source": "https://github.com/twigphp/Twig/tree/v2.15.3"
     736                "source": "https://github.com/twigphp/Twig/tree/v2.15.5"
    742737            },
    743738            "funding": [
  • juvo-mail-editor/tags/3.1.0/vendor/composer/installed.php

    r2793158 r2981043  
    22    'root' => array(
    33        'name' => 'juvo/mail-editor',
    4         'pretty_version' => '3.0.14',
    5         'version' => '3.0.14.0',
    6         'reference' => 'd2121200fa0f831478fcfc06bf91e4a5c0a22a00',
     4        'pretty_version' => '3.1.0',
     5        'version' => '3.1.0.0',
     6        'reference' => 'bb23356d74fe5d290e3a616e6e0967dede6bcd24',
    77        'type' => 'wordpress-plugin',
    88        'install_path' => __DIR__ . '/../../',
     
    3939        ),
    4040        'juvo/mail-editor' => array(
    41             'pretty_version' => '3.0.14',
    42             'version' => '3.0.14.0',
    43             'reference' => 'd2121200fa0f831478fcfc06bf91e4a5c0a22a00',
     41            'pretty_version' => '3.1.0',
     42            'version' => '3.1.0.0',
     43            'reference' => 'bb23356d74fe5d290e3a616e6e0967dede6bcd24',
    4444            'type' => 'wordpress-plugin',
    4545            'install_path' => __DIR__ . '/../../',
     
    4848        ),
    4949        'symfony/polyfill-ctype' => array(
    50             'pretty_version' => 'v1.26.0',
    51             'version' => '1.26.0.0',
    52             'reference' => '6fd1b9a79f6e3cf65f9e679b23af304cd9e010d4',
     50            'pretty_version' => 'v1.28.0',
     51            'version' => '1.28.0.0',
     52            'reference' => 'ea208ce43cbb04af6867b4fdddb1bdbf84cc28cb',
    5353            'type' => 'library',
    5454            'install_path' => __DIR__ . '/../symfony/polyfill-ctype',
     
    6666        ),
    6767        'symfony/polyfill-php72' => array(
    68             'pretty_version' => 'v1.26.0',
    69             'version' => '1.26.0.0',
    70             'reference' => 'bf44a9fd41feaac72b074de600314a93e2ae78e2',
     68            'pretty_version' => 'v1.28.0',
     69            'version' => '1.28.0.0',
     70            'reference' => '70f4aebd92afca2f865444d30a4d2151c13c3179',
    7171            'type' => 'library',
    7272            'install_path' => __DIR__ . '/../symfony/polyfill-php72',
     
    7575        ),
    7676        'timber/timber' => array(
    77             'pretty_version' => '1.20.0',
    78             'version' => '1.20.0.0',
    79             'reference' => '3ac8c7629656009b9e0d6d9e4ccda202aad3b8e0',
     77            'pretty_version' => '1.22.1',
     78            'version' => '1.22.1.0',
     79            'reference' => '57fc582c42519f1b05fff5fb2ebf4291b5cd638f',
    8080            'type' => 'library',
    8181            'install_path' => __DIR__ . '/../timber/timber',
     
    9393        ),
    9494        'twig/twig' => array(
    95             'pretty_version' => 'v2.15.3',
    96             'version' => '2.15.3.0',
    97             'reference' => 'ab402673db8746cb3a4c46f3869d6253699f614a',
     95            'pretty_version' => 'v2.15.5',
     96            'version' => '2.15.5.0',
     97            'reference' => 'fc02a6af3eeb97c4bf5650debc76c2eda85ac22e',
    9898            'type' => 'library',
    9999            'install_path' => __DIR__ . '/../twig/twig',
  • juvo-mail-editor/tags/3.1.0/vendor/symfony/polyfill-ctype/LICENSE

    r2644151 r2981043  
    1 Copyright (c) 2018-2019 Fabien Potencier
     1Copyright (c) 2018-present Fabien Potencier
    22
    33Permission is hereby granted, free of charge, to any person obtaining a copy
  • juvo-mail-editor/tags/3.1.0/vendor/symfony/polyfill-php72/LICENSE

    r2677983 r2981043  
    1 Copyright (c) 2015-2019 Fabien Potencier
     1Copyright (c) 2015-present Fabien Potencier
    22
    33Permission is hereby granted, free of charge, to any person obtaining a copy
  • juvo-mail-editor/tags/3.1.0/vendor/symfony/polyfill-php72/Php72.php

    r2677983 r2981043  
    8484        ];
    8585
    86         return isset($map[\PHP_OS]) ? $map[\PHP_OS] : 'Unknown';
     86        return $map[\PHP_OS] ?? 'Unknown';
    8787    }
    8888
     
    9797
    9898        // On 32-bit systems, PHP_INT_SIZE is 4,
    99         return self::$hashMask ^ hexdec(substr($hash, 16 - (\PHP_INT_SIZE * 2 - 1), (\PHP_INT_SIZE * 2 - 1)));
     99        return self::$hashMask ^ hexdec(substr($hash, 16 - (\PHP_INT_SIZE * 2 - 1), \PHP_INT_SIZE * 2 - 1));
    100100    }
    101101
     
    168168        }
    169169
    170         self::$hashMask ^= hexdec(substr(spl_object_hash($obj), 16 - (\PHP_INT_SIZE * 2 - 1), (\PHP_INT_SIZE * 2 - 1)));
     170        self::$hashMask ^= hexdec(substr(spl_object_hash($obj), 16 - (\PHP_INT_SIZE * 2 - 1), \PHP_INT_SIZE * 2 - 1));
    171171    }
    172172
  • juvo-mail-editor/tags/3.1.0/vendor/timber/timber/lib/Image.php

    r2644151 r2981043  
    438438     */
    439439    public function link() {
    440         if ( strlen($this->abs_url) ) {
     440        if (!empty($this->abs_url)) {
    441441            return $this->abs_url;
    442442        }
     
    484484     */
    485485    public function src( $size = 'full' ) {
    486         if ( isset($this->abs_url) ) {
     486        if (!empty($this->abs_url)) {
    487487            return $this->_maybe_secure_url($this->abs_url);
    488488        }
  • juvo-mail-editor/tags/3.1.0/vendor/timber/timber/lib/Image/Operation/Letterbox.php

    r2793157 r2981043  
    6464            return false;
    6565        }
    66        
     66
    6767        $w = $this->w;
    6868        $h = $this->h;
     
    9393                $x = $w / 2 - $owt / 2;
    9494                $oht = $h;
    95                 $image->crop(0, 0, $ow, $oh, $owt, $oht);
     95                $image->crop(0, 0, round($ow), round($oh), round($owt), round($oht));
    9696            } else {
    9797                $w_scale = $w / $ow;
     
    100100                $y = $h / 2 - $oht / 2;
    101101                $owt = $w;
    102                 $image->crop(0, 0, $ow, $oh, $owt, $oht);
     102                $image->crop(0, 0, round($ow), round($oh), round($owt), round($oht));
    103103            }
    104104            $result = $image->save($save_filename);
     
    121121            }
    122122            $image = $func($save_filename);
    123             imagecopy($bg, $image, $x, $y, 0, 0, $owt, $oht);
     123            imagecopy($bg, $image, round($x), round($y), 0, 0, round($owt), round($oht));
    124124            if ( $save_func === 'imagegif' ) {
    125125                return $save_func($bg, $save_filename);
  • juvo-mail-editor/tags/3.1.0/vendor/timber/timber/lib/Image/Operation/Resize.php

    r2793157 r2981043  
    7676        $crop  = self::get_target_sizes($editor);
    7777        foreach ( $image as $frame ) {
    78             $frame->cropImage($crop['src_w'], $crop['src_h'], $crop['x'], $crop['y']);
     78            $frame->cropImage(
     79                round($crop['src_w']),
     80                round($crop['src_h']),
     81                round($crop['x']),
     82                round($crop['y'])
     83            );
    7984            $frame->thumbnailImage($w, $h);
    8085            $frame->setImagePage($w, $h, 0, 0);
     
    189194
    190195            $crop = self::get_target_sizes($image);
    191             $image->crop(   $crop['x'],
    192                             $crop['y'],
    193                             $crop['src_w'],
    194                             $crop['src_h'],
    195                             $crop['target_w'],
    196                             $crop['target_h']
     196            $image->crop(
     197                round( $crop['x'] ),
     198                round( $crop['y'] ),
     199                round( $crop['src_w'] ),
     200                round( $crop['src_h'] ),
     201                round( $crop['target_w'] ),
     202                round( $crop['target_h'] )
    197203            );
    198204            $quality = apply_filters( 'wp_editor_set_quality', 82, 'image/jpeg');
  • juvo-mail-editor/tags/3.1.0/vendor/timber/timber/lib/Image/Operation/Retina.php

    r2644151 r2981043  
    6363            $src_h = $current_size['height'];
    6464            // Get ratios
    65             $w = $src_w * $this->factor;
    66             $h = $src_h * $this->factor;
     65            $w = round( $src_w * $this->factor );
     66            $h = round( $src_h * $this->factor );
    6767            $image->crop(0, 0, $src_w, $src_h, $w, $h);
    6868            $result = $image->save($save_filename);
  • juvo-mail-editor/tags/3.1.0/vendor/timber/timber/lib/Loader.php

    r2644151 r2981043  
    206206        $cache_mode = $this->_get_cache_mode($cache_mode);
    207207        if ( self::CACHE_TRANSIENT === $cache_mode || self::CACHE_SITE_TRANSIENT === $cache_mode ) {
    208             return self::clear_cache_timber_database();
     208            // $wpdb->query() might return 0 affected rows, but that means it’s still successful.
     209            return false !== self::clear_cache_timber_database();
    209210        } else if ( self::CACHE_OBJECT === $cache_mode && $object_cache ) {
    210             return self::clear_cache_timber_object();
     211            return false !== self::clear_cache_timber_object();
    211212        }
    212213        return false;
  • juvo-mail-editor/tags/3.1.0/vendor/timber/timber/lib/PostsIterator.php

    r2644151 r2981043  
    99 */
    1010class PostsIterator extends \ArrayIterator {
    11    
     11
     12    #[\ReturnTypeWillChange]
    1213    public function current() {
    1314        global $post;
     
    1516        return $post;
    1617    }
    17    
     18
    1819}
  • juvo-mail-editor/tags/3.1.0/vendor/timber/timber/lib/QueryIterator.php

    r2644151 r2981043  
    131131    //
    132132
    133     public function valid() {
     133    public function valid(): bool {
    134134        return $this->_query->have_posts();
    135135    }
    136136
     137    #[\ReturnTypeWillChange]
    137138    public function current() {
    138139        global $post;
     
    148149     * Don't implement next, because current already advances the loop
    149150     */
     151    #[\ReturnTypeWillChange]
    150152    final public function next() {}
    151153
     154    #[\ReturnTypeWillChange]
    152155    public function rewind() {
    153156        $this->_query->rewind_posts();
    154157    }
    155158
     159    #[\ReturnTypeWillChange]
    156160    public function key() {
    157161        $this->_query->current_post;
     
    200204     * The return value is cast to an integer.
    201205     */
    202     public function count() {
     206    public function count(): int {
    203207        return $this->post_count();
    204208    }
  • juvo-mail-editor/tags/3.1.0/vendor/timber/timber/lib/Timber.php

    r2793157 r2981043  
    3636class Timber {
    3737
    38     public static $version = '1.20.0';
     38    public static $version = '1.22.1';
    3939    public static $locations;
    4040    public static $dirname = 'views';
  • juvo-mail-editor/tags/3.1.0/vendor/timber/timber/phpunit-nocover.xml

    r2644151 r2981043  
    66    convertNoticesToExceptions="true"
    77    convertWarningsToExceptions="true"
    8     >
     8>
    99    <testsuites>
    10         <testsuite>
     10        <testsuite name="all">
    1111            <directory prefix="test-" suffix=".php">tests/</directory>
    1212        </testsuite>
     
    1414        as it includes a test that sets some const and would contaminate
    1515        the other tests as well. -->
    16         <testsuite>
     16        <testsuite name="all-but-last">
    1717            <directory prefix="testX-" suffix=".php">tests/</directory>
    1818        </testsuite>
  • juvo-mail-editor/tags/3.1.0/vendor/timber/timber/readme.txt

    r2793157 r2981043  
    22Contributors: jarednova
    33Tags: template engine, templates, twig
    4 Requires at least: 4.9.8
    5 Tested up to: 5.9.3
    6 Stable tag: 1.20.0
    7 Requires PHP: 5.6
     4Tested up to: 6.1
     5Stable tag: 1.22.1
     6Requires PHP: 7.2.5
     7Requires at least: 5.3.0
    88License: GPLv2 or later
    99License URI: http://www.gnu.org/licenses/gpl-2.0.html
     
    3838
    3939**Fixes and improvements**
     40
     41= 1.22.1 =
     42
     43* Fixed a bug when Twig version 3 was accidentally installed when installing Timber through Composer, by @rmens in https://github.com/timber/timber/pull/2679.
     44
     45= 1.22.0 =
     46
     47* Fixed included Twig version. In the plugin version 1.21.0 of Timber, Twig version 2.15.3 was accidentally included instead of Twig version 1.44.7.
     48* Removed official support for PHP 8.1 in the plugin version. If you need to support PHP 8.1 in the future, please install [Timber through Composer](https://timber.github.io/docs/getting-started/setup/#via-github-for-developers) instead of installing Timber as a plugin. This will the only supported way of installing Timber when Timber version 2 will be released.
     49* Updated minimum required WordPress version to 5.3.
     50
     51= 1.21.0 =
     52
     53* Updated minimum required PHP version to 7.2 to make the included Twig version support PHP 8.0 and 8.1, by @gchtr in #2640.
     54* Updated minimum Twig version to 1.44.0 to support PHP 8.0 and 8.1, by @gchtr in #2640.
     55* Fixed support for PHP 8.0 and PHP 8.1, by @nlemoine and @gchtr in #2638, #2640.
    4056
    4157= 1.20.0 =
  • juvo-mail-editor/tags/3.1.0/vendor/twig/twig/CHANGELOG

    r2793157 r2981043  
     1# 2.15.5 (2023-05-03)
     2
     3 * Make the Lexer initialize itself lazily
     4
     5# 2.15.4 (2022-12-27)
     6
     7 * Fix optimizing closures callbacks
     8 * Add a better exception when getting an undefined constant via `constant`
     9 * Fix `if` nodes when outside of a block and with an empty body
     10
    111# 2.15.3 (2022-09-28)
    212
  • juvo-mail-editor/tags/3.1.0/vendor/twig/twig/LICENSE

    r2677983 r2981043  
    1 Copyright (c) 2009-2022 by the Twig Team.
     1Copyright (c) 2009-present by the Twig Team.
    22
    33All rights reserved.
  • juvo-mail-editor/tags/3.1.0/vendor/twig/twig/src/Environment.php

    r2793157 r2981043  
    3939class Environment
    4040{
    41     public const VERSION = '2.15.3';
    42     public const VERSION_ID = 21503;
     41    public const VERSION = '2.15.5';
     42    public const VERSION_ID = 21505;
    4343    public const MAJOR_VERSION = 2;
    4444    public const MINOR_VERSION = 15;
    45     public const RELEASE_VERSION = 3;
     45    public const RELEASE_VERSION = 5;
    4646    public const EXTRA_VERSION = '';
    4747
  • juvo-mail-editor/tags/3.1.0/vendor/twig/twig/src/Extension/CoreExtension.php

    r2677983 r2981043  
    13301330    }
    13311331
     1332    if (!\defined($constant)) {
     1333        throw new RuntimeError(sprintf('Constant "%s" is undefined.', $constant));
     1334    }
     1335
    13321336    return \constant($constant);
    13331337}
  • juvo-mail-editor/tags/3.1.0/vendor/twig/twig/src/Lexer.php

    r2644151 r2981043  
    2222class Lexer
    2323{
     24    private $isInitialized = false;
     25
    2426    private $tokens;
    2527    private $code;
     
    6466            'interpolation' => ['#{', '}'],
    6567        ], $options);
     68    }
     69
     70    private function initialize()
     71    {
     72        if ($this->isInitialized) {
     73            return;
     74        }
     75
     76        $this->isInitialized = true;
    6677
    6778        // when PHP 7.3 is the min version, we will be able to remove the '#' part in preg_quote as it's part of the default
     
    156167    public function tokenize(Source $source)
    157168    {
     169        $this->initialize();
     170
    158171        $this->source = $source;
    159172        $this->code = str_replace(["\r\n", "\r"], "\n", $source->getCode());
  • juvo-mail-editor/tags/3.1.0/vendor/twig/twig/src/Node/Expression/CallExpression.php

    r2793157 r2981043  
    305305            $callable = [$object, $r->name];
    306306            $callableName = (\function_exists('get_debug_type') ? get_debug_type($object) : \get_class($object)).'::'.$r->name;
    307         } elseif ($class = $r->getClosureScopeClass()) {
     307        } elseif (\PHP_VERSION_ID >= 80111 && $class = $r->getClosureCalledClass()) {
     308            $callableName = $class->name.'::'.$r->name;
     309        } elseif (\PHP_VERSION_ID < 80111 && $class = $r->getClosureScopeClass()) {
    308310            $callableName = (\is_array($callable) ? $callable[0] : $class->name).'::'.$r->name;
    309311        } else {
  • juvo-mail-editor/tags/3.1.0/vendor/twig/twig/src/Node/IfNode.php

    r2644151 r2981043  
    5151                ->raw(") {\n")
    5252                ->indent()
    53                 ->subcompile($this->getNode('tests')->getNode($i + 1))
    5453            ;
     54            // The node might not exists if the content is empty
     55            if ($this->getNode('tests')->hasNode($i + 1)) {
     56                $compiler->subcompile($this->getNode('tests')->getNode($i + 1));
     57            }
    5558        }
    5659
  • juvo-mail-editor/trunk/juvo-mail-editor.php

    r2793158 r2981043  
    88 * Text Domain:     juvo-mail-editor
    99 * Domain Path:     /languages
    10  * Version:         3.0.14
     10 * Version:         3.1.0
     11 * Requires at least: 6.2
     12 * Requires PHP: 7.4
    1113 */
    1214
     
    1618
    1719// If this file is called directly, abort.
    18 if ( ! defined( 'WPINC' ) ) {
     20if (!defined('WPINC')) {
    1921    die;
    2022}
     
    2325 * Plugin absolute path
    2426 */
    25 define( 'JUVO_MAIL_EDITOR_PATH', plugin_dir_path( __FILE__ ) );
    26 define( 'JUVO_MAIL_EDITOR_URL', plugin_dir_url( __FILE__ ) );
     27define('JUVO_MAIL_EDITOR_PATH', plugin_dir_path(__FILE__));
     28define('JUVO_MAIL_EDITOR_URL', plugin_dir_url(__FILE__));
    2729
    2830/**
     
    3032 * Add file check to avoid autoloading if included as sub-package
    3133 */
    32 $juvo_mail_editor_plugin_dir = plugin_dir_path( __FILE__ );
    33 if ( file_exists( $juvo_mail_editor_plugin_dir . 'vendor/autoload.php' ) ) {
    34     require plugin_dir_path( __FILE__ ) . 'vendor/autoload.php';
     34$juvo_mail_editor_plugin_dir = plugin_dir_path(__FILE__);
     35if (file_exists($juvo_mail_editor_plugin_dir . 'vendor/autoload.php')) {
     36    require plugin_dir_path(__FILE__) . 'vendor/autoload.php';
    3537}
    3638
     
    3840 * Load cmb2 manually and not by composer because file autoloading does not work
    3941 */
    40 if ( file_exists( $juvo_mail_editor_plugin_dir . 'vendor/cmb2/cmb2/init.php' ) ) {
     42if (file_exists($juvo_mail_editor_plugin_dir . 'vendor/cmb2/cmb2/init.php')) {
    4143    // Path for standalone plugin. Load from local vendor folder
    42     require plugin_dir_path( __FILE__ ) . 'vendor/cmb2/cmb2/init.php';
     44    require plugin_dir_path(__FILE__) . 'vendor/cmb2/cmb2/init.php';
    4345} else {
    4446    // Lookup vendor folder when included as library
    45     preg_match( '/(.*)vendor/U', $juvo_mail_editor_plugin_dir, $matches );
    46     if ( file_exists( $matches[1] . 'vendor/cmb2/cmb2/init.php' ) ) {
     47    preg_match('/(.*)vendor/U', $juvo_mail_editor_plugin_dir, $matches);
     48    if (file_exists($matches[1] . 'vendor/cmb2/cmb2/init.php')) {
    4749        require $matches[1] . 'vendor/cmb2/cmb2/init.php';
    4850    }
     
    5355 * This action is documented in includes/class-plugin-name-activator.php
    5456 */
    55 function juvo_mail_editor_activate() {
     57function juvo_mail_editor_activate()
     58{
    5659    Activator::activate();
    5760}
     
    6164 * This action is documented in includes/class-plugin-name-deactivator.php
    6265 */
    63 function juvo_mail_editor_deactivate() {
     66function juvo_mail_editor_deactivate()
     67{
    6468    Deactivator::deactivate();
    6569}
    6670
    67 register_activation_hook( __FILE__, 'juvo_mail_editor_activate' );
    68 register_deactivation_hook( __FILE__, 'juvo_mail_editor_deactivate' );
     71register_activation_hook(__FILE__, 'juvo_mail_editor_activate');
     72register_deactivation_hook(__FILE__, 'juvo_mail_editor_deactivate');
    6973
    7074
     
    7882 * @since    1.0.0
    7983 */
    80 function juvo_mail_editor_run() {
     84function juvo_mail_editor_run()
     85{
    8186
    82     if ( ! defined( 'ABSPATH' ) ) {
     87    if (!defined('ABSPATH')) {
    8388        return;
    8489    }
    8590
    8691    // Make sure only loaded once
    87     if ( class_exists( '\WP' ) && ! defined( 'JUVO_MAIL_EDITOR_LOADED' ) ) {
     92    if (class_exists('\WP') && !defined('JUVO_MAIL_EDITOR_LOADED')) {
    8893
    8994        $plugin = new Mail_Editor();
    9095        $plugin->run();
    9196
    92         define( 'JUVO_MAIL_EDITOR_LOADED', true );
     97        define('JUVO_MAIL_EDITOR_LOADED', true);
    9398    }
    9499
  • juvo-mail-editor/trunk/readme.txt

    r2793158 r2981043  
    33Tags: mail,editor,framework
    44License: GPLv2 or later
    5 Tested up to: 5.9
    6 Stable tag: 3.0.14
     5Tested up to: 6.3
     6Stable tag: 3.1.0
    77
    88JUVO Mail Editor helps to modify the standard WordPress Mailings and allows adding dynamic mail triggers.
  • juvo-mail-editor/trunk/src/Mail_Editor.php

    r2717851 r2981043  
    9595        $this->loader->add_action( 'admin_enqueue_scripts', $plugin_admin, 'enqueue_scripts' );
    9696
     97        // Init Trigger Registry
     98        Trigger_Registry::getInstance();
     99
    97100        /**
    98101         * Options
     
    121124         * Handle Sending
    122125         */
    123         add_action( "juvo_mail_editor_send", array( Relay::class, 'sendMails' ), 10, 2 );
     126        $relay = new Relay();
     127        $this->loader->add_action("juvo_mail_editor_send", $relay, 'send_mails_action_callback', 10, 2);
     128        $this->loader->add_filter("wp_mail", $relay, 'wpmail_filter_callback', 10, 1);
    124129
    125130        /**
     
    139144        $this->loader->add_action( 'wp_new_user_notification_email', new New_User(), 'prepareSend', 10, 2 );
    140145        $this->loader->add_action( 'rest_insert_user', new New_User_Rest(), 'prepareSend', 12, 1 ); // Rest
    141 
    142         /**
    143          * New User Notification Admin
    144          */
    145146        $this->loader->add_action( 'wp_new_user_notification_email_admin', new New_User_Admin(), 'prepareSend', 10, 2 );
    146147        $this->loader->add_action( 'rest_insert_user', new New_User_Admin_Rest(), 'prepareSend', 12, 1 ); // Rest
     
    149150         * Password Reset
    150151         */
    151         $this->loader->add_filter( 'retrieve_password_message', new Password_Reset(), 'prepareSend', 10, 4 );
    152 
    153         /**
    154          * Password Reset Admin
    155          */
    156         $this->loader->add_filter( 'retrieve_password_message', new Password_Reset_Admin(), 'prepareSend', 99, 4 );
     152        $this->loader->add_filter( 'retrieve_password_notification_email', new Password_Reset(), 'prepareSend', 10, 4 );
     153        $this->loader->add_filter( 'retrieve_password_notification_email', new Password_Reset_Admin(), 'prepareSend', 10, 4 );
    157154
    158155        /**
     
    160157         */
    161158        $this->loader->add_filter( 'password_change_email', new Password_Changed(), 'prepareSend', 10, 2 );
    162 
    163         /**
    164          * Password Changed Admin
    165          */
    166159        $this->loader->add_filter( 'wp_password_change_notification_email', new Password_Changed_Admin(), 'prepareSend', 10, 2 );
    167160
  • juvo-mail-editor/trunk/src/Mail_Generator.php

    r2672700 r2981043  
    1212    public function __construct() {
    1313        add_filter( 'juvo_mail_editor_post_metabox', array( $this, 'addCustomFields' ) );
    14         add_filter( 'juvo_mail_editor_trigger', array( $this, 'registerTrigger' ) );
    1514
    1615        add_filter( "juvo_mail_editor_{$this->getTrigger()}_always_sent", array( $this, 'getAlwaysSent' ), 10, 0 );
     
    2827        );
    2928        add_filter( "juvo_mail_editor_{$this->getTrigger()}_language", array( $this, 'getLanguage' ), 1, 2 );
     29
     30        // Add current trigger to registry
     31        add_action('init', function() {
     32            Trigger_Registry::getInstance()->set( $this->getName(), $this->getTrigger(), $this->getMailArrayHook() );
     33        }, 20);
     34
     35    }
     36
     37    public function getSubject(string $subject) {
     38        return $subject;
     39    }
     40
     41    public function getMessage(string $message) {
     42        return $message;
     43    }
     44
     45    public function getRecipients(array $recipients) {
     46        return $recipients;
    3047    }
    3148
     
    4461     * This allows filters or other functions to fill or show the placeholder in the most dynamic way.
    4562     *
     63     * @param array $placeholders
    4664     * @param array|null $context
    4765     *
     
    5068    public function getPlaceholders( array $placeholders, ?array $context ): array {
    5169        return $placeholders;
    52     }
    53 
    54     /**
    55      * @param Trigger[] $triggers
    56      *
    57      * @return Trigger[]
    58      */
    59     public function registerTrigger( array $triggers ): array {
    60         $triggers[] = new Trigger( $this->getName(), $this->getTrigger() );
    61 
    62         return $triggers;
    6370    }
    6471
     
    8693
    8794    /**
     95     * Get the language an email should be sent in.
     96     *
    8897     * @param string $language
    89      * @param array $context
     98     * @param array $context the context array allows to adjust the language e.g. to the users language
    9099     *
    91100     * @return string
     
    117126
    118127    /**
     128     * WordPress has something of a default array structure that is used for wp_mail.
     129     * Often there is a hook to directly modify this array. If so set it here.
     130     *
     131     * @return string
     132     */
     133    protected function getMailArrayHook(): string {
     134        return "";
     135    }
     136
     137    /**
    119138     * Utility function that completely empties the often used mail array.
    120139     * This is most useful if hooking into native core function
  • juvo-mail-editor/trunk/src/Mail_Trigger_TAX.php

    r2655718 r2981043  
    9292    public function registerTrigger() {
    9393
    94         $triggers = array();
    95         $errors   = new WP_Error();
     94        $errors = new WP_Error();
    9695
    97         $triggers = apply_filters( 'juvo_mail_editor_trigger', $triggers );
     96        $triggers = Trigger_Registry::getInstance()->getAll();
    9897
    9998        foreach ( $triggers as $trigger ) {
  • juvo-mail-editor/trunk/src/Mails/Mail.php

    r2672700 r2981043  
    55interface Mail {
    66
    7     public function getSubject( string $subject ): string;
    8 
    9     public function getMessage( string $message ): string;
    10 
    11     public function getRecipients( array $recipients ): array;
    12 
    137    public function getAlwaysSent(): bool;
    148
  • juvo-mail-editor/trunk/src/Mails/New_User.php

    r2717851 r2981043  
    44
    55use JUVO_MailEditor\Mail_Generator;
     6use JUVO_MailEditor\Trigger_Registry;
    67use WP_User;
    78
     
    1314
    1415    public function prepareSend( array $email, WP_User $user ): array {
    15         do_action( "juvo_mail_editor_send", $this->getTrigger(), [ "user" => $user ] );
    16         return $this->emptyMailArray( $email );
     16
     17        Trigger_Registry::getInstance()->get( $this->getTrigger() )
     18                        ->setContext( [ "user" => $user ] );
     19
     20        return $email;
     21    }
     22
     23    protected function getMailArrayHook(): string {
     24        return "wp_new_user_notification_email";
    1725    }
    1826
     
    3947    }
    4048
    41     public function getSubject( string $subject ): string {
    42 
    43         if ( ! empty( $subject ) ) {
    44             return $subject;
    45         }
    46 
    47         return sprintf( __( '%s Login Details', 'default' ), '{{site.name}}' );
    48     }
    49 
    50     public function getMessage( string $message ): string {
    51 
    52         if ( ! empty( $message ) ) {
    53             return $message;
    54         }
    55 
    56         $message = sprintf( __( 'Username: %s', 'default' ), '{{user.name}}' ) . "\r\n\r\n";
    57         $message .= __( 'To set your password, visit the following address:', 'default' ) . "\r\n\r\n";
    58         $message .= '{{password_reset_link}}' . "\r\n";
    59 
    60         return $message;
    61     }
    62 
    63     public function getRecipients( array $recipients ): array {
    64 
    65         if ( ! empty( $recipients ) ) {
    66             return $recipients;
    67         }
    68 
    69         return [ '{{user.user_email}}' ];
    70     }
    71 
    7249    protected function getName(): string {
    7350        return 'New User (User)';
  • juvo-mail-editor/trunk/src/Mails/New_User_Admin.php

    r2672700 r2981043  
    44
    55use JUVO_MailEditor\Mail_Generator;
     6use JUVO_MailEditor\Trigger_Registry;
    67use WP_User;
    78
     
    1617
    1718    public function prepareSend( array $email, WP_User $user ): array {
    18         do_action( "juvo_mail_editor_send", $this->getTrigger(), [ "user" => $user ] );
     19        Trigger_Registry::getInstance()->get( $this->getTrigger() )
     20                        ->setContext( [ "user" => $user ] );
    1921
    20         return $this->emptyMailArray( $email );
     22        return $email;
    2123    }
    2224
    23     public function getSubject( string $subject ): string {
    24 
    25         if ( ! empty( $subject ) ) {
    26             return $subject;
    27         }
    28 
    29         return sprintf( __( '[%s] New User Registration', 'default' ), '{{site.name}}' );
    30     }
    31 
    32     public function getMessage( string $message ): string {
    33 
    34         if ( ! empty( $message ) ) {
    35             return $message;
    36         }
    37 
    38         $message = sprintf( __( 'New user registration on your site %s:', 'default' ), '{{site.name}}' ) . "\r\n\r\n";
    39         $message .= sprintf( __( 'Username: %s', 'default' ), '{{user.name}}' ) . "\r\n\r\n";
    40         $message .= sprintf( __( 'Email: %s', 'default' ), '{{user.user_email}}' ) . "\r\n";
    41 
    42         return $message;
    43     }
    44 
    45     public function getRecipients( array $recipients ): array {
    46 
    47         if ( ! empty( $recipients ) ) {
    48             return $recipients;
    49         }
    50 
    51         return [ '{{site.admin_email}}' ];
     25    protected function getMailArrayHook(): string {
     26        return "wp_new_user_notification_email_admin";
    5227    }
    5328
  • juvo-mail-editor/trunk/src/Mails/Password_Changed.php

    r2791814 r2981043  
    88use JUVO_MailEditor\Mail_Trigger_TAX;
    99use JUVO_MailEditor\Mails_PT;
     10use JUVO_MailEditor\Trigger_Registry;
    1011use WP_User;
    1112
    1213class Password_Changed extends Mail_Generator {
    13 
    14     public function addCustomFields( CMB2 $cmb ): CMB2 {
    15 
    16         /** There are usecases to allow sending this mail to other recipients
    17         if ( $cmb->object_id() && has_term( $this->getTrigger(), Mail_Trigger_TAX::TAXONOMY_NAME, $cmb->object_id() ) ) {
    18 
    19             $recipients = $cmb->get_field( Mails_PT::POST_TYPE_NAME . '_recipients' );
    20             if (!empty( $recipients->value )) {
    21                 update_post_meta( $cmb->object_id(), Mails_PT::POST_TYPE_NAME . '_recipients', [] );
    22             }
    23             $cmb->remove_field( Mails_PT::POST_TYPE_NAME . '_recipients' );
    24 
    25             $cc = $cmb->get_field( Mails_PT::POST_TYPE_NAME . '_cc' );
    26             if (!empty( $cc->value )) {
    27                 update_post_meta( $cmb->object_id(), Mails_PT::POST_TYPE_NAME . '_cc', [] );
    28             }
    29             $cmb->remove_field( Mails_PT::POST_TYPE_NAME . '_cc' );
    30 
    31             $bcc = $cmb->get_field( Mails_PT::POST_TYPE_NAME . '_bcc' );
    32             if (!empty( $bcc->value )) {
    33                 update_post_meta( $cmb->object_id(), Mails_PT::POST_TYPE_NAME . '_bcc', [] );
    34             }
    35             $cmb->remove_field( Mails_PT::POST_TYPE_NAME . '_bcc' );
    36 
    37         }
    38         **/
    39 
    40         return $cmb;
    41     }
    4214
    4315    protected function getTrigger(): string {
     
    4517    }
    4618
    47     public function getSubject( string $subject ): string {
     19    public function prepareSend( array $email, array $user ): array {
    4820
    49         if ( ! empty( $subject ) ) {
    50             return $subject;
    51         }
     21        Trigger_Registry::getInstance()->get( $this->getTrigger() )
     22                        ->setContext( [ "user" => get_user_by( "ID", $user['ID'] ) ] );
    5223
    53         return sprintf( __( '%s Password Changed', 'default' ), '{{site.name}}' );
     24        return $email;
    5425    }
    5526
    56     public function getMessage( string $message ): string {
    57 
    58         if ( ! empty( $message ) ) {
    59             return $message;
    60         }
    61 
    62         $message = __(
    63             'Hi ###USERNAME###,
    64 
    65 This notice confirms that your password was changed on ###SITENAME###.
    66 
    67 If you did not change your password, please contact the Site Administrator at
    68 ###ADMIN_EMAIL###
    69 
    70 This email has been sent to ###EMAIL###
    71 
    72 Regards,
    73 All at ###SITENAME###
    74 ###SITEURL###',
    75             'default'
    76         );
    77 
    78         $message = str_replace(
    79             array(
    80                 '###USERNAME###',
    81                 '###SITENAME###',
    82                 '###ADMIN_EMAIL###',
    83                 '###SITEURL###',
    84                 '###EMAIL###',
    85             ),
    86             array( '{{user.name}}', '{{site.name}}', '{{site.admin_email}}', '{{site.url}}', '{{user.user_email}}' ),
    87             $message
    88         );
    89 
    90         return $message;
    91     }
    92 
    93     public function getRecipients( array $recipients ): array {
    94 
    95         if ( ! empty( $recipients ) ) {
    96             return $recipients;
    97         }
    98 
    99         return [ '{{user.user_email}}' ];
    100     }
    101 
    102     public function prepareSend( array $email, array $user ): array {
    103         do_action( "juvo_mail_editor_send", $this->getTrigger(), [ "user" => get_user_by( "ID", $user['ID'] ) ] );
    104 
    105         return $this->emptyMailArray( $email );
     27    protected function getMailArrayHook(): string {
     28        return "wp_password_change_notification_email";
    10629    }
    10730
  • juvo-mail-editor/trunk/src/Mails/Password_Changed_Admin.php

    r2677983 r2981043  
    66use CMB2;
    77use JUVO_MailEditor\Mail_Generator;
     8use JUVO_MailEditor\Trigger_Registry;
    89use WP_User;
    910
     
    1819    }
    1920
    20     public function getSubject( string $subject ): string {
     21    public function prepareSend( array $email, WP_User $user ): array {
    2122
    22         if ( ! empty( $subject ) ) {
    23             return $subject;
    24         }
     23        Trigger_Registry::getInstance()->get( $this->getTrigger() )
     24                        ->setContext( [ "user" => $user ] );
    2525
    26         return sprintf( __( '%s Password Changed', 'default' ), '{{site.name}}' );
     26        return $email;
    2727    }
    2828
    29     public function getMessage( string $message ): string {
    30 
    31         if ( ! empty( $message ) ) {
    32             return $message;
    33         }
    34 
    35         return sprintf( __( 'Password changed for user: %s', 'default' ), '{{user.name}}' ) . "\r\n";
    36     }
    37 
    38     public function getRecipients( array $recipients ): array {
    39 
    40         if ( ! empty( $recipients ) ) {
    41             return $recipients;
    42         }
    43 
    44         return [ '{{site.admin_email}}' ];
    45     }
    46 
    47     public function prepareSend( array $email, WP_User $user ): array {
    48         do_action( "juvo_mail_editor_send", $this->getTrigger(), [ "user" => $user ] );
    49 
    50         return $this->emptyMailArray( $email );
     29    protected function getMailArrayHook(): string {
     30        return "retrieve_password_notification_email";
    5131    }
    5232
  • juvo-mail-editor/trunk/src/Mails/Password_Reset.php

    r2791814 r2981043  
    44namespace JUVO_MailEditor\Mails;
    55
    6 use CMB2;
    76use JUVO_MailEditor\Mail_Generator;
    8 use JUVO_MailEditor\Mail_Trigger_TAX;
    9 use JUVO_MailEditor\Mails_PT;
     7use JUVO_MailEditor\Trigger_Registry;
    108use WP_User;
    119
     
    1614    }
    1715
    18     public function addCustomFields( CMB2 $cmb ): CMB2 {
     16    public function prepareSend( array $args, string $key, $user_login, WP_User $user ): array {
    1917
    20         /** There are usecases to allow sending this mail to other recipients
    21         if ( $cmb->object_id() && has_term( $this->getTrigger(), Mail_Trigger_TAX::TAXONOMY_NAME, $cmb->object_id() ) ) {
     18        Trigger_Registry::getInstance()->get( $this->getTrigger() )
     19            ->setContext( [ "user" => $user, 'key' => $key ] );
    2220
    23             $recipients = $cmb->get_field( Mails_PT::POST_TYPE_NAME . '_recipients' );
    24             if (!empty( $recipients->value )) {
    25                 update_post_meta( $cmb->object_id(), Mails_PT::POST_TYPE_NAME . '_recipients', [] );
    26             }
    27             $cmb->remove_field( Mails_PT::POST_TYPE_NAME . '_recipients' );
    28 
    29             $cc = $cmb->get_field( Mails_PT::POST_TYPE_NAME . '_cc' );
    30             if (!empty( $cc->value )) {
    31                 update_post_meta( $cmb->object_id(), Mails_PT::POST_TYPE_NAME . '_cc', [] );
    32             }
    33             $cmb->remove_field( Mails_PT::POST_TYPE_NAME . '_cc' );
    34 
    35             $bcc = $cmb->get_field( Mails_PT::POST_TYPE_NAME . '_bcc' );
    36             if (!empty( $bcc->value )) {
    37                 update_post_meta( $cmb->object_id(), Mails_PT::POST_TYPE_NAME . '_bcc', [] );
    38             }
    39             $cmb->remove_field( Mails_PT::POST_TYPE_NAME . '_bcc' );
    40 
    41         }
    42         **/
    43 
    44         return $cmb;
     21        return $args;
    4522    }
    4623
    47     public function prepareSend( $message, string $key, $user_login, WP_User $user ): string {
    48         do_action( "juvo_mail_editor_send", $this->getTrigger(), [ "user" => $user, 'key' => $key ] );
    49 
    50         return '';
    51     }
    52 
    53     public function getSubject( string $subject ): string {
    54 
    55         if ( ! empty( $subject ) ) {
    56             return $subject;
    57         }
    58 
    59         return __( 'Password Reset', 'juvo-mail-editor' );
    60     }
    61 
    62     public function getMessage( string $message ): string {
    63 
    64         if ( ! empty( $message ) ) {
    65             return $message;
    66         }
    67 
    68         $message = __( 'Someone has requested a password reset for the following account:', 'default' ) . "\r\n\r\n";
    69         $message .= sprintf( __( 'Site Name: %s', 'default' ), '{{ site.name }}' ) . "\r\n\r\n";
    70         $message .= sprintf( __( 'Username: %s', 'default' ), '{{ user.name }}' ) . "\r\n\r\n";
    71         $message .= __( 'If this was a mistake, ignore this email and nothing will happen.', 'default' ) . "\r\n\r\n";
    72         $message .= __( 'To reset your password, visit the following address:', 'default' ) . "\r\n\r\n";
    73         $message .= '{{password_reset_link}}' . "\r\n\r\n";
    74 
    75         return $message;
    76     }
    77 
    78     public function getRecipients( array $recipients ): array {
    79 
    80         if ( ! empty( $recipients ) ) {
    81             return $recipients;
    82         }
    83 
    84         return [ '{{user.user_email}}' ];
     24    protected function getMailArrayHook(): string {
     25        return "retrieve_password_notification_email";
    8526    }
    8627
  • juvo-mail-editor/trunk/src/Mails/Password_Reset_Admin.php

    r2672700 r2981043  
    66use CMB2;
    77use JUVO_MailEditor\Mail_Generator;
     8use JUVO_MailEditor\Trigger_Registry;
    89use WP_User;
    910
     
    1213    public function addCustomFields( CMB2 $cmb ): CMB2 {
    1314        return $cmb;
     15    }
     16
     17    public function prepareSend( array $message, $key, $user_login, WP_User $user ): array {
     18
     19
     20        Trigger_Registry::getInstance()->get( $this->getTrigger() )
     21            ->setContext( [ "user" => $user, 'key' => $key ] );
     22
     23        // This is not a native wordpress mail. Therefore no mailhook is set and sending need to be added manually
     24        do_action( "juvo_mail_editor_send", $this->getTrigger(), [ "user" => $user ] );
     25
     26        return $message;
    1427    }
    1528
     
    4558    }
    4659
    47     public function prepareSend( $message, $key, $user_login, WP_User $user ): string {
    48         do_action( "juvo_mail_editor_send", $this->getTrigger(), [ "user" => $user, 'key' => $key ] );
    49 
    50         return '';
    51     }
    52 
    5360    protected function getTrigger(): string {
    5461        return 'password_reset_admin';
  • juvo-mail-editor/trunk/src/Relay.php

    r2793158 r2981043  
    44namespace JUVO_MailEditor;
    55
    6 use JUVO_MailEditor\Mails\Generic;
     6use WP_HTML_Tag_Processor;
    77use WP_Post;
    8 use WP_Term;
    98
    109class Relay {
    1110
    12     /**
    13      * @var string
    14      */
    15     private $trigger;
    16 
    17     /**
    18      * @var array
    19      */
    20     private $placeholders;
    21 
    22     /**
    23      * @var WP_Term
    24      */
    25     private $term;
    26 
    27     /**
    28      * @var int[]|WP_Post[]
    29      */
    30     private $posts;
    31 
    32 
    33     private $context;
    34 
    35     /**
    36      * Relay constructor.
     11    private $args = [];
     12
     13    /**
     14     * This callback hooks into wp_mail and checks if the header indicates that this mail should be processed by juvo_mail_editor.
     15     * If so it will process the mail and return the mail array.
     16     * If multiple templates are set up for one trigger, the first one will be returned callback and all other mails will be send directly with wp_mail in "process_trigger".
     17     *
     18     * @param array $args {
     19     *      Array of the `wp_mail()` arguments.
     20     *
     21     * @return array
     22     */
     23    public function wpmail_filter_callback( array $args ): array {
     24
     25        // Trigger info lives in header. If no headers set exit early
     26        if ( empty( $args['headers'] ) ) {
     27            return $args;
     28        }
     29
     30        // Headers can be passed as array and as string
     31        if (!is_array($args['headers'])) {
     32            $args['headers'] = explode("\r\n", $args['headers']);
     33        }
     34
     35        $this->args = $args;
     36
     37        $mailArrays = [];
     38
     39        foreach ( $args['headers'] as $header ) {
     40            if ( strpos( $header, 'X-JUVO-ME-Trigger:' ) !== false ) {
     41                $value = trim( explode( ':', $header, 2 )[1] );
     42                $mailArrays = array_merge($mailArrays, $this->buildMailArrays( $value ));
     43            }
     44        }
     45
     46        // Return first mail array item;
     47        if (!empty($mailArrays)) {
     48            $this->process_trigger( $mailArrays, true );
     49            return reset($mailArrays);
     50        }
     51
     52        return $args;
     53
     54    }
     55
     56    /**
     57     * Some triggers might not use wp_mail natively. It is totally fine to directly send the mails with juvo_mail_editor.
     58     * In this case we do not hook into wp_mail but directly send the mails.
     59     *
     60     * Callback for the "juvo_mail_editor_send" action.
    3761     *
    3862     * @param string $trigger
    3963     * @param array $context
    40      * @param WP_Term $term
    41      */
    42     public function __construct( string $trigger, array $context, WP_Term $term ) {
    43         $this->trigger      = $trigger;
    44         $this->context      = $context;
    45         $this->term         = $term;
    46         $this->posts        = $this->setPostsForTrigger();
    47         $this->placeholders = $this->preparePlaceholders();
    48     }
    49 
    50     /**
    51      * @return WP_Post[]
    52      */
    53     private function setPostsForTrigger(): array {
    54 
    55         return get_posts(
    56             array(
    57                 'post_type'        => Mails_PT::POST_TYPE_NAME,
    58                 'post_status'      => 'publish',
    59                 'numberposts'      => - 1,
    60                 'suppress_filters' => false,
    61                 'tax_query'        => array(
    62                     array(
    63                         'taxonomy' => Mail_Trigger_TAX::TAXONOMY_NAME,
    64                         'field'    => 'id',
    65                         'terms'    => $this->term,
    66                     ),
    67                 ),
    68             )
    69         );
    70 
    71     }
    72 
    73     /**
    74      * @return array
    75      */
    76     public function preparePlaceholders(): array {
    77         return apply_filters( "juvo_mail_editor_{$this->trigger}_placeholders", array(), $this->context );
    78     }
    79 
    80     /**
    81      * Sends mails for all posts that are associated with the trigger.
    82      * To send mails even if not post is associated set the "alwaysSend" flag.
    83      *
    84      * If the flag is set the term defaults are used for the mailing
    85      */
    86     public static function sendMails( string $trigger, array $context = array() ) {
    87 
    88         $term = get_term_by( 'slug', $trigger, Mail_Trigger_TAX::TAXONOMY_NAME );
    89 
    90         if ( ! $term instanceof WP_Term ) {
    91             return false;
     64     *
     65     * @return void
     66     */
     67    public function send_mails_action_callback( string $trigger, array $context = array() ) {
     68
     69        // Add Context
     70        Trigger_Registry::getInstance()->get( $trigger )
     71                        ->setContext( $context );
     72
     73        $mailArrays = $this->buildMailArrays( $trigger );
     74        $this->process_trigger( $mailArrays, false );
     75    }
     76
     77    /**
     78     * Send the given mail array and optionally return the first mail array.
     79     *
     80     * @param array $mailArrays
     81     * @param bool $return_first
     82     *
     83     * @return array
     84     */
     85    public function process_trigger(  array $mailArrays, bool $return_first = false ): array {
     86
     87        // Exit early if no mails are set up
     88        if ( empty( $mailArrays ) ) {
     89            return [];
     90        }
     91
     92        // Avoid endless loop, so unhook
     93        remove_filter( 'wp_mail', array( $this, 'wpmail_filter_callback' ), 10 );
     94
     95        // Send all others
     96        $i = 0;
     97        foreach ( $mailArrays as $key => $mailArray ) {
     98
     99            // Send all but first one
     100            if ( $return_first && $i === 0 ) {
     101                $i ++;
     102                continue;
     103            }
     104
     105            // Avoid endless loop, so unhook
     106            remove_filter( 'wp_mail', array( $this, 'wpmail_filter_callback' ), 10 );
     107
     108            wp_mail( $mailArray['to'], $mailArray['subject'], $mailArray['message'], $mailArray['headers'], $mailArray['attachments'] );
     109
     110            // Add unhooked code again
     111            add_filter( 'wp_mail', array( $this, 'wpmail_filter_callback' ), 10, 1 );
     112
     113            // Remove mail from array so that either none or only one mail is returned
     114            unset( $mailArrays[ $key ] );
     115            $i ++;
     116        }
     117
     118        return $mailArrays;
     119    }
     120
     121    /**
     122     * Build mail array for each template and returns one combined array that contains all mails to be sent.
     123     * This function also takes care that translations are applied correctly for each template.
     124     *
     125     * @param string $slug
     126     *
     127     * @return array
     128     */
     129    public function buildMailArrays( string $slug ): array {
     130
     131        // Get Trigger from Registry
     132        $trigger = Trigger_Registry::getInstance()->get( $slug );
     133        if ( empty( $trigger ) ) {
     134            return [];
    92135        }
    93136
    94137        // Add Muted Capability
    95         if ( self::triggerIsMuted( $trigger ) ) {
    96             return false;
    97         }
    98 
    99         $relay = new self( $trigger, $context, $term );
     138        if ( $trigger->isMuted() ) {
     139            return [];
     140        }
    100141
    101142        // Store blog language defaults
     
    103144        $blogLocale = get_locale();
    104145
    105         if ( ! empty( $relay->posts ) ) {
    106             // If templates were created for trigger
    107 
    108             foreach ( $relay->posts as $post ) {
    109 
    110                 $locale = apply_filters( "juvo_mail_editor_{$trigger}_language", $blogLocale, $relay->context );
    111                 $lang   = locale_get_primary_language( $locale );
    112 
    113                 // Switch language context
    114                 $switched_locale = switch_to_locale( $locale );
     146        $mails     = [];
     147        $templates = $trigger->getRelatedPosts();
     148
     149        $locale = apply_filters( "juvo_mail_editor_{$trigger->getSlug()}_language", $blogLocale, $trigger->getContext() );
     150        $lang   = locale_get_primary_language( $locale );
     151
     152        // Switch language context
     153        $switched_locale = switch_to_locale( $locale );
     154
     155
     156        if ( ! $templates ) {
     157            // If not template is set up try to get mail array from hooks
     158            $mails[] = $this->buildMailArray( $trigger );
     159        } else {
     160
     161            // Build mail array for each template
     162            foreach ( $templates as $template ) {
    115163
    116164                // Get translated post with WPML
    117                 $translationId = apply_filters( 'wpml_object_id', $post->ID, Mails_PT::POST_TYPE_NAME, true, $lang );
    118                 if ( $translationId && $translationId !== $post->ID && get_post_status( $translationId ) === 'publish' ) {
    119                     $post = get_post( $translationId );
     165                $translationId = apply_filters( 'wpml_object_id', $template->ID, Mails_PT::POST_TYPE_NAME, true, $lang );
     166                if ( $translationId && $translationId !== $template->ID && get_post_status( $translationId ) === 'publish' ) {
     167                    $template = get_post( $translationId );
    120168                }
    121169
    122                 // Recipients
    123                 $recipients = $relay->prepareRecipients( $post );
    124 
    125                 // Content
    126                 $content = $relay->prepareContent( $post );
    127 
    128                 // Subject
    129                 $subject = $relay->prepareSubject( $post );
    130 
    131                 // Headers
    132                 $headers = $relay->prepareHeaders( $post );
    133 
    134                 // Attachments
    135                 $attachments = $relay->prepareAttachments( $post );
    136 
    137                 // Restore language context
    138                 if ( $switched_locale ) {
    139                     restore_previous_locale();
    140                 }
    141 
    142                 $mail = new Generic( $subject, $content, $recipients, $headers, $attachments );
    143                 $mail->send();
    144 
    145             }
    146         } else {
    147             // No templates created use trigger defaults
    148 
    149             // Some triggers might only send mails if a post is associated
    150             $alwaysSent = apply_filters( "juvo_mail_editor_{$trigger}_always_sent", false, $relay->context );
    151             if ( ! $alwaysSent ) {
    152                 return false;
    153             }
    154 
    155             $lang = apply_filters( "juvo_mail_editor_{$trigger}_language", $blogLocale, $relay->context );
    156 
    157             $switched_locale = switch_to_locale( $lang );
    158 
    159             // Fallback if not posts are found for configured trigger
    160             $content     = $relay->prepareContent();
    161             $subject     = $relay->prepareSubject();
    162             $recipients  = $relay->prepareRecipients();
    163             $headers     = $relay->prepareHeaders();
    164             $attachments = $relay->prepareAttachments();
    165 
    166             if ( $switched_locale ) {
    167                 restore_previous_locale();
    168             }
    169 
    170             $mail = new Generic( $subject, $content, $recipients, $headers, $attachments );
    171             $mail->send();
    172 
    173         }
    174 
    175         return true;
    176     }
    177 
    178     /**
    179      * Checks if the given trigger is globally muted.
    180      * Might be called manually if the mail is not send using the 'Relay' class but eg. with a filter.
    181      *
    182      * @param string $trigger
    183      *
    184      * @return bool
    185      */
    186     public static function triggerIsMuted( string $trigger ): bool {
    187         $pluginSettings = get_option( 'settings' );
    188 
    189         if ( isset( $pluginSettings['trigger_mute'] ) ) {
    190             return in_array( $trigger, $pluginSettings['trigger_mute'], true );
    191         }
    192 
    193         return false;
    194     }
    195 
    196     /**
     170                $mails[] = $this->buildMailArray( $trigger, $template );
     171            }
     172
     173        }
     174
     175        // Restore language context
     176        if ( $switched_locale ) {
     177            restore_previous_locale();
     178        }
     179
     180        return $mails;
     181
     182    }
     183
     184    /**
     185     * Builds an array with mail args in a way that WordPress uses internally
     186     *
     187     * @param Trigger $trigger
    197188     * @param WP_Post|null $post
    198189     *
    199190     * @return array
    200191     */
    201     public function prepareRecipients( WP_Post $post = null ): array {
     192    public function buildMailArray( Trigger $trigger, WP_Post $post = null ): array {
     193
     194        $new_args = [
     195            'to'          => $this->prepareRecipients( $trigger, $post ),
     196            'subject'     => $this->prepareSubject( $trigger, $post ),
     197            'message'     => $this->prepareContent( $trigger, $post ),
     198            'attachments' => $this->prepareAttachments( $trigger, $post ),
     199        ];
     200
     201        $new_args['headers'] = implode("\r\n", $this->prepareHeaders( $trigger, $post, $new_args['message'] ));
     202
     203        // Replace empty args with original args
     204        foreach ( $new_args as $key => $value ) {
     205            if ( empty( $value ) ) {
     206                $new_args[ $key ] = $this->args[ $key ] ?? "";
     207            }
     208        }
     209
     210        return $new_args;
     211    }
     212
     213    /**
     214     * @param WP_Post|null $post
     215     * @param Trigger $trigger
     216     *
     217     * @return array
     218     */
     219    public function prepareRecipients( Trigger $trigger, WP_Post $post = null ): array {
    202220
    203221        $recipients = [];
     
    208226        }
    209227
    210         $recipients = apply_filters( "juvo_mail_editor_{$this->trigger}_recipients", $recipients, $this->context );
    211 
    212         return apply_filters( 'juvo_mail_editor_after_recipients_placeholder', $this->parseToCcBcc( $recipients ), $this->trigger, $this->context );
     228        $recipients = apply_filters( "juvo_mail_editor_{$trigger->getSlug()}_recipients", $recipients, $trigger->getContext() );
     229
     230        return apply_filters( 'juvo_mail_editor_after_recipients_placeholder', $this->parseToCcBcc( $trigger, $recipients ), $trigger->getSlug(), $trigger->getContext() );
    213231    }
    214232
    215233    /**
    216234     * @param WP_Post|null $post
     235     * @param Trigger $trigger
    217236     *
    218237     * @return string
    219238     */
    220     public function prepareContent( WP_Post $post = null ): string {
     239    public function prepareContent( Trigger $trigger, WP_Post $post = null ): string {
    221240
    222241        $content = '';
     
    232251        }
    233252
    234         $content = apply_filters( "juvo_mail_editor_{$this->trigger}_message", $content, $this->context );
    235         $content = Placeholder::replacePlaceholder( $this->placeholders, $content, $this->context );
    236         $content = apply_filters( 'juvo_mail_editor_after_content_placeholder', $content, $this->trigger, $this->context );
    237 
    238         $content = $this->setContentType( $content );
     253        $content = apply_filters( "juvo_mail_editor_{$trigger->getSlug()}_message", $content, $trigger->getContext() );
     254        $content = Placeholder::replacePlaceholder( $this->preparePlaceholders( $trigger ), $content, $trigger->getContext() );
     255
     256        // If html tags present use wpautop to automagically fix linebreaks
     257        $p = new WP_HTML_Tag_Processor( $content );
     258        if ($p->next_tag()) {
     259            $content = wpautop( $content );
     260        }
     261
     262        $content = apply_filters( 'juvo_mail_editor_after_content_placeholder', $content, $trigger->getSlug(), $trigger->getContext() );
    239263
    240264        return $content;
    241265    }
    242266
    243     public function setContentType( string $message ): string {
    244 
    245         $type    = 'text/html';
    246 
    247         // If plaintext make linebreaks html compliant
    248         if($message == strip_tags($message)){
    249             $message = wpautop( $message );
    250         }
    251 
    252         add_filter(
    253             'wp_mail_content_type',
    254             function( $content_type ) use ( $type ) {
    255                 return $type;
    256             },
    257             10
    258         );
    259 
    260         return $message;
    261     }
    262 
    263267    /**
    264268     * @param WP_Post|null $post
     269     * @param Trigger $trigger
    265270     *
    266271     * @return string
    267272     */
    268     public function prepareSubject( WP_Post $post = null ): string {
     273    public function prepareSubject( Trigger $trigger, WP_Post $post = null ): string {
    269274
    270275        $subject = '';
     
    275280        }
    276281
    277         $subject = apply_filters( "juvo_mail_editor_{$this->trigger}_subject", $subject, $this->context );
    278         $subject = Placeholder::replacePlaceholder( $this->placeholders, $subject, $this->context );
    279 
    280         return apply_filters( 'juvo_mail_editor_after_subject_placeholder', $subject, $this->trigger, $this->context );
    281     }
    282 
    283     /**
    284      * @return array
    285      */
    286     public function getPlaceholders(): array {
    287         return $this->placeholders;
    288     }
    289 
    290     /**
    291      * @return WP_Term
    292      */
    293     public function getTerm() {
    294         return $this->term;
    295     }
    296 
    297     /**
    298      * @return WP_Post[]
    299      */
    300     public function getPosts(): array {
    301         return $this->posts;
     282        $subject = apply_filters( "juvo_mail_editor_{$trigger->getSlug()}_subject", $subject, $trigger->getContext() );
     283        $subject = Placeholder::replacePlaceholder( $this->preparePlaceholders( $trigger ), $subject, $trigger->getContext() );
     284
     285        return apply_filters( 'juvo_mail_editor_after_subject_placeholder', $subject, $trigger->getSlug(), $trigger->getContext() );
     286    }
     287
     288    /**
     289     * @param Trigger $trigger
     290     *
     291     * @return array
     292     */
     293    public function preparePlaceholders( Trigger $trigger ): array {
     294        return apply_filters( "juvo_mail_editor_{$trigger->getSlug()}_placeholders", array(), $trigger->getContext() );
    302295    }
    303296
    304297    /**
    305298     * Sets custom headers.
    306      * By defaults adds headers to identify mail-editor mails through wordpress
     299     * By defaults adds headers to identify mail-editor mails through WordPress
    307300     *
    308301     * @param WP_Post|null $post
     
    310303     * @return mixed|void
    311304     */
    312     private function prepareHeaders( WP_Post $post = null ) {
    313 
    314         $headers[] = "X-JUVO-ME-Trigger: {$this->trigger}";
     305    private function prepareHeaders( Trigger $trigger, WP_Post $post = null, string $content = "" ) {
     306
     307        $headers[] = "X-JUVO-ME-Trigger: {$trigger->getSlug()}";
    315308
    316309        if ( $post ) {
     
    318311        }
    319312
     313        // Use new Tag Processor API to dynamically set content type
     314        if (!empty($content)) {
     315            $p = new WP_HTML_Tag_Processor( $content );
     316            if ($p->next_tag()) {
     317                $headers[] = "Content-Type: text/html; charset=UTF-8";
     318            }
     319        }
     320
    320321        // Add CC and BCC
    321         $headers = $this->prepareCc( $headers, $post );
    322         $headers = $this->prepareBcc( $headers, $post );
    323 
    324         return apply_filters( "juvo_mail_editor_{$this->trigger}_headers", $headers, $this->context );
    325     }
    326 
    327     private function prepareAttachments( WP_Post $post = null ): array {
     322        $headers = array_merge($headers, $this->prepareCc( $headers, $trigger, $post ));
     323        $headers = array_merge($headers, $this->prepareBcc( $headers, $trigger, $post ));
     324
     325        return apply_filters( "juvo_mail_editor_{$trigger->getSlug()}_headers", $headers, $trigger->getContext() );
     326    }
     327
     328    private function prepareAttachments( Trigger $trigger, WP_Post $post = null ): array {
    328329
    329330        $attachments = [];
     
    342343        }
    343344
    344         return apply_filters( "juvo_mail_editor_{$this->trigger}_attachments", $attachments, $this->context );
    345     }
    346 
    347     private function prepareCc( array $headers, WP_Post $post = null ): array {
     345        return apply_filters( "juvo_mail_editor_{$trigger->getSlug()}_attachments", $attachments, $trigger->getContext() );
     346    }
     347
     348    private function prepareCc( array $headers, Trigger $trigger, WP_Post $post = null ): array {
    348349
    349350        $cc = [];
     
    351352        // phpcs:ignore Squiz.PHP.DisallowMultipleAssignments.FoundInControlStructure
    352353        if ( $post ) {
    353             $cc = get_post_meta( $post->ID, Mails_PT::POST_TYPE_NAME . '_cc', true ) ?: [] ;
    354         }
    355 
    356         $cc = apply_filters( "juvo_mail_editor_{$this->trigger}_cc", $cc, $this->context );
    357         $cc = apply_filters( 'juvo_mail_editor_after_cc_placeholder', $this->parseToCcBcc( $cc, "Cc:" ), $this->trigger, $this->context );
    358 
    359         return array_merge( $headers, $cc );
    360     }
    361 
    362     private function prepareBcc( array $headers, WP_Post $post = null ): array {
     354            $cc = get_post_meta( $post->ID, Mails_PT::POST_TYPE_NAME . '_cc', true ) ?: [];
     355        }
     356
     357        $cc = apply_filters( "juvo_mail_editor_{$trigger->getSlug()}_cc", $cc, $trigger->getContext() );
     358        $cc = apply_filters( 'juvo_mail_editor_after_cc_placeholder', $this->parseToCcBcc( $trigger, $cc, "Cc:" ), $trigger->getSlug(), $trigger->getContext() );
     359
     360        return $cc;
     361    }
     362
     363    private function prepareBcc( array $headers, Trigger $trigger, WP_Post $post = null ): array {
    363364
    364365        $bcc = [];
     
    369370        }
    370371
    371         $bcc = apply_filters( "juvo_mail_editor_{$this->trigger}_bcc", $bcc, $this->context );
    372         $bcc = apply_filters( 'juvo_mail_editor_after_bcc_placeholder', $this->parseToCcBcc( $bcc, "Bcc:" ), $this->trigger, $this->context );
    373 
    374         return array_merge( $headers, $bcc );
     372        $bcc = apply_filters( "juvo_mail_editor_{$trigger->getSlug()}_bcc", $bcc, $trigger->getContext() );
     373        $bcc = apply_filters( 'juvo_mail_editor_after_bcc_placeholder', $this->parseToCcBcc( $trigger, $bcc, "Bcc:" ), $trigger->getSlug(), $trigger->getContext() );
     374
     375        return $bcc;
    375376    }
    376377
     
    378379     * Parses cmb2 repeater groups or strings to wp_mail compatible array format for "to", "cc" and "bcc"
    379380     *
     381     * @param Trigger $trigger
    380382     * @param array|string $recipients
    381383     * @param string $prefix "Cc:" or "Bcc:"
     
    383385     * @return array
    384386     */
    385     private function parseToCcBcc( $recipients, string $prefix = "" ): array {
     387    private function parseToCcBcc( Trigger $trigger, $recipients, string $prefix = "" ): array {
    386388
    387389        if ( empty( $recipients ) ) {
     
    401403            }
    402404
    403             $recipient = Placeholder::replacePlaceholder( $this->placeholders, $recipient, $this->context );
     405            $recipient = Placeholder::replacePlaceholder( $this->preparePlaceholders( $trigger ), $recipient, $trigger->getContext() );
    404406
    405407            if ( ! empty( $prefix ) ) {
  • juvo-mail-editor/trunk/src/Trigger.php

    r2644151 r2981043  
    33
    44namespace JUVO_MailEditor;
     5
     6use WP_Term;
    57
    68/**
     
    2426
    2527    /**
     28     * @var WP_Term|null
     29     */
     30    private ?WP_Term $term;
     31
     32    private array $context = [];
     33
     34    private string $mailHook;
     35
     36    /**
    2637     * Trigger constructor.
    2738     *
    2839     * @param string $name
    2940     * @param string $slug
     41     * @param string $mailHook
    3042     */
    31     public function __construct( string $name, string $slug ) {
    32         $this->name = $name;
    33         $this->slug = $slug;
     43    public function __construct( string $name, string $slug, string $mailHook = '' ) {
     44        $this->name     = $name;
     45        $this->slug     = $slug;
     46        $this->mailHook = $mailHook;
     47        $this->term     = get_term_by( 'slug', $slug, Mail_Trigger_TAX::TAXONOMY_NAME ) ?: null;
     48
     49        add_filter( $this->mailHook, array( $this, 'addTriggerToHeader' ), 9, 1 );
     50    }
     51
     52    public function getTerm(): ?WP_Term {
     53        return $this->term ?? null;
    3454    }
    3555
     
    4868    }
    4969
     70    /**
     71     * Check if a trigger is globally muted
     72     *
     73     * @return bool
     74     */
     75    public function isMuted(): bool {
     76        $pluginSettings = get_option( 'settings' );
     77
     78        if ( isset( $pluginSettings['trigger_mute'] ) ) {
     79            return in_array( $this->slug, $pluginSettings['trigger_mute'], true );
     80        }
     81
     82        return false;
     83    }
     84
     85    public function getRelatedPosts(): array {
     86
     87        if ( ! $this->getTerm() instanceof WP_Term ) {
     88            return [];
     89        }
     90
     91        return get_posts(
     92            array(
     93                'post_type'        => Mails_PT::POST_TYPE_NAME,
     94                'post_status'      => 'publish',
     95                'numberposts'      => - 1,
     96                'suppress_filters' => false,
     97                'tax_query'        => array(
     98                    array(
     99                        'taxonomy' => Mail_Trigger_TAX::TAXONOMY_NAME,
     100                        'field'    => 'id',
     101                        'terms'    => $this->term,
     102                    ),
     103                ),
     104            )
     105        );
     106    }
     107
     108    public function getMailHook(): string {
     109        return $this->mailHook;
     110    }
     111
     112    public function getContext(): array {
     113        return $this->context;
     114    }
     115
     116    public function setContext( array $context ): void {
     117        $this->context = $context;
     118    }
     119
     120    /**
     121     * Add trigger slug to mail header to identify throughout the process
     122     *
     123     * @param array $args
     124     *
     125     * @return array
     126     */
     127    public function addTriggerToHeader( array $args ): array {
     128
     129        // Enforce headers to be array
     130        if ( ! empty( $args['headers'] ) && is_string( $args['headers'] ) ) {
     131            $args['headers'] = explode( "\n", str_replace( "\r\n", "\n", $args['headers'] ) );
     132        } elseif(empty($args['headers'])) {
     133            $args['headers'] = [];
     134        }
     135
     136        $args['headers'][] = "X-JUVO-ME-Trigger: {$this->getSlug()}";
     137
     138        // Format back to string since some smtp plugins do not support arrays
     139        $args['headers'] = implode("\r\n", $args['headers']);
     140
     141        return $args;
     142
     143    }
     144
    50145}
  • juvo-mail-editor/trunk/vendor/autoload.php

    r2793158 r2981043  
    44
    55if (PHP_VERSION_ID < 50600) {
    6     echo 'Composer 2.3.0 dropped support for autoloading on PHP <5.6 and you are running '.PHP_VERSION.', please upgrade PHP or use Composer 2.2 LTS via "composer self-update --2.2". Aborting.'.PHP_EOL;
    7     exit(1);
     6    if (!headers_sent()) {
     7        header('HTTP/1.1 500 Internal Server Error');
     8    }
     9    $err = 'Composer 2.3.0 dropped support for autoloading on PHP <5.6 and you are running '.PHP_VERSION.', please upgrade PHP or use Composer 2.2 LTS via "composer self-update --2.2". Aborting.'.PHP_EOL;
     10    if (!ini_get('display_errors')) {
     11        if (PHP_SAPI === 'cli' || PHP_SAPI === 'phpdbg') {
     12            fwrite(STDERR, $err);
     13        } elseif (!headers_sent()) {
     14            echo $err;
     15        }
     16    }
     17    trigger_error(
     18        $err,
     19        E_USER_ERROR
     20    );
    821}
    922
    1023require_once __DIR__ . '/composer/autoload_real.php';
    1124
    12 return ComposerAutoloaderInit9c6548f6eba24e2705cd7acb45e71c62::getLoader();
     25return ComposerAutoloaderInitf48a6f250b401e6a6afc3e88e6ee63ed::getLoader();
  • juvo-mail-editor/trunk/vendor/composer/ClassLoader.php

    r2665450 r2981043  
    4343class ClassLoader
    4444{
    45     /** @var ?string */
     45    /** @var \Closure(string):void */
     46    private static $includeFile;
     47
     48    /** @var string|null */
    4649    private $vendorDir;
    4750
    4851    // PSR-4
    4952    /**
    50      * @var array[]
    51      * @psalm-var array<string, array<string, int>>
     53     * @var array<string, array<string, int>>
    5254     */
    5355    private $prefixLengthsPsr4 = array();
    5456    /**
    55      * @var array[]
    56      * @psalm-var array<string, array<int, string>>
     57     * @var array<string, list<string>>
    5758     */
    5859    private $prefixDirsPsr4 = array();
    5960    /**
    60      * @var array[]
    61      * @psalm-var array<string, string>
     61     * @var list<string>
    6262     */
    6363    private $fallbackDirsPsr4 = array();
     
    6565    // PSR-0
    6666    /**
    67      * @var array[]
    68      * @psalm-var array<string, array<string, string[]>>
     67     * List of PSR-0 prefixes
     68     *
     69     * Structured as array('F (first letter)' => array('Foo\Bar (full prefix)' => array('path', 'path2')))
     70     *
     71     * @var array<string, array<string, list<string>>>
    6972     */
    7073    private $prefixesPsr0 = array();
    7174    /**
    72      * @var array[]
    73      * @psalm-var array<string, string>
     75     * @var list<string>
    7476     */
    7577    private $fallbackDirsPsr0 = array();
     
    7981
    8082    /**
    81      * @var string[]
    82      * @psalm-var array<string, string>
     83     * @var array<string, string>
    8384     */
    8485    private $classMap = array();
     
    8889
    8990    /**
    90      * @var bool[]
    91      * @psalm-var array<string, bool>
     91     * @var array<string, bool>
    9292     */
    9393    private $missingClasses = array();
    9494
    95     /** @var ?string */
     95    /** @var string|null */
    9696    private $apcuPrefix;
    9797
    9898    /**
    99      * @var self[]
     99     * @var array<string, self>
    100100     */
    101101    private static $registeredLoaders = array();
    102102
    103103    /**
    104      * @param ?string $vendorDir
     104     * @param string|null $vendorDir
    105105     */
    106106    public function __construct($vendorDir = null)
    107107    {
    108108        $this->vendorDir = $vendorDir;
    109     }
    110 
    111     /**
    112      * @return string[]
     109        self::initializeIncludeClosure();
     110    }
     111
     112    /**
     113     * @return array<string, list<string>>
    113114     */
    114115    public function getPrefixes()
     
    122123
    123124    /**
    124      * @return array[]
    125      * @psalm-return array<string, array<int, string>>
     125     * @return array<string, list<string>>
    126126     */
    127127    public function getPrefixesPsr4()
     
    131131
    132132    /**
    133      * @return array[]
    134      * @psalm-return array<string, string>
     133     * @return list<string>
    135134     */
    136135    public function getFallbackDirs()
     
    140139
    141140    /**
    142      * @return array[]
    143      * @psalm-return array<string, string>
     141     * @return list<string>
    144142     */
    145143    public function getFallbackDirsPsr4()
     
    149147
    150148    /**
    151      * @return string[] Array of classname => path
    152      * @psalm-return array<string, string>
     149     * @return array<string, string> Array of classname => path
    153150     */
    154151    public function getClassMap()
     
    158155
    159156    /**
    160      * @param string[] $classMap Class to filename map
    161      * @psalm-param array<string, string> $classMap
     157     * @param array<string, string> $classMap Class to filename map
    162158     *
    163159     * @return void
     
    176172     * appending or prepending to the ones previously set for this prefix.
    177173     *
    178      * @param string          $prefix  The prefix
    179      * @param string[]|string $paths   The PSR-0 root directories
    180      * @param bool            $prepend Whether to prepend the directories
     174     * @param string              $prefix  The prefix
     175     * @param list<string>|string $paths   The PSR-0 root directories
     176     * @param bool                $prepend Whether to prepend the directories
    181177     *
    182178     * @return void
     
    184180    public function add($prefix, $paths, $prepend = false)
    185181    {
     182        $paths = (array) $paths;
    186183        if (!$prefix) {
    187184            if ($prepend) {
    188185                $this->fallbackDirsPsr0 = array_merge(
    189                     (array) $paths,
     186                    $paths,
    190187                    $this->fallbackDirsPsr0
    191188                );
     
    193190                $this->fallbackDirsPsr0 = array_merge(
    194191                    $this->fallbackDirsPsr0,
    195                     (array) $paths
     192                    $paths
    196193                );
    197194            }
     
    202199        $first = $prefix[0];
    203200        if (!isset($this->prefixesPsr0[$first][$prefix])) {
    204             $this->prefixesPsr0[$first][$prefix] = (array) $paths;
     201            $this->prefixesPsr0[$first][$prefix] = $paths;
    205202
    206203            return;
     
    208205        if ($prepend) {
    209206            $this->prefixesPsr0[$first][$prefix] = array_merge(
    210                 (array) $paths,
     207                $paths,
    211208                $this->prefixesPsr0[$first][$prefix]
    212209            );
     
    214211            $this->prefixesPsr0[$first][$prefix] = array_merge(
    215212                $this->prefixesPsr0[$first][$prefix],
    216                 (array) $paths
     213                $paths
    217214            );
    218215        }
     
    223220     * appending or prepending to the ones previously set for this namespace.
    224221     *
    225      * @param string          $prefix  The prefix/namespace, with trailing '\\'
    226      * @param string[]|string $paths   The PSR-4 base directories
    227      * @param bool            $prepend Whether to prepend the directories
     222     * @param string              $prefix  The prefix/namespace, with trailing '\\'
     223     * @param list<string>|string $paths   The PSR-4 base directories
     224     * @param bool                $prepend Whether to prepend the directories
    228225     *
    229226     * @throws \InvalidArgumentException
     
    233230    public function addPsr4($prefix, $paths, $prepend = false)
    234231    {
     232        $paths = (array) $paths;
    235233        if (!$prefix) {
    236234            // Register directories for the root namespace.
    237235            if ($prepend) {
    238236                $this->fallbackDirsPsr4 = array_merge(
    239                     (array) $paths,
     237                    $paths,
    240238                    $this->fallbackDirsPsr4
    241239                );
     
    243241                $this->fallbackDirsPsr4 = array_merge(
    244242                    $this->fallbackDirsPsr4,
    245                     (array) $paths
     243                    $paths
    246244                );
    247245            }
     
    253251            }
    254252            $this->prefixLengthsPsr4[$prefix[0]][$prefix] = $length;
    255             $this->prefixDirsPsr4[$prefix] = (array) $paths;
     253            $this->prefixDirsPsr4[$prefix] = $paths;
    256254        } elseif ($prepend) {
    257255            // Prepend directories for an already registered namespace.
    258256            $this->prefixDirsPsr4[$prefix] = array_merge(
    259                 (array) $paths,
     257                $paths,
    260258                $this->prefixDirsPsr4[$prefix]
    261259            );
     
    264262            $this->prefixDirsPsr4[$prefix] = array_merge(
    265263                $this->prefixDirsPsr4[$prefix],
    266                 (array) $paths
     264                $paths
    267265            );
    268266        }
     
    273271     * replacing any others previously set for this prefix.
    274272     *
    275      * @param string          $prefix The prefix
    276      * @param string[]|string $paths  The PSR-0 base directories
     273     * @param string              $prefix The prefix
     274     * @param list<string>|string $paths  The PSR-0 base directories
    277275     *
    278276     * @return void
     
    291289     * replacing any others previously set for this namespace.
    292290     *
    293      * @param string          $prefix The prefix/namespace, with trailing '\\'
    294      * @param string[]|string $paths  The PSR-4 base directories
     291     * @param string              $prefix The prefix/namespace, with trailing '\\'
     292     * @param list<string>|string $paths  The PSR-4 base directories
    295293     *
    296294     * @throws \InvalidArgumentException
     
    426424    {
    427425        if ($file = $this->findFile($class)) {
    428             includeFile($file);
     426            $includeFile = self::$includeFile;
     427            $includeFile($file);
    429428
    430429            return true;
     
    477476
    478477    /**
    479      * Returns the currently registered loaders indexed by their corresponding vendor directories.
    480      *
    481      * @return self[]
     478     * Returns the currently registered loaders keyed by their corresponding vendor directories.
     479     *
     480     * @return array<string, self>
    482481     */
    483482    public static function getRegisteredLoaders()
     
    556555        return false;
    557556    }
     557
     558    /**
     559     * @return void
     560     */
     561    private static function initializeIncludeClosure()
     562    {
     563        if (self::$includeFile !== null) {
     564            return;
     565        }
     566
     567        /**
     568         * Scope isolated include.
     569         *
     570         * Prevents access to $this/self from included files.
     571         *
     572         * @param  string $file
     573         * @return void
     574         */
     575        self::$includeFile = \Closure::bind(static function($file) {
     576            include $file;
     577        }, null, null);
     578    }
    558579}
    559 
    560 /**
    561  * Scope isolated include.
    562  *
    563  * Prevents access to $this/self from included files.
    564  *
    565  * @param  string $file
    566  * @return void
    567  * @private
    568  */
    569 function includeFile($file)
    570 {
    571     include $file;
    572 }
  • juvo-mail-editor/trunk/vendor/composer/InstalledVersions.php

    r2791814 r2981043  
    9999        foreach (self::getInstalled() as $installed) {
    100100            if (isset($installed['versions'][$packageName])) {
    101                 return $includeDevRequirements || empty($installed['versions'][$packageName]['dev_requirement']);
     101                return $includeDevRequirements || !isset($installed['versions'][$packageName]['dev_requirement']) || $installed['versions'][$packageName]['dev_requirement'] === false;
    102102            }
    103103        }
     
    120120    public static function satisfies(VersionParser $parser, $packageName, $constraint)
    121121    {
    122         $constraint = $parser->parseConstraints($constraint);
     122        $constraint = $parser->parseConstraints((string) $constraint);
    123123        $provided = $parser->parseConstraints(self::getVersionRanges($packageName));
    124124
     
    329329                    $installed[] = self::$installedByVendor[$vendorDir];
    330330                } elseif (is_file($vendorDir.'/composer/installed.php')) {
    331                     $installed[] = self::$installedByVendor[$vendorDir] = require $vendorDir.'/composer/installed.php';
     331                    /** @var array{root: array{name: string, pretty_version: string, version: string, reference: string|null, type: string, install_path: string, aliases: string[], dev: bool}, versions: array<string, array{pretty_version?: string, version?: string, reference?: string|null, type?: string, install_path?: string, aliases?: string[], dev_requirement: bool, replaced?: string[], provided?: string[]}>} $required */
     332                    $required = require $vendorDir.'/composer/installed.php';
     333                    $installed[] = self::$installedByVendor[$vendorDir] = $required;
    332334                    if (null === self::$installed && strtr($vendorDir.'/composer', '\\', '/') === strtr(__DIR__, '\\', '/')) {
    333335                        self::$installed = $installed[count($installed) - 1];
     
    341343            // and not from its source location in the composer/composer package, see https://github.com/composer/composer/issues/9937
    342344            if (substr(__DIR__, -8, 1) !== 'C') {
    343                 self::$installed = require __DIR__ . '/installed.php';
     345                /** @var array{root: array{name: string, pretty_version: string, version: string, reference: string|null, type: string, install_path: string, aliases: string[], dev: bool}, versions: array<string, array{pretty_version?: string, version?: string, reference?: string|null, type?: string, install_path?: string, aliases?: string[], dev_requirement: bool, replaced?: string[], provided?: string[]}>} $required */
     346                $required = require __DIR__ . '/installed.php';
     347                self::$installed = $required;
    344348            } else {
    345349                self::$installed = array();
    346350            }
    347351        }
    348         $installed[] = self::$installed;
     352
     353        if (self::$installed !== array()) {
     354            $installed[] = self::$installed;
     355        }
    349356
    350357        return $installed;
  • juvo-mail-editor/trunk/vendor/composer/autoload_real.php

    r2793158 r2981043  
    33// autoload_real.php @generated by Composer
    44
    5 class ComposerAutoloaderInit9c6548f6eba24e2705cd7acb45e71c62
     5class ComposerAutoloaderInitf48a6f250b401e6a6afc3e88e6ee63ed
    66{
    77    private static $loader;
     
    2323        }
    2424
    25         spl_autoload_register(array('ComposerAutoloaderInit9c6548f6eba24e2705cd7acb45e71c62', 'loadClassLoader'), true, true);
     25        spl_autoload_register(array('ComposerAutoloaderInitf48a6f250b401e6a6afc3e88e6ee63ed', 'loadClassLoader'), true, true);
    2626        self::$loader = $loader = new \Composer\Autoload\ClassLoader(\dirname(__DIR__));
    27         spl_autoload_unregister(array('ComposerAutoloaderInit9c6548f6eba24e2705cd7acb45e71c62', 'loadClassLoader'));
     27        spl_autoload_unregister(array('ComposerAutoloaderInitf48a6f250b401e6a6afc3e88e6ee63ed', 'loadClassLoader'));
    2828
    2929        require __DIR__ . '/autoload_static.php';
    30         call_user_func(\Composer\Autoload\ComposerStaticInit9c6548f6eba24e2705cd7acb45e71c62::getInitializer($loader));
     30        call_user_func(\Composer\Autoload\ComposerStaticInitf48a6f250b401e6a6afc3e88e6ee63ed::getInitializer($loader));
    3131
    3232        $loader->register(true);
    3333
    34         $includeFiles = \Composer\Autoload\ComposerStaticInit9c6548f6eba24e2705cd7acb45e71c62::$files;
    35         foreach ($includeFiles as $fileIdentifier => $file) {
    36             composerRequire9c6548f6eba24e2705cd7acb45e71c62($fileIdentifier, $file);
     34        $filesToLoad = \Composer\Autoload\ComposerStaticInitf48a6f250b401e6a6afc3e88e6ee63ed::$files;
     35        $requireFile = \Closure::bind(static function ($fileIdentifier, $file) {
     36            if (empty($GLOBALS['__composer_autoload_files'][$fileIdentifier])) {
     37                $GLOBALS['__composer_autoload_files'][$fileIdentifier] = true;
     38
     39                require $file;
     40            }
     41        }, null, null);
     42        foreach ($filesToLoad as $fileIdentifier => $file) {
     43            $requireFile($fileIdentifier, $file);
    3744        }
    3845
     
    4047    }
    4148}
    42 
    43 /**
    44  * @param string $fileIdentifier
    45  * @param string $file
    46  * @return void
    47  */
    48 function composerRequire9c6548f6eba24e2705cd7acb45e71c62($fileIdentifier, $file)
    49 {
    50     if (empty($GLOBALS['__composer_autoload_files'][$fileIdentifier])) {
    51         $GLOBALS['__composer_autoload_files'][$fileIdentifier] = true;
    52 
    53         require $file;
    54     }
    55 }
  • juvo-mail-editor/trunk/vendor/composer/autoload_static.php

    r2793158 r2981043  
    55namespace Composer\Autoload;
    66
    7 class ComposerStaticInit9c6548f6eba24e2705cd7acb45e71c62
     7class ComposerStaticInitf48a6f250b401e6a6afc3e88e6ee63ed
    88{
    99    public static $files = array (
     
    100100    {
    101101        return \Closure::bind(function () use ($loader) {
    102             $loader->prefixLengthsPsr4 = ComposerStaticInit9c6548f6eba24e2705cd7acb45e71c62::$prefixLengthsPsr4;
    103             $loader->prefixDirsPsr4 = ComposerStaticInit9c6548f6eba24e2705cd7acb45e71c62::$prefixDirsPsr4;
    104             $loader->fallbackDirsPsr4 = ComposerStaticInit9c6548f6eba24e2705cd7acb45e71c62::$fallbackDirsPsr4;
    105             $loader->prefixesPsr0 = ComposerStaticInit9c6548f6eba24e2705cd7acb45e71c62::$prefixesPsr0;
    106             $loader->classMap = ComposerStaticInit9c6548f6eba24e2705cd7acb45e71c62::$classMap;
     102            $loader->prefixLengthsPsr4 = ComposerStaticInitf48a6f250b401e6a6afc3e88e6ee63ed::$prefixLengthsPsr4;
     103            $loader->prefixDirsPsr4 = ComposerStaticInitf48a6f250b401e6a6afc3e88e6ee63ed::$prefixDirsPsr4;
     104            $loader->fallbackDirsPsr4 = ComposerStaticInitf48a6f250b401e6a6afc3e88e6ee63ed::$fallbackDirsPsr4;
     105            $loader->prefixesPsr0 = ComposerStaticInitf48a6f250b401e6a6afc3e88e6ee63ed::$prefixesPsr0;
     106            $loader->classMap = ComposerStaticInitf48a6f250b401e6a6afc3e88e6ee63ed::$classMap;
    107107
    108108        }, null, ClassLoader::class);
  • juvo-mail-editor/trunk/vendor/composer/installed.json

    r2793157 r2981043  
    276276        {
    277277            "name": "symfony/polyfill-ctype",
    278             "version": "v1.26.0",
    279             "version_normalized": "1.26.0.0",
     278            "version": "v1.28.0",
     279            "version_normalized": "1.28.0.0",
    280280            "source": {
    281281                "type": "git",
    282282                "url": "https://github.com/symfony/polyfill-ctype.git",
    283                 "reference": "6fd1b9a79f6e3cf65f9e679b23af304cd9e010d4"
    284             },
    285             "dist": {
    286                 "type": "zip",
    287                 "url": "https://api.github.com/repos/symfony/polyfill-ctype/zipball/6fd1b9a79f6e3cf65f9e679b23af304cd9e010d4",
    288                 "reference": "6fd1b9a79f6e3cf65f9e679b23af304cd9e010d4",
     283                "reference": "ea208ce43cbb04af6867b4fdddb1bdbf84cc28cb"
     284            },
     285            "dist": {
     286                "type": "zip",
     287                "url": "https://api.github.com/repos/symfony/polyfill-ctype/zipball/ea208ce43cbb04af6867b4fdddb1bdbf84cc28cb",
     288                "reference": "ea208ce43cbb04af6867b4fdddb1bdbf84cc28cb",
    289289                "shasum": ""
    290290            },
     
    298298                "ext-ctype": "For best performance"
    299299            },
    300             "time": "2022-05-24T11:49:31+00:00",
     300            "time": "2023-01-26T09:26:14+00:00",
    301301            "type": "library",
    302302            "extra": {
    303303                "branch-alias": {
    304                     "dev-main": "1.26-dev"
     304                    "dev-main": "1.28-dev"
    305305                },
    306306                "thanks": {
     
    341341            ],
    342342            "support": {
    343                 "source": "https://github.com/symfony/polyfill-ctype/tree/v1.26.0"
     343                "source": "https://github.com/symfony/polyfill-ctype/tree/v1.28.0"
    344344            },
    345345            "funding": [
     
    444444        {
    445445            "name": "symfony/polyfill-php72",
    446             "version": "v1.26.0",
    447             "version_normalized": "1.26.0.0",
     446            "version": "v1.28.0",
     447            "version_normalized": "1.28.0.0",
    448448            "source": {
    449449                "type": "git",
    450450                "url": "https://github.com/symfony/polyfill-php72.git",
    451                 "reference": "bf44a9fd41feaac72b074de600314a93e2ae78e2"
    452             },
    453             "dist": {
    454                 "type": "zip",
    455                 "url": "https://api.github.com/repos/symfony/polyfill-php72/zipball/bf44a9fd41feaac72b074de600314a93e2ae78e2",
    456                 "reference": "bf44a9fd41feaac72b074de600314a93e2ae78e2",
     451                "reference": "70f4aebd92afca2f865444d30a4d2151c13c3179"
     452            },
     453            "dist": {
     454                "type": "zip",
     455                "url": "https://api.github.com/repos/symfony/polyfill-php72/zipball/70f4aebd92afca2f865444d30a4d2151c13c3179",
     456                "reference": "70f4aebd92afca2f865444d30a4d2151c13c3179",
    457457                "shasum": ""
    458458            },
     
    460460                "php": ">=7.1"
    461461            },
    462             "time": "2022-05-24T11:49:31+00:00",
     462            "time": "2023-01-26T09:26:14+00:00",
    463463            "type": "library",
    464464            "extra": {
    465465                "branch-alias": {
    466                     "dev-main": "1.26-dev"
     466                    "dev-main": "1.28-dev"
    467467                },
    468468                "thanks": {
     
    503503            ],
    504504            "support": {
    505                 "source": "https://github.com/symfony/polyfill-php72/tree/v1.26.0"
     505                "source": "https://github.com/symfony/polyfill-php72/tree/v1.28.0"
    506506            },
    507507            "funding": [
     
    523523        {
    524524            "name": "timber/timber",
    525             "version": "1.20.0",
    526             "version_normalized": "1.20.0.0",
     525            "version": "1.22.1",
     526            "version_normalized": "1.22.1.0",
    527527            "source": {
    528528                "type": "git",
    529529                "url": "https://github.com/timber/timber.git",
    530                 "reference": "3ac8c7629656009b9e0d6d9e4ccda202aad3b8e0"
    531             },
    532             "dist": {
    533                 "type": "zip",
    534                 "url": "https://api.github.com/repos/timber/timber/zipball/3ac8c7629656009b9e0d6d9e4ccda202aad3b8e0",
    535                 "reference": "3ac8c7629656009b9e0d6d9e4ccda202aad3b8e0",
     530                "reference": "57fc582c42519f1b05fff5fb2ebf4291b5cd638f"
     531            },
     532            "dist": {
     533                "type": "zip",
     534                "url": "https://api.github.com/repos/timber/timber/zipball/57fc582c42519f1b05fff5fb2ebf4291b5cd638f",
     535                "reference": "57fc582c42519f1b05fff5fb2ebf4291b5cd638f",
    536536                "shasum": ""
    537537            },
    538538            "require": {
    539539                "composer/installers": "^1.0 || ^2.0",
    540                 "php": ">=5.3.0 || 7.*",
     540                "php": ">=7.2.5 || ^8.0",
    541541                "twig/cache-extension": "^1.5",
    542                 "twig/twig": "^1.41 || ^2.10",
    543                 "upstatement/routes": "0.9.*"
     542                "twig/twig": "^1.44.7 || ^2.10",
     543                "upstatement/routes": "^0.9"
    544544            },
    545545            "require-dev": {
    546                 "dealerdirect/phpcodesniffer-composer-installer": "^0.7.0",
    547                 "johnpbloch/wordpress": "*",
    548                 "phpunit/phpunit": "5.7.21 || 6.*",
    549                 "squizlabs/php_codesniffer": "3.*",
    550                 "wp-coding-standards/wpcs": "^2.0",
    551                 "wpackagist-plugin/advanced-custom-fields": "5.*",
    552                 "wpackagist-plugin/co-authors-plus": "3.2.* || 3.4.*",
    553                 "yoast/phpunit-polyfills": "^1.0"
     546                "wpackagist-plugin/advanced-custom-fields": "^5.0",
     547                "wpackagist-plugin/co-authors-plus": "^3.2 || ^3.4",
     548                "yoast/wp-test-utils": "^1.0"
    554549            },
    555550            "suggest": {
    556551                "satooshi/php-coveralls": "1.0.* for code coverage"
    557552            },
    558             "time": "2022-06-22T19:42:09+00:00",
     553            "time": "2022-11-24T03:42:29+00:00",
    559554            "type": "library",
    560555            "installation-source": "dist",
     
    672667        {
    673668            "name": "twig/twig",
    674             "version": "v2.15.3",
    675             "version_normalized": "2.15.3.0",
     669            "version": "v2.15.5",
     670            "version_normalized": "2.15.5.0",
    676671            "source": {
    677672                "type": "git",
    678673                "url": "https://github.com/twigphp/Twig.git",
    679                 "reference": "ab402673db8746cb3a4c46f3869d6253699f614a"
    680             },
    681             "dist": {
    682                 "type": "zip",
    683                 "url": "https://api.github.com/repos/twigphp/Twig/zipball/ab402673db8746cb3a4c46f3869d6253699f614a",
    684                 "reference": "ab402673db8746cb3a4c46f3869d6253699f614a",
     674                "reference": "fc02a6af3eeb97c4bf5650debc76c2eda85ac22e"
     675            },
     676            "dist": {
     677                "type": "zip",
     678                "url": "https://api.github.com/repos/twigphp/Twig/zipball/fc02a6af3eeb97c4bf5650debc76c2eda85ac22e",
     679                "reference": "fc02a6af3eeb97c4bf5650debc76c2eda85ac22e",
    685680                "shasum": ""
    686681            },
     
    695690                "symfony/phpunit-bridge": "^4.4.9|^5.0.9|^6.0"
    696691            },
    697             "time": "2022-09-28T08:40:08+00:00",
     692            "time": "2023-05-03T17:49:41+00:00",
    698693            "type": "library",
    699694            "extra": {
     
    739734            "support": {
    740735                "issues": "https://github.com/twigphp/Twig/issues",
    741                 "source": "https://github.com/twigphp/Twig/tree/v2.15.3"
     736                "source": "https://github.com/twigphp/Twig/tree/v2.15.5"
    742737            },
    743738            "funding": [
  • juvo-mail-editor/trunk/vendor/composer/installed.php

    r2793158 r2981043  
    22    'root' => array(
    33        'name' => 'juvo/mail-editor',
    4         'pretty_version' => '3.0.14',
    5         'version' => '3.0.14.0',
    6         'reference' => 'd2121200fa0f831478fcfc06bf91e4a5c0a22a00',
     4        'pretty_version' => '3.1.0',
     5        'version' => '3.1.0.0',
     6        'reference' => 'bb23356d74fe5d290e3a616e6e0967dede6bcd24',
    77        'type' => 'wordpress-plugin',
    88        'install_path' => __DIR__ . '/../../',
     
    3939        ),
    4040        'juvo/mail-editor' => array(
    41             'pretty_version' => '3.0.14',
    42             'version' => '3.0.14.0',
    43             'reference' => 'd2121200fa0f831478fcfc06bf91e4a5c0a22a00',
     41            'pretty_version' => '3.1.0',
     42            'version' => '3.1.0.0',
     43            'reference' => 'bb23356d74fe5d290e3a616e6e0967dede6bcd24',
    4444            'type' => 'wordpress-plugin',
    4545            'install_path' => __DIR__ . '/../../',
     
    4848        ),
    4949        'symfony/polyfill-ctype' => array(
    50             'pretty_version' => 'v1.26.0',
    51             'version' => '1.26.0.0',
    52             'reference' => '6fd1b9a79f6e3cf65f9e679b23af304cd9e010d4',
     50            'pretty_version' => 'v1.28.0',
     51            'version' => '1.28.0.0',
     52            'reference' => 'ea208ce43cbb04af6867b4fdddb1bdbf84cc28cb',
    5353            'type' => 'library',
    5454            'install_path' => __DIR__ . '/../symfony/polyfill-ctype',
     
    6666        ),
    6767        'symfony/polyfill-php72' => array(
    68             'pretty_version' => 'v1.26.0',
    69             'version' => '1.26.0.0',
    70             'reference' => 'bf44a9fd41feaac72b074de600314a93e2ae78e2',
     68            'pretty_version' => 'v1.28.0',
     69            'version' => '1.28.0.0',
     70            'reference' => '70f4aebd92afca2f865444d30a4d2151c13c3179',
    7171            'type' => 'library',
    7272            'install_path' => __DIR__ . '/../symfony/polyfill-php72',
     
    7575        ),
    7676        'timber/timber' => array(
    77             'pretty_version' => '1.20.0',
    78             'version' => '1.20.0.0',
    79             'reference' => '3ac8c7629656009b9e0d6d9e4ccda202aad3b8e0',
     77            'pretty_version' => '1.22.1',
     78            'version' => '1.22.1.0',
     79            'reference' => '57fc582c42519f1b05fff5fb2ebf4291b5cd638f',
    8080            'type' => 'library',
    8181            'install_path' => __DIR__ . '/../timber/timber',
     
    9393        ),
    9494        'twig/twig' => array(
    95             'pretty_version' => 'v2.15.3',
    96             'version' => '2.15.3.0',
    97             'reference' => 'ab402673db8746cb3a4c46f3869d6253699f614a',
     95            'pretty_version' => 'v2.15.5',
     96            'version' => '2.15.5.0',
     97            'reference' => 'fc02a6af3eeb97c4bf5650debc76c2eda85ac22e',
    9898            'type' => 'library',
    9999            'install_path' => __DIR__ . '/../twig/twig',
  • juvo-mail-editor/trunk/vendor/symfony/polyfill-ctype/LICENSE

    r2644151 r2981043  
    1 Copyright (c) 2018-2019 Fabien Potencier
     1Copyright (c) 2018-present Fabien Potencier
    22
    33Permission is hereby granted, free of charge, to any person obtaining a copy
  • juvo-mail-editor/trunk/vendor/symfony/polyfill-php72/LICENSE

    r2677983 r2981043  
    1 Copyright (c) 2015-2019 Fabien Potencier
     1Copyright (c) 2015-present Fabien Potencier
    22
    33Permission is hereby granted, free of charge, to any person obtaining a copy
  • juvo-mail-editor/trunk/vendor/symfony/polyfill-php72/Php72.php

    r2677983 r2981043  
    8484        ];
    8585
    86         return isset($map[\PHP_OS]) ? $map[\PHP_OS] : 'Unknown';
     86        return $map[\PHP_OS] ?? 'Unknown';
    8787    }
    8888
     
    9797
    9898        // On 32-bit systems, PHP_INT_SIZE is 4,
    99         return self::$hashMask ^ hexdec(substr($hash, 16 - (\PHP_INT_SIZE * 2 - 1), (\PHP_INT_SIZE * 2 - 1)));
     99        return self::$hashMask ^ hexdec(substr($hash, 16 - (\PHP_INT_SIZE * 2 - 1), \PHP_INT_SIZE * 2 - 1));
    100100    }
    101101
     
    168168        }
    169169
    170         self::$hashMask ^= hexdec(substr(spl_object_hash($obj), 16 - (\PHP_INT_SIZE * 2 - 1), (\PHP_INT_SIZE * 2 - 1)));
     170        self::$hashMask ^= hexdec(substr(spl_object_hash($obj), 16 - (\PHP_INT_SIZE * 2 - 1), \PHP_INT_SIZE * 2 - 1));
    171171    }
    172172
  • juvo-mail-editor/trunk/vendor/timber/timber/lib/Image.php

    r2644151 r2981043  
    438438     */
    439439    public function link() {
    440         if ( strlen($this->abs_url) ) {
     440        if (!empty($this->abs_url)) {
    441441            return $this->abs_url;
    442442        }
     
    484484     */
    485485    public function src( $size = 'full' ) {
    486         if ( isset($this->abs_url) ) {
     486        if (!empty($this->abs_url)) {
    487487            return $this->_maybe_secure_url($this->abs_url);
    488488        }
  • juvo-mail-editor/trunk/vendor/timber/timber/lib/Image/Operation/Letterbox.php

    r2793157 r2981043  
    6464            return false;
    6565        }
    66        
     66
    6767        $w = $this->w;
    6868        $h = $this->h;
     
    9393                $x = $w / 2 - $owt / 2;
    9494                $oht = $h;
    95                 $image->crop(0, 0, $ow, $oh, $owt, $oht);
     95                $image->crop(0, 0, round($ow), round($oh), round($owt), round($oht));
    9696            } else {
    9797                $w_scale = $w / $ow;
     
    100100                $y = $h / 2 - $oht / 2;
    101101                $owt = $w;
    102                 $image->crop(0, 0, $ow, $oh, $owt, $oht);
     102                $image->crop(0, 0, round($ow), round($oh), round($owt), round($oht));
    103103            }
    104104            $result = $image->save($save_filename);
     
    121121            }
    122122            $image = $func($save_filename);
    123             imagecopy($bg, $image, $x, $y, 0, 0, $owt, $oht);
     123            imagecopy($bg, $image, round($x), round($y), 0, 0, round($owt), round($oht));
    124124            if ( $save_func === 'imagegif' ) {
    125125                return $save_func($bg, $save_filename);
  • juvo-mail-editor/trunk/vendor/timber/timber/lib/Image/Operation/Resize.php

    r2793157 r2981043  
    7676        $crop  = self::get_target_sizes($editor);
    7777        foreach ( $image as $frame ) {
    78             $frame->cropImage($crop['src_w'], $crop['src_h'], $crop['x'], $crop['y']);
     78            $frame->cropImage(
     79                round($crop['src_w']),
     80                round($crop['src_h']),
     81                round($crop['x']),
     82                round($crop['y'])
     83            );
    7984            $frame->thumbnailImage($w, $h);
    8085            $frame->setImagePage($w, $h, 0, 0);
     
    189194
    190195            $crop = self::get_target_sizes($image);
    191             $image->crop(   $crop['x'],
    192                             $crop['y'],
    193                             $crop['src_w'],
    194                             $crop['src_h'],
    195                             $crop['target_w'],
    196                             $crop['target_h']
     196            $image->crop(
     197                round( $crop['x'] ),
     198                round( $crop['y'] ),
     199                round( $crop['src_w'] ),
     200                round( $crop['src_h'] ),
     201                round( $crop['target_w'] ),
     202                round( $crop['target_h'] )
    197203            );
    198204            $quality = apply_filters( 'wp_editor_set_quality', 82, 'image/jpeg');
  • juvo-mail-editor/trunk/vendor/timber/timber/lib/Image/Operation/Retina.php

    r2644151 r2981043  
    6363            $src_h = $current_size['height'];
    6464            // Get ratios
    65             $w = $src_w * $this->factor;
    66             $h = $src_h * $this->factor;
     65            $w = round( $src_w * $this->factor );
     66            $h = round( $src_h * $this->factor );
    6767            $image->crop(0, 0, $src_w, $src_h, $w, $h);
    6868            $result = $image->save($save_filename);
  • juvo-mail-editor/trunk/vendor/timber/timber/lib/Loader.php

    r2644151 r2981043  
    206206        $cache_mode = $this->_get_cache_mode($cache_mode);
    207207        if ( self::CACHE_TRANSIENT === $cache_mode || self::CACHE_SITE_TRANSIENT === $cache_mode ) {
    208             return self::clear_cache_timber_database();
     208            // $wpdb->query() might return 0 affected rows, but that means it’s still successful.
     209            return false !== self::clear_cache_timber_database();
    209210        } else if ( self::CACHE_OBJECT === $cache_mode && $object_cache ) {
    210             return self::clear_cache_timber_object();
     211            return false !== self::clear_cache_timber_object();
    211212        }
    212213        return false;
  • juvo-mail-editor/trunk/vendor/timber/timber/lib/PostsIterator.php

    r2644151 r2981043  
    99 */
    1010class PostsIterator extends \ArrayIterator {
    11    
     11
     12    #[\ReturnTypeWillChange]
    1213    public function current() {
    1314        global $post;
     
    1516        return $post;
    1617    }
    17    
     18
    1819}
  • juvo-mail-editor/trunk/vendor/timber/timber/lib/QueryIterator.php

    r2644151 r2981043  
    131131    //
    132132
    133     public function valid() {
     133    public function valid(): bool {
    134134        return $this->_query->have_posts();
    135135    }
    136136
     137    #[\ReturnTypeWillChange]
    137138    public function current() {
    138139        global $post;
     
    148149     * Don't implement next, because current already advances the loop
    149150     */
     151    #[\ReturnTypeWillChange]
    150152    final public function next() {}
    151153
     154    #[\ReturnTypeWillChange]
    152155    public function rewind() {
    153156        $this->_query->rewind_posts();
    154157    }
    155158
     159    #[\ReturnTypeWillChange]
    156160    public function key() {
    157161        $this->_query->current_post;
     
    200204     * The return value is cast to an integer.
    201205     */
    202     public function count() {
     206    public function count(): int {
    203207        return $this->post_count();
    204208    }
  • juvo-mail-editor/trunk/vendor/timber/timber/lib/Timber.php

    r2793157 r2981043  
    3636class Timber {
    3737
    38     public static $version = '1.20.0';
     38    public static $version = '1.22.1';
    3939    public static $locations;
    4040    public static $dirname = 'views';
  • juvo-mail-editor/trunk/vendor/timber/timber/phpunit-nocover.xml

    r2644151 r2981043  
    66    convertNoticesToExceptions="true"
    77    convertWarningsToExceptions="true"
    8     >
     8>
    99    <testsuites>
    10         <testsuite>
     10        <testsuite name="all">
    1111            <directory prefix="test-" suffix=".php">tests/</directory>
    1212        </testsuite>
     
    1414        as it includes a test that sets some const and would contaminate
    1515        the other tests as well. -->
    16         <testsuite>
     16        <testsuite name="all-but-last">
    1717            <directory prefix="testX-" suffix=".php">tests/</directory>
    1818        </testsuite>
  • juvo-mail-editor/trunk/vendor/timber/timber/readme.txt

    r2793157 r2981043  
    22Contributors: jarednova
    33Tags: template engine, templates, twig
    4 Requires at least: 4.9.8
    5 Tested up to: 5.9.3
    6 Stable tag: 1.20.0
    7 Requires PHP: 5.6
     4Tested up to: 6.1
     5Stable tag: 1.22.1
     6Requires PHP: 7.2.5
     7Requires at least: 5.3.0
    88License: GPLv2 or later
    99License URI: http://www.gnu.org/licenses/gpl-2.0.html
     
    3838
    3939**Fixes and improvements**
     40
     41= 1.22.1 =
     42
     43* Fixed a bug when Twig version 3 was accidentally installed when installing Timber through Composer, by @rmens in https://github.com/timber/timber/pull/2679.
     44
     45= 1.22.0 =
     46
     47* Fixed included Twig version. In the plugin version 1.21.0 of Timber, Twig version 2.15.3 was accidentally included instead of Twig version 1.44.7.
     48* Removed official support for PHP 8.1 in the plugin version. If you need to support PHP 8.1 in the future, please install [Timber through Composer](https://timber.github.io/docs/getting-started/setup/#via-github-for-developers) instead of installing Timber as a plugin. This will the only supported way of installing Timber when Timber version 2 will be released.
     49* Updated minimum required WordPress version to 5.3.
     50
     51= 1.21.0 =
     52
     53* Updated minimum required PHP version to 7.2 to make the included Twig version support PHP 8.0 and 8.1, by @gchtr in #2640.
     54* Updated minimum Twig version to 1.44.0 to support PHP 8.0 and 8.1, by @gchtr in #2640.
     55* Fixed support for PHP 8.0 and PHP 8.1, by @nlemoine and @gchtr in #2638, #2640.
    4056
    4157= 1.20.0 =
  • juvo-mail-editor/trunk/vendor/twig/twig/CHANGELOG

    r2793157 r2981043  
     1# 2.15.5 (2023-05-03)
     2
     3 * Make the Lexer initialize itself lazily
     4
     5# 2.15.4 (2022-12-27)
     6
     7 * Fix optimizing closures callbacks
     8 * Add a better exception when getting an undefined constant via `constant`
     9 * Fix `if` nodes when outside of a block and with an empty body
     10
    111# 2.15.3 (2022-09-28)
    212
  • juvo-mail-editor/trunk/vendor/twig/twig/LICENSE

    r2677983 r2981043  
    1 Copyright (c) 2009-2022 by the Twig Team.
     1Copyright (c) 2009-present by the Twig Team.
    22
    33All rights reserved.
  • juvo-mail-editor/trunk/vendor/twig/twig/src/Environment.php

    r2793157 r2981043  
    3939class Environment
    4040{
    41     public const VERSION = '2.15.3';
    42     public const VERSION_ID = 21503;
     41    public const VERSION = '2.15.5';
     42    public const VERSION_ID = 21505;
    4343    public const MAJOR_VERSION = 2;
    4444    public const MINOR_VERSION = 15;
    45     public const RELEASE_VERSION = 3;
     45    public const RELEASE_VERSION = 5;
    4646    public const EXTRA_VERSION = '';
    4747
  • juvo-mail-editor/trunk/vendor/twig/twig/src/Extension/CoreExtension.php

    r2677983 r2981043  
    13301330    }
    13311331
     1332    if (!\defined($constant)) {
     1333        throw new RuntimeError(sprintf('Constant "%s" is undefined.', $constant));
     1334    }
     1335
    13321336    return \constant($constant);
    13331337}
  • juvo-mail-editor/trunk/vendor/twig/twig/src/Lexer.php

    r2644151 r2981043  
    2222class Lexer
    2323{
     24    private $isInitialized = false;
     25
    2426    private $tokens;
    2527    private $code;
     
    6466            'interpolation' => ['#{', '}'],
    6567        ], $options);
     68    }
     69
     70    private function initialize()
     71    {
     72        if ($this->isInitialized) {
     73            return;
     74        }
     75
     76        $this->isInitialized = true;
    6677
    6778        // when PHP 7.3 is the min version, we will be able to remove the '#' part in preg_quote as it's part of the default
     
    156167    public function tokenize(Source $source)
    157168    {
     169        $this->initialize();
     170
    158171        $this->source = $source;
    159172        $this->code = str_replace(["\r\n", "\r"], "\n", $source->getCode());
  • juvo-mail-editor/trunk/vendor/twig/twig/src/Node/Expression/CallExpression.php

    r2793157 r2981043  
    305305            $callable = [$object, $r->name];
    306306            $callableName = (\function_exists('get_debug_type') ? get_debug_type($object) : \get_class($object)).'::'.$r->name;
    307         } elseif ($class = $r->getClosureScopeClass()) {
     307        } elseif (\PHP_VERSION_ID >= 80111 && $class = $r->getClosureCalledClass()) {
     308            $callableName = $class->name.'::'.$r->name;
     309        } elseif (\PHP_VERSION_ID < 80111 && $class = $r->getClosureScopeClass()) {
    308310            $callableName = (\is_array($callable) ? $callable[0] : $class->name).'::'.$r->name;
    309311        } else {
  • juvo-mail-editor/trunk/vendor/twig/twig/src/Node/IfNode.php

    r2644151 r2981043  
    5151                ->raw(") {\n")
    5252                ->indent()
    53                 ->subcompile($this->getNode('tests')->getNode($i + 1))
    5453            ;
     54            // The node might not exists if the content is empty
     55            if ($this->getNode('tests')->hasNode($i + 1)) {
     56                $compiler->subcompile($this->getNode('tests')->getNode($i + 1));
     57            }
    5558        }
    5659
Note: See TracChangeset for help on using the changeset viewer.