PluginProbe
Double Opt-In for Contact Form 7 – Secure, GDPR-Compliant Email Verification / 5.5.0
Double Opt-In for Contact Form 7 – Secure, GDPR-Compliant Email Verification v5.5.0
5.5.0 5.4.0 5.3.2 5.3.1 5.1.6 5.1.5 trunk 2.1.5 2.11 2.12 2.13 2.15 3.0.0 3.0.1 3.0.2 3.0.3 3.0.5 3.0.51 3.0.60 3.0.61 3.0.62 3.0.70 3.0.71 3.0.72 3.1.0 All 34 releases
double-opt-in / src / EmailTemplates / EmailTemplateRepository.php

EmailTemplateRepository.php in Double Opt-In for Contact Form 7 – Secure, GDPR-Compliant Email Verification 5.5.0, at src/EmailTemplates/EmailTemplateRepository.php

284 lines 7.2 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * Email Template Repository
4 *
5 * @package Forge12\DoubleOptIn\EmailTemplates
6 * @since 4.0.0
7 */
8
9 namespace Forge12\DoubleOptIn\EmailTemplates;
10
11 if ( ! defined( 'ABSPATH' ) ) {
12 exit;
13 }
14
15 /**
16 * Class EmailTemplateRepository
17 *
18 * Repository for Email Template CRUD operations.
19 */
20 class EmailTemplateRepository {
21
22 /**
23 * Find all templates.
24 *
25 * @param array $args Optional. Query arguments.
26 * @return array Array of template data.
27 */
28 public function findAll( array $args = array() ): array {
29 $defaults = array(
30 'post_type' => EmailTemplatePostType::POST_TYPE,
31 'post_status' => array( 'publish', 'draft' ),
32 'posts_per_page' => -1,
33 'orderby' => 'title',
34 'order' => 'ASC',
35 );
36
37 $query_args = wp_parse_args( $args, $defaults );
38 $posts = get_posts( $query_args );
39
40 return array_map( array( $this, 'formatTemplate' ), $posts );
41 }
42
43 /**
44 * Find template by ID.
45 *
46 * @param int $id Template ID.
47 * @return array|null Template data or null if not found.
48 */
49 public function findById( int $id ): ?array {
50 $post = get_post( $id );
51
52 if ( ! $post || $post->post_type !== EmailTemplatePostType::POST_TYPE ) {
53 return null;
54 }
55
56 return $this->formatTemplate( $post );
57 }
58
59 /**
60 * Debug info from last create operation.
61 *
62 * @var array
63 */
64 public array $lastCreateDebug = array();
65
66 /**
67 * Create a new template.
68 *
69 * @param array $data Template data.
70 * @return int|false Template ID on success, false on failure.
71 */
72 public function create( array $data ) {
73 $this->lastCreateDebug = array(
74 'input_blocks_json_length' => strlen( $data['blocks_json'] ?? '' ),
75 'input_blocks_json_preview' => substr( $data['blocks_json'] ?? '', 0, 200 ),
76 );
77
78 $post_data = array(
79 'post_type' => EmailTemplatePostType::POST_TYPE,
80 'post_title' => sanitize_text_field( $data['title'] ?? __( 'Untitled Template', 'double-opt-in' ) ),
81 'post_content' => wp_kses_post( $data['html'] ?? '' ),
82 'post_status' => sanitize_text_field( $data['status'] ?? 'draft' ),
83 );
84
85 $post_id = wp_insert_post( $post_data, true );
86
87 if ( is_wp_error( $post_id ) ) {
88 $this->lastCreateDebug['error'] = $post_id->get_error_message();
89 return false;
90 }
91
92 $this->lastCreateDebug['post_id'] = $post_id;
93
94 // Save meta data
95 $this->saveMeta( $post_id, $data );
96
97 // Verify what was saved
98 $savedBlocks = get_post_meta( $post_id, EmailTemplatePostType::META_BLOCKS_JSON, true );
99 $this->lastCreateDebug['saved_blocks_json_length'] = strlen( $savedBlocks );
100 $this->lastCreateDebug['saved_blocks_json_preview'] = substr( $savedBlocks, 0, 200 );
101
102 return $post_id;
103 }
104
105 /**
106 * Update an existing template.
107 *
108 * @param int $id Template ID.
109 * @param array $data Template data.
110 * @return bool True on success, false on failure.
111 */
112 public function update( int $id, array $data ): bool {
113 $post = get_post( $id );
114
115 if ( ! $post || $post->post_type !== EmailTemplatePostType::POST_TYPE ) {
116 return false;
117 }
118
119 $post_data = array(
120 'ID' => $id,
121 );
122
123 if ( isset( $data['title'] ) ) {
124 $post_data['post_title'] = sanitize_text_field( $data['title'] );
125 }
126
127 if ( isset( $data['html'] ) ) {
128 $post_data['post_content'] = wp_kses_post( $data['html'] );
129 }
130
131 if ( isset( $data['status'] ) ) {
132 $post_data['post_status'] = sanitize_text_field( $data['status'] );
133 }
134
135 $result = wp_update_post( $post_data, true );
136
137 if ( is_wp_error( $result ) ) {
138 return false;
139 }
140
141 // Save meta data
142 $this->saveMeta( $id, $data );
143
144 return true;
145 }
146
147 /**
148 * Delete a template.
149 *
150 * @param int $id Template ID.
151 * @param bool $force Optional. Whether to force delete (bypass trash). Default false.
152 * @return bool True on success, false on failure.
153 */
154 public function delete( int $id, bool $force = false ): bool {
155 $post = get_post( $id );
156
157 if ( ! $post || $post->post_type !== EmailTemplatePostType::POST_TYPE ) {
158 return false;
159 }
160
161 $result = wp_delete_post( $id, $force );
162
163 return $result !== false && $result !== null;
164 }
165
166 /**
167 * Duplicate a template.
168 *
169 * @param int $id Template ID to duplicate.
170 * @return int|false New template ID on success, false on failure.
171 */
172 public function duplicate( int $id ) {
173 $template = $this->findById( $id );
174
175 if ( ! $template ) {
176 return false;
177 }
178
179 $data = array(
180 'title' => sprintf( __( '%s (Copy)', 'double-opt-in' ), $template['title'] ),
181 'html' => $template['html'],
182 'status' => 'draft',
183 'blocks_json' => $template['blocks_json'],
184 'global_styles' => $template['global_styles'],
185 );
186
187 return $this->create( $data );
188 }
189
190 /**
191 * Count published templates.
192 *
193 * @return int Number of published templates.
194 */
195 public function countPublished(): int {
196 $query = new \WP_Query(
197 array(
198 'post_type' => EmailTemplatePostType::POST_TYPE,
199 'post_status' => 'publish',
200 'posts_per_page' => -1,
201 'fields' => 'ids',
202 )
203 );
204
205 return $query->found_posts;
206 }
207
208 /**
209 * Get templates for select dropdown.
210 *
211 * @return array Key-value pairs of template ID => title.
212 */
213 public function getForSelect(): array {
214 $templates = $this->findAll(
215 array(
216 'post_status' => 'publish',
217 )
218 );
219
220 $options = array();
221 foreach ( $templates as $template ) {
222 $options[ 'custom_' . $template['id'] ] = $template['title'];
223 }
224
225 return $options;
226 }
227
228 /**
229 * Save meta data for a template.
230 *
231 * @param int $id Template ID.
232 * @param array $data Template data.
233 * @return void
234 */
235 private function saveMeta( int $id, array $data ): void {
236 if ( isset( $data['blocks_json'] ) ) {
237 $json = is_string( $data['blocks_json'] )
238 ? $data['blocks_json']
239 : wp_json_encode( $data['blocks_json'] );
240
241 // WordPress requires slashing for update_post_meta
242 // See: https://developer.wordpress.org/reference/functions/update_post_meta/
243 $slashed_json = wp_slash( $json );
244
245 update_post_meta( $id, EmailTemplatePostType::META_BLOCKS_JSON, $slashed_json );
246 }
247
248 if ( isset( $data['global_styles'] ) ) {
249 $json = is_string( $data['global_styles'] )
250 ? $data['global_styles']
251 : wp_json_encode( $data['global_styles'] );
252 update_post_meta( $id, EmailTemplatePostType::META_GLOBAL_STYLES, $json );
253 }
254
255 if ( isset( $data['thumbnail'] ) ) {
256 update_post_meta( $id, EmailTemplatePostType::META_THUMBNAIL, sanitize_text_field( $data['thumbnail'] ) );
257 }
258 }
259
260 /**
261 * Format a post object into template data array.
262 *
263 * @param \WP_Post $post Post object.
264 * @return array Formatted template data.
265 */
266 private function formatTemplate( \WP_Post $post ): array {
267 $blocks_json = get_post_meta( $post->ID, EmailTemplatePostType::META_BLOCKS_JSON, true );
268 $global_styles = get_post_meta( $post->ID, EmailTemplatePostType::META_GLOBAL_STYLES, true );
269 $thumbnail = get_post_meta( $post->ID, EmailTemplatePostType::META_THUMBNAIL, true );
270
271 return array(
272 'id' => $post->ID,
273 'title' => $post->post_title,
274 'html' => $post->post_content,
275 'status' => $post->post_status,
276 'blocks_json' => $blocks_json ?: '[]',
277 'global_styles' => $global_styles ?: '{}',
278 'thumbnail' => $thumbnail ?: '',
279 'created_at' => $post->post_date,
280 'updated_at' => $post->post_modified,
281 );
282 }
283 }
284