/var/www/html_it/wp-content/plugins/woocommerce/src/Internal/EmailEditor/EmailApiController.php


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
<?php

declare( strict_types );

namespace 
Automattic\WooCommerce\Internal\EmailEditor;

use 
Automattic\WooCommerce\EmailEditor\Validator\Builder;
use 
Automattic\WooCommerce\Internal\EmailEditor\WCTransactionalEmails\WCTransactionalEmailPostsManager;
use 
WC_Email;
use 
WP_Error;

defined'ABSPATH' ) || exit;

/**
 * API Controller for managing WooCommerce email templates via extending the post type API.
 *
 * @internal
 */
class EmailApiController {
    
/**
     * A list of WooCommerce emails.
     *
     * @var \WC_Email[]
     */
    
private array $emails;

    
/**
     * The WooCommerce transactional email post manager.
     *
     * @var WCTransactionalEmailPostsManager|null
     */
    
private ?WCTransactionalEmailPostsManager $post_manager;

    
/**
     * Initialize the controller.
     *
     * @internal
     */
    
final public function init(): void {
        
$this->emails       WC()->mailer()->get_emails();
        
$this->post_manager WCTransactionalEmailPostsManager::get_instance();
    }

    
/**
     * Returns the data from wp_options table for the given post.
     *
     * @param array $post_data - Post data.
     * @return array - The email data.
     */
    
public function get_email_data$post_data ): array {
        
$email_type $this->post_manager->get_email_type_from_post_id$post_data['id'] );
        
$email      $this->get_email_by_type$email_type ?? '' );

        
// When the email type is not found, it means that the email type is not supported.
        
if ( ! $email ) {
            return array(
                
'subject'         => null,
                
'subject_full'    => null,
                
'subject_partial' => null,
                
'preheader'       => null,
                
'default_subject' => null,
                
'email_type'      => null,
                
'recipient'       => null,
                
'cc'              => null,
                
'bcc'             => null,
            );
        }

        
$form_fields $email->get_form_fields();
        
$enabled     $email->get_option'enabled' );
        return array(
            
'enabled'         => is_null$enabled ) ? $email->is_enabled() : 'yes' === $enabled,
            
'is_manual'       => $email->is_manual(),
            
'subject'         => $email->get_option'subject' ),
            
'subject_full'    => $email->get_option'subject_full' ), // For customer_refunded_order email type because it has two different subjects.
            
'subject_partial' => $email->get_option'subject_partial' ),
            
'preheader'       => $email->get_option'preheader' ),
            
'default_subject' => $email->get_default_subject(),
            
'email_type'      => $email_type,
            
// Recipient is possible to set only for the specific type of emails. When the field `recipient` is set in the form fields, it means that the email type has a recipient field.
            
'recipient'       => array_key_exists'recipient'$form_fields ) ? $email->get_option'recipient'get_option'admin_email' ) ) : null,
            
'cc'              => $email->get_option'cc' ),
            
'bcc'             => $email->get_option'bcc' ),
        );
    }

    
/**
     * Update WooCommerce specific option data by post name.
     *
     * @param array    $data - Data that are stored in the wp_options table.
     * @param \WP_Post $post - WP_Post object.
     * @return \WP_Error|null Returns WP_Error if email validation fails, null otherwise.
     */
    
public function save_email_data( array $data\WP_Post $post ): ?\WP_Error {
        
$error $this->validate_email_data$data );
        if ( 
is_wp_error$error ) ) {
            return new 
\WP_Error'invalid_email_data'implode' '$error->get_error_messages() ), array( 'status' => 400 ) );
        }

        if ( ! 
array_key_exists'subject'$data ) && ! array_key_exists'preheader'$data ) ) {
            return 
null;
        }
        
$email_type $this->post_manager->get_email_type_from_post_id$post->ID );
        
$email      $this->get_email_by_type$email_type ?? '' );

        if ( ! 
$email ) {
            return 
null// not saving of type wc_email. Allow process to continue.
        
}

        
// Handle customer_refunded_order email type because it has two different subjects.
        
