PluginProbe
YayMail – WooCommerce Email Customizer / 4.4.2
YayMail – WooCommerce Email Customizer v4.4.2
4.4.4 4.4.3 4.4.2 4.4.1 trunk 1.9.6 2.1.4 2.1.5 3.2.2 3.2.6 3.2.7.1 3.2.8.1 3.2.9 3.3 3.3.1 3.3.4 3.3.5 3.3.6 3.3.7 3.3.8 3.3.9 3.4 3.4.1 3.4.2 3.4.3 All 55 releases
yaymail / src / Models / LibraryTemplateModel.php

LibraryTemplateModel.php in YayMail – WooCommerce Email Customizer 4.4.2, at src/Models/LibraryTemplateModel.php

260 lines 8.5 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2
3 namespace YayMail\Models;
4
5 use YayMail\TemplateLibrary\LibraryTemplateSchema;
6 use YayMail\Utils\TemplateHelpers;
7
8 /**
9 * Persistence for user-saved Template Library presets.
10 */
11 class LibraryTemplateModel {
12
13 public const TABLE_NAME = 'yaymail_library_templates';
14
15 public const SAVED_ID_PREFIX = 'saved_';
16
17 /**
18 * Full table name including WP prefix.
19 *
20 * @return string
21 */
22 public static function get_table_name() {
23 global $wpdb;
24 return $wpdb->prefix . self::TABLE_NAME;
25 }
26
27 /**
28 * Insert one library template row.
29 *
30 * @param array $row Row data.
31 *
32 * @return string|false public_id on success, false on failure.
33 */
34 public static function create( $row ) {
35 self::ensure_table();
36
37 global $wpdb;
38
39 $sanitized = self::sanitize_row( $row );
40 $elements = json_decode( $sanitized['elements'], true );
41 if ( ! is_array( $elements ) || empty( $elements ) ) {
42 return false;
43 }
44
45 $public_id = ! empty( $sanitized['public_id'] ) ? $sanitized['public_id'] : wp_generate_uuid4();
46 $now = current_time( 'mysql', true );
47
48 // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery
49 $inserted = $wpdb->insert(
50 self::get_table_name(),
51 [
52 'public_id' => $public_id,
53 'email_type' => $sanitized['email_type'],
54 'name' => $sanitized['name'],
55 'description' => $sanitized['description'],
56 'elements' => $sanitized['elements'],
57 'email_settings' => $sanitized['email_settings'],
58 'global_header_settings' => $sanitized['global_header_settings'],
59 'global_footer_settings' => $sanitized['global_footer_settings'],
60 'position' => $sanitized['position'],
61 'created_by' => $sanitized['created_by'],
62 'created_at' => $now,
63 'updated_at' => $now,
64 ],
65 [
66 '%s',
67 '%s',
68 '%s',
69 '%s',
70 '%s',
71 '%s',
72 '%s',
73 '%s',
74 '%d',
75 '%d',
76 '%s',
77 '%s',
78 ]
79 );
80
81 if ( false === $inserted ) {
82 return false;
83 }
84
85 return $public_id;
86 }
87
88 /**
89 * Insert multiple rows in a transaction.
90 *
91 * @param array[] $rows Rows to insert.
92 *
93 * @return string[] public_ids created.
94 */
95 public static function create_many( $rows ) {
96 if ( empty( $rows ) ) {
97 return [];
98 }
99
100 global $wpdb;
101
102 $public_ids = [];
103 $wpdb->query( 'START TRANSACTION' );
104
105 try {
106 foreach ( $rows as $row ) {
107 $public_id = self::create( $row );
108 if ( false === $public_id ) {
109 throw new \RuntimeException( 'Failed to insert library template row.' );
110 }
111 $public_ids[] = $public_id;
112 }
113 $wpdb->query( 'COMMIT' );
114 } catch ( \Exception $e ) {
115 $wpdb->query( 'ROLLBACK' );
116 return [];
117 }
118
119 return $public_ids;
120 }
121
122 /**
123 * List saved templates for email type (language-agnostic).
124 *
125 * @param string $email_type Email type slug.
126 *
127 * @return array[]
128 */
129 public static function list_by_email_type( $email_type ) {
130 return array();
131 }
132
133 /**
134 * Hard-delete a row by public_id.
135 *
136 * @param string $public_id UUID.
137 *
138 * @return bool
139 */
140 public static function delete_by_public_id( $public_id ) {
141 self::ensure_table();
142
143 global $wpdb;
144
145 $public_id = sanitize_text_field( $public_id );
146 if ( '' === $public_id ) {
147 return false;
148 }
149
150 // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching
151 $deleted = $wpdb->delete(
152 self::get_table_name(),
153 [ 'public_id' => $public_id ],
154 [ '%s' ]
155 );
156
157 return false !== $deleted && $deleted > 0;
158 }
159
160 /**
161 * Map DB row to Template Library API summary shape.
162 *
163 * @param array $row Database row.
164 *
165 * @return array
166 */
167 public static function to_library_summary( $row ) {
168 $elements = json_decode( $row['elements'] ?? '[]', true );
169 $email_settings = json_decode( $row['email_settings'] ?? '{}', true );
170
171 if ( ! is_array( $elements ) ) {
172 $elements = [];
173 }
174 if ( ! is_array( $email_settings ) ) {
175 $email_settings = [];
176 }
177
178 return [
179 'id' => self::SAVED_ID_PREFIX . ( $row['public_id'] ?? '' ),
180 'email_type' => $row['email_type'] ?? '',
181 'name' => $row['name'] ?? '',
182 'description' => $row['description'] ?? '',
183 'elements' => $elements,
184 'email_settings' => $email_settings,
185 'position' => isset( $row['position'] ) ? (int) $row['position'] : 100,
186 'available' => true,
187 'access' => 'free',
188 'source' => 'saved',
189 ];
190 }
191
192 /**
193 * Build sanitized row from REST save payload.
194 *
195 * @param array $payload Request payload fields.
196 *
197 * @return array
198 */
199 public static function build_row_from_save_payload( $payload ) {
200 $elements = isset( $payload['elements'] ) && is_array( $payload['elements'] )
201 ? TemplateHelpers::sanitize_elements_recursive( $payload['elements'] )
202 : [];
203
204 $email_settings = isset( $payload['email_settings'] ) && is_array( $payload['email_settings'] )
205 ? $payload['email_settings']
206 : [];
207
208 $global_header = isset( $payload['global_header_settings'] ) && is_array( $payload['global_header_settings'] )
209 ? $payload['global_header_settings']
210 : null;
211
212 $global_footer = isset( $payload['global_footer_settings'] ) && is_array( $payload['global_footer_settings'] )
213 ? $payload['global_footer_settings']
214 : null;
215
216 return [
217 'email_type' => sanitize_text_field( $payload['email_type'] ?? '' ),
218 'name' => sanitize_text_field( $payload['name'] ?? '' ),
219 'description' => '',
220 'elements' => wp_json_encode( $elements ),
221 'email_settings' => wp_json_encode( $email_settings ),
222 'global_header_settings' => null !== $global_header ? wp_json_encode( $global_header ) : null,
223 'global_footer_settings' => null !== $global_footer ? wp_json_encode( $global_footer ) : null,
224 'position' => 100,
225 'created_by' => get_current_user_id(),
226 ];
227 }
228
229 /**
230 * @param array $row Raw row before insert.
231 *
232 * @return array
233 */
234 private static function sanitize_row( $row ) {
235 $elements = isset( $row['elements'] ) ? $row['elements'] : '[]';
236 if ( is_array( $elements ) ) {
237 $elements = wp_json_encode( TemplateHelpers::sanitize_elements_recursive( $elements ) );
238 }
239
240 return [
241 'public_id' => isset( $row['public_id'] ) ? sanitize_text_field( $row['public_id'] ) : '',
242 'email_type' => sanitize_text_field( $row['email_type'] ?? '' ),
243 'name' => sanitize_text_field( $row['name'] ?? '' ),
244 'description' => sanitize_text_field( $row['description'] ?? '' ),
245 'elements' => $elements,
246 'email_settings' => is_string( $row['email_settings'] ?? '' ) ? $row['email_settings'] : wp_json_encode( [] ),
247 'global_header_settings' => $row['global_header_settings'] ?? null,
248 'global_footer_settings' => $row['global_footer_settings'] ?? null,
249 'position' => isset( $row['position'] ) ? (int) $row['position'] : 100,
250 'created_by' => isset( $row['created_by'] ) ? (int) $row['created_by'] : get_current_user_id(),
251 ];
252 }
253
254 /**
255 * @return void
256 */
257 private static function ensure_table() {
258 LibraryTemplateSchema::maybe_create_table();
259 }
260 }