if ( 'customer_refunded_order' === $email_type ) {
            if ( 
array_key_exists'subject_full'$data ) ) {
                
$email->update_option'subject_full'$data['subject_full'] );
            }
            if ( 
array_key_exists'subject_partial'$data ) ) {
                
$email->update_option'subject_partial'$data['subject_partial'] );
            }
        } elseif ( 
array_key_exists'subject'$data ) ) {
            
$email->update_option'subject'$data['subject'] );
        }

        if ( 
array_key_exists'preheader'$data ) ) {
            
$email->update_option'preheader'$data['preheader'] );
        }

        if ( 
array_key_exists'enabled'$data ) ) {
            
$email->update_option'enabled'$data['enabled'] ? 'yes' 'no' );
        }
        if ( 
array_key_exists'recipient'$data ) ) {
            
$email->update_option'recipient'$data['recipient'] );
        }
        if ( 
array_key_exists'cc'$data ) ) {
            
$email->update_option'cc'$data['cc'] );
        }
        if ( 
array_key_exists'bcc'$data ) ) {
            
$email->update_option'bcc'$data['bcc'] );
        }

        return 
null;
    }

    
/**
     * Validate the email data.
     *
     * @param array $data - The email data.
     * @return \WP_Error|null Returns WP_Error if email validation fails, null otherwise.
     */
    
private function validate_email_data( array $data ) {
        
$error = new \WP_Error();

        
// Validate 'recipient' email(s) field.
        
$invalid_recipients $this->filter_invalid_email_addresses$data['recipient'] ?? '' );
        if ( ! empty( 
$invalid_recipients ) ) {
            
$error_message sprintf(
                
// translators: %s will be replaced by comma-separated email addresses. For example, "[email protected],[email protected]".
                
__'One or more Recipient email addresses are invalid: “%s”. Please enter valid email addresses separated by commas.''woocommerce' ),
                
implode','$invalid_recipients )
            );
            
$error->add'invalid_recipient_email_address'$error_message );
        }

        
// Validate 'cc' email(s) field.
        
$invalid_cc $this->filter_invalid_email_addresses$data['cc'] ?? '' );
        if ( ! empty( 
$invalid_cc ) ) {
            
$error_message sprintf(
                
// translators: %s will be replaced by comma-separated email addresses. For example, "[email protected],[email protected]".
                
__'One or more CC email addresses are invalid: “%s”. Please enter valid email addresses separated by commas.''woocommerce' ),
                
implode','$invalid_cc )
            );
            
$error->add'invalid_cc_email_address'$error_message );
        }

        
// Validate 'bcc' email(s) field.
        
$invalid_bcc $this->filter_invalid_email_addresses$data['bcc'] ?? '' );
        if ( ! empty( 
$invalid_bcc ) ) {
            
$error_message sprintf(
                
// translators: %s will be replaced by comma-separated email addresses. For example, "[email protected],[email protected]".
                
__'One or more BCC email addresses are invalid: “%s”. Please enter valid email addresses separated by commas.''woocommerce' ),
                
implode','$invalid_bcc )
            );
            
$error->add'invalid_bcc_email_address'$error_message );
        }

        if ( 
$error->has_errors() ) {
            return 
$error;
        }

        return 
null;
    }

    
/**
     * Filter in invalid email addresses from a comma-separated string.
     *
     * @param string $comma_separated_email_addresses - A comma-separated string of email addresses.
     * @return array - An array of invalid email addresses.
     */
    
private function filter_invalid_email_addresses$comma_separated_email_addresses ) {
        
$invalid_email_addresses = array();

        if ( empty( 
trim$comma_separated_email_addresses ) ) ) {
            return 
$invalid_email_addresses;
        }

        foreach ( 
explode','$comma_separated_email_addresses ) as $email_address ) {
            if ( ! 
filter_vartrim$email_address ), FILTER_VALIDATE_EMAIL ) ) {
                
$invalid_email_addresses[] = trim$email_address );
            }
        }

        return 
$invalid_email_addresses;
    }

    
/**
     * Get the schema for the WooCommerce email post data.
     *
     * @return array
     */
    
public function get_email_data_schema(): array {
        return 
Builder::object(
            array(
                
'subject'         => Builder::string()->nullable(),
                
'subject_full'    => Builder::string()->nullable(), // For customer_refunded_order email type because it has two different subjects.
                
'subject_partial' => Builder::string()->nullable(),
                
'preheader'       => Builder::string()->nullable(),
                
'default_subject' => Builder::string()->nullable(),
                
'email_type'      => Builder::string()->nullable(),
                
'recipient'       => Builder::string()->nullable(),
                
'cc'              => Builder::string()->nullable(),
                
'bcc'             => Builder::string()->nullable(),
            )
        )->
to_array();
    }

    
/**
     * Get the email object by ID.
     *
     * @param string $id - The email ID.
     * @return \WC_Email|null - The email object or null if not found.
     */
    
private function get_email_by_type( ?string $id ): ?WC_Email {
        foreach ( 
$this->emails as $email ) {
            if ( 
$email->id === $id ) {
                return 
$email;
            }
        }
        return 
null;
    }
}