PluginProbe
Woody Code Snippets – Insert PHP, CSS, JS, and Header/Footer Scripts / 2.2.7
Woody Code Snippets – Insert PHP, CSS, JS, and Header/Footer Scripts v2.2.7
2.7.7 2.7.6 2.7.5 2.7.4 trunk 1.3 2.0.4 2.0.6 2.1.91 2.2.4 2.2.7 2.2.9 2.3.1 2.3.10 2.4.10 2.4.2 2.4.4 2.4.5 2.4.6 2.4.7 2.4.8 2.4.9 2.6.0 2.6.1 2.7.0 All 28 releases
← All changes | admin/includes/class.import.snippet.php +217 -364 2.7.42.2.7 View file →
@@ -1,364 +1,217 @@
1 -<?php
2 -
3 -/**
4 - * Import snippet
5 - *
6 - * @package Woody_Code_Snippets
7 - */
8 -
9 -// Exit if accessed directly
10 -if ( ! defined( 'ABSPATH' ) ) {
11 - exit;
12 -}
13 -
14 -class WINP_Import_Snippet {
15 -
16 - /**
17 - * Process import files and return results
18 - *
19 - * @param array<array<string, mixed>>|array<string, mixed> $files Array of files from $_FILES or REST API.
20 - * @param string $dup_action Duplicate action: 'ignore', 'replace', or 'skip'.
21 - *
22 - * @return array<string, mixed> Array with 'count', 'error', and 'errors' keys
23 - */
24 - public function process_import_files( $files, $dup_action = 'ignore' ) {
25 - $count = 0;
26 - $error = false;
27 - $errors = [];
28 -
29 - // Sanitize duplicate action.
30 - $dup_action = sanitize_text_field( $dup_action );
31 - if ( ! in_array( $dup_action, [ 'ignore', 'replace', 'skip' ], true ) ) {
32 - $dup_action = 'ignore';
33 - }
34 -
35 - // Normalize file array structure.
36 - $normalized_files = [];
37 - if ( isset( $files['tmp_name'] ) ) {
38 - // Handle both single file and multiple files format.
39 - $file_count = count( $files['tmp_name'] );
40 - for ( $i = 0; $i < $file_count; $i++ ) {
41 - $normalized_files[] = [
42 - 'name' => isset( $files['name'][ $i ] ) ? sanitize_file_name( $files['name'][ $i ] ) : '',
43 - 'type' => isset( $files['type'][ $i ] ) ? sanitize_text_field( $files['type'][ $i ] ) : '',
44 - 'tmp_name' => isset( $files['tmp_name'][ $i ] ) ? $files['tmp_name'][ $i ] : '',
45 - 'error' => isset( $files['error'][ $i ] ) ? (int) $files['error'][ $i ] : UPLOAD_ERR_NO_FILE,
46 - 'size' => isset( $files['size'][ $i ] ) ? (int) $files['size'][ $i ] : 0,
47 - ];
48 - }
49 - } else {
50 - // Already in correct format (from REST API) - still need to sanitize.
51 - foreach ( $files as $file ) {
52 - $normalized_files[] = [
53 - 'name' => isset( $file['name'] ) ? sanitize_file_name( $file['name'] ) : '',
54 - 'type' => isset( $file['type'] ) ? sanitize_text_field( $file['type'] ) : '',
55 - 'tmp_name' => isset( $file['tmp_name'] ) ? $file['tmp_name'] : '',
56 - 'error' => isset( $file['error'] ) ? (int) $file['error'] : UPLOAD_ERR_NO_FILE,
57 - 'size' => isset( $file['size'] ) ? (int) $file['size'] : 0,
58 - ];
59 - }
60 - }
61 -
62 - foreach ( $normalized_files as $file ) {
63 - // Validate tmp_name path.
64 - if ( empty( $file['tmp_name'] ) || ! file_exists( $file['tmp_name'] ) ) {
65 - $error = true;
66 - // translators: %s is the file name.
67 - $errors[] = sprintf( __( 'Invalid or missing temporary file for: %s', 'insert-php' ), $file['name'] );
68 - continue;
69 - }
70 -
71 - $ext = pathinfo( $file['name'], PATHINFO_EXTENSION );
72 - $ext = strtolower( sanitize_text_field( $ext ) );
73 - $mime_type = $file['type'];
74 - $import_file = $file['tmp_name'];
75 -
76 - if ( 'json' === $ext || 'application/json' === $mime_type ) {
77 - $result = $this->import_snippet( $import_file, $dup_action );
78 - } elseif ( 'zip' === $ext || 'application/zip' === $mime_type ) {
79 - $result = $this->import_zip_snippets( $import_file, $dup_action );
80 - } else {
81 - $result = apply_filters( 'wbcr/inp/import/snippet', false, $ext, $mime_type, $import_file, $dup_action );
82 - }
83 -
84 - if ( false === $result || - 1 === $result ) {
85 - $error = true;
86 - // translators: %s is the file name.
87 - $errors[] = sprintf( __( 'Failed to import file: %s', 'insert-php' ), $file['name'] );
88 - } else {
89 - $count += count( $result );
90 - }
91 - }
92 -
93 - return [
94 - 'count' => $count,
95 - 'error' => $error,
96 - 'errors' => $errors,
97 - ];
98 - }
99 -
100 - /**
101 - * Import snippets
102 - *
103 - * @param string $file File path.
104 - * @param string $dup_action Duplicate action: 'ignore', 'replace', or 'skip'.
105 - *
106 - * @return int|bool|array<int>
107 - */
108 - public function import_snippet( $file, $dup_action ) {
109 - if ( ! file_exists( $file ) || ! is_file( $file ) ) {
110 - return false;
111 - }
112 -
113 - $raw_data = file_get_contents( $file );
114 - $data = json_decode( $raw_data, true );
115 - $snippets = isset( $data['snippets'] ) ? $data['snippets'] : [];
116 -
117 - $imported = $this->save_imported_snippets( $snippets, $dup_action );
118 -
119 - return $imported;
120 - }
121 -
122 - /**
123 - * Import snippets from ZIP archive
124 - *
125 - * @param string $file File path.
126 - * @param string $dup_action Duplicate action: 'ignore', 'replace', or 'skip'.
127 - *
128 - * @return int|bool|array<int>
129 - */
130 - public function import_zip_snippets( $file, $dup_action ) {
131 - if ( ! class_exists( 'ZipArchive' ) ) {
132 - return false;
133 - }
134 -
135 - $zip = new ZipArchive();
136 -
137 - if ( true !== $zip->open( $file ) ) {
138 - return false;
139 - }
140 -
141 - $result = [];
142 - $upload_dir = wp_get_upload_dir();
143 - // Use unique directory name to prevent race conditions.
144 - $unzip_path = $upload_dir['path'] . '/winp_' . uniqid();
145 -
146 - // Create extraction directory.
147 - if ( ! wp_mkdir_p( $unzip_path ) ) {
148 - $zip->close();
149 - return false;
150 - }
151 -
152 - // Validate and extract only safe files.
153 - for ( $i = 0; $i < $zip->numFiles; $i++ ) { // phpcs:ignore WordPress.NamingConventions.ValidVariableName.UsedPropertyNotSnakeCase
154 - $filename = $zip->getNameIndex( $i );
155 -
156 - // Skip if filename cannot be retrieved.
157 - if ( false === $filename ) {
158 - continue;
159 - }
160 -
161 - // Security: Skip files with directory traversal attempts.
162 - if ( false !== strpos( $filename, '..' ) || false !== strpos( $filename, '/' ) || false !== strpos( $filename, '\\' ) ) {
163 - continue;
164 - }
165 -
166 - // Only extract files (not directories).
167 - $file_info = $zip->statIndex( $i );
168 - if ( ! empty( $file_info ) && 0 === $file_info['size'] ) {
169 - continue;
170 - }
171 -
172 - $zip->extractTo( $unzip_path, $filename );
173 - }
174 -
175 - $zip->close();
176 -
177 - // Process extracted files using modern iterator.
178 - try {
179 - $iterator = new DirectoryIterator( $unzip_path );
180 - foreach ( $iterator as $file_info ) {
181 - if ( $file_info->isFile() && $file_info->getSize() > 0 ) {
182 - $filepath = $file_info->getPathname();
183 - $_result = $this->import_snippet( $filepath, $dup_action );
184 - if ( is_array( $_result ) ) {
185 - $result = array_merge( $result, $_result );
186 - }
187 - }
188 - }
189 - } catch ( Exception $e ) {
190 - $this->cleanup_directory( $unzip_path );
191 - return false;
192 - }
193 -
194 - // Cleanup: Delete all files and directory.
195 - $this->cleanup_directory( $unzip_path );
196 -
197 - return $result;
198 - }
199 -
200 - /**
201 - * Cleanup directory and its contents
202 - *
203 - * @param string $dir_path Directory path.
204 - *
205 - * @return void
206 - */
207 - private function cleanup_directory( $dir_path ) {
208 - if ( ! is_dir( $dir_path ) ) {
209 - return;
210 - }
211 -
212 - try {
213 - $iterator = new DirectoryIterator( $dir_path );
214 - foreach ( $iterator as $file_info ) {
215 - if ( $file_info->isFile() ) {
216 - wp_delete_file( $file_info->getPathname() );
217 - }
218 - }
219 - } catch ( Exception $e ) {
220 - return;
221 - }
222 -
223 - $wp_filesystem = WINP_Helper::get_wp_filesystem();
224 -
225 - if ( false !== $wp_filesystem ) {
226 - $wp_filesystem->rmdir( $dir_path, true );
227 - }
228 - }
229 -
230 - /**
231 - * Update taxonomy tags
232 - *
233 - * @param int $snippet_id Snippet ID.
234 - * @param array<string> $tags Tags slugs.
235 - *
236 - * @return void
237 - */
238 - private function update_taxonomy_tags( $snippet_id, $tags ) {
239 - if ( ! empty( $tags ) ) {
240 - foreach ( $tags as $tag_slug ) {
241 - $term = get_term_by( 'slug', $tag_slug, WINP_SNIPPETS_TAXONOMY );
242 - if ( $term ) {
243 - wp_set_post_terms( $snippet_id, [ $term->term_id ], WINP_SNIPPETS_TAXONOMY, true );
244 - }
245 - }
246 - }
247 - }
248 -
249 - /**
250 - * Update post meta
251 - *
252 - * @param int $post_id Post ID.
253 - * @param string $meta_name Meta name.
254 - * @param mixed $meta_value Meta value.
255 - *
256 - * @return void
257 - */
258 - private function update_meta( $post_id, $meta_name, $meta_value ) {
259 - update_post_meta( $post_id, 'wbcr_inp_' . $meta_name, $meta_value );
260 - }
261 -
262 - /**
263 - * Save snippet
264 - *
265 - * @param array<string, mixed> $snippet Snippet data.
266 - *
267 - * @return int
268 - */
269 - private function save_snippet( $snippet ) {
270 - $content = $snippet['content'];
271 -
272 - if ( WINP_SNIPPET_TYPE_TEXT != $snippet['type'] && WINP_SNIPPET_TYPE_AD != $snippet['type'] ) {
273 - $content = empty( $content ) && isset( $snippet['code'] ) && ! empty( $snippet['code'] ) ? $snippet['code'] : $content;
274 - }
275 -
276 - $data = [
277 - 'post_title' => $snippet['title'],
278 - 'post_content' => $content,
279 - 'post_status' => 'publish',
280 - 'post_type' => WINP_SNIPPETS_POST_TYPE,
281 - ];
282 -
283 - if ( isset( $snippet['id'] ) && 0 != $snippet['id'] ) {
284 - $data['ID'] = $snippet['id'];
285 - }
286 -
287 - $snippet['id'] = wp_insert_post( $data );
288 -
289 - $this->update_meta( $snippet['id'], 'snippet_location', $snippet['location'] );
290 - $this->update_meta( $snippet['id'], 'snippet_type', $snippet['type'] );
291 - $this->update_meta( $snippet['id'], 'snippet_filters', $snippet['filters'] );
292 - $this->update_meta( $snippet['id'], 'changed_filters', $snippet['changed_filters'] );
293 - $this->update_meta( $snippet['id'], 'snippet_scope', $snippet['scope'] );
294 - $this->update_meta( $snippet['id'], 'snippet_description', $snippet['description'] );
295 - $this->update_meta( $snippet['id'], 'snippet_tags', $snippet['attributes'] );
296 - $this->update_meta( $snippet['id'], 'snippet_activate', 0 );
297 - $this->update_meta( $snippet['id'], 'snippet_priority', $snippet['priority'] );
298 - $this->update_meta( $snippet['id'], 'snippet_custom_name', $snippet['custom_name'] );
299 -
300 - $this->update_taxonomy_tags( $snippet['id'], $snippet['tags'] );
301 -
302 - return $snippet['id'];
303 - }
304 -
305 - /**
306 - * Save imported snippets
307 - *
308 - * @param array<array<string, mixed>> $snippets Snippets data.
309 - * @param string $dup_action Duplicate action: 'ignore', 'replace', or 'skip'.
310 - *
311 - * @return array<int> Imported snippet IDs.
312 - */
313 - private function save_imported_snippets( $snippets, $dup_action ) {
314 - $existing_snippets = [];
315 -
316 - if ( 'replace' === $dup_action || 'skip' === $dup_action ) {
317 - $all_snippets = get_posts(
318 - [
319 - 'post_type' => WINP_SNIPPETS_POST_TYPE,
320 - 'posts_per_page' => -1,
321 - 'post_status' => 'any',
322 - ]
323 - );
324 -
325 - foreach ( $all_snippets as $snippet ) {
326 - // Store by both post_name (slug) and post_title for matching.
327 - $existing_snippets[ $snippet->post_name ] = $snippet->ID;
328 - $existing_snippets[ $snippet->post_title ] = $snippet->ID;
329 - }
330 - }
331 -
332 - $imported = [];
333 -
334 - foreach ( $snippets as $snippet ) {
335 - $is_duplicate = false;
336 - $duplicate_id = null;
337 -
338 - if ( 'ignore' !== $dup_action ) {
339 - if ( isset( $snippet['name'] ) && isset( $existing_snippets[ $snippet['name'] ] ) ) {
340 - $is_duplicate = true;
341 - $duplicate_id = $existing_snippets[ $snippet['name'] ];
342 - } elseif ( isset( $snippet['title'] ) && isset( $existing_snippets[ $snippet['title'] ] ) ) {
343 - $is_duplicate = true;
344 - $duplicate_id = $existing_snippets[ $snippet['title'] ];
345 - }
346 -
347 - if ( $is_duplicate ) {
348 - if ( 'replace' === $dup_action ) {
349 - $snippet['id'] = $duplicate_id;
350 - } elseif ( 'skip' === $dup_action ) {
351 - continue;
352 - }
353 - }
354 - }
355 -
356 - $snippet_id = $this->save_snippet( $snippet );
357 - if ( $snippet_id ) {
358 - $imported[] = $snippet_id;
359 - }
360 - }
361 -
362 - return $imported;
363 - }
364 -}
1 +<?php
2 +
3 +/**
4 + * Import snippet
5 + *
6 + * @author Webcraftic <wordpress.webraftic@gmail.com>
7 + * @copyright (c) 16.11.2018, Webcraftic
8 + * @version 1.0
9 + */
10 +
11 +// Exit if accessed directly
12 +if ( ! defined( 'ABSPATH' ) ) {
13 + exit;
14 +}
15 +
16 +class WINP_Import_Snippet {
17 +
18 + /**
19 + * WINP_Export_Snippet constructor.
20 + */
21 + public function __construct() {
22 + $this->registerHooks();
23 + }
24 +
25 + /**
26 + * Register hooks
27 + */
28 + public function registerHooks() {
29 + add_action( 'admin_init', [ $this, 'import_snippets_proccess' ] );
30 + }
31 +
32 + /**
33 + * Process the uploaded import files
34 + *
35 + * @uses import_snippets() to process the import file
36 + * @uses wp_redirect() to pass the import results to the page
37 + * @uses add_query_arg() to append the results to the current URI
38 + */
39 + public function import_snippets_proccess() {
40 + if ( isset( $_POST['wbcr_inp_import_form_saved'] ) ) {
41 +
42 + if ( ! WINP_Plugin::app()->currentUserCan() ) {
43 + wp_die( __( 'Sorry, you are not allowed to import snippets as this user.' ), __( 'You need a higher level of permission.' ), 403 );
44 + }
45 +
46 + check_admin_referer( 'wbcr_inp_import_form', 'wbcr_inp_import_form_nonce_field' );
47 +
48 + if ( ! isset( $_FILES['wbcr_inp_import_files'] ) || ! count( $_FILES['wbcr_inp_import_files'] ) || ! isset( $_FILES['wbcr_inp_import_files']['tmp_name'][0] ) || empty( $_FILES['wbcr_inp_import_files']['tmp_name'][0] ) ) {
49 + return;
50 + }
51 +
52 + $url = remove_query_arg( [ 'wbcr_inp_error', 'wbcr_inp_imported' ] );
53 +
54 + // Only ine files for free version
55 + if ( ! WINP_Plugin::app()->get_api_object()->is_key() && count( $_FILES['wbcr_inp_import_files']['tmp_name'] ) > 1 ) {
56 + $url = add_query_arg( [ 'wbcr_import_error' => true ], $url );
57 + wp_redirect( esc_url_raw( $url ) );
58 + exit;
59 + }
60 +
61 + $count = 0;
62 + $uploads = $_FILES['wbcr_inp_import_files'];
63 + $dup_action = WINP_Plugin::app()->request->post( 'duplicate_action', 'ignore', true );
64 + $error = false;
65 +
66 + foreach ( $uploads['tmp_name'] as $i => $import_file ) {
67 + $ext = pathinfo( $uploads['name'][ $i ] );
68 + $ext = $ext['extension'];
69 + $mime_type = $uploads['type'][ $i ];
70 +
71 + if ( 'json' === $ext || 'application/json' === $mime_type ) {
72 + $result = $this->importSnippet( $import_file, $dup_action );
73 + } else {
74 + $result = apply_filters( 'wbcr/inp/import/snippet', false, $ext, $mime_type, $import_file, $dup_action );
75 + }
76 +
77 + if ( false === $result || - 1 === $result ) {
78 + $error = true;
79 + } else {
80 + $count += count( $result );
81 + }
82 + }
83 +
84 + $url = add_query_arg( $error ? [ 'wbcr_inp_error' => true ] : [ 'wbcr_inp_imported' => $count ], $url );
85 + wp_redirect( esc_url_raw( $url ) );
86 + exit;
87 + }
88 + }
89 +
90 + /**
91 + * Import snippets
92 + *
93 + * @param $file
94 + * @param $dup_action
95 + *
96 + * @return int|bool|array
97 + */
98 + private function importSnippet( $file, $dup_action ) {
99 + if ( ! file_exists( $file ) || ! is_file( $file ) ) {
100 + return false;
101 + }
102 +
103 + $raw_data = file_get_contents( $file );
104 + $data = json_decode( $raw_data, true );
105 + $snippets = isset( $data['snippets'] ) ? $data['snippets'] : [];
106 +
107 + $imported = $this->saveImportedSnippets( $snippets, $dup_action );
108 +
109 + return $imported;
110 + }
111 +
112 + /**
113 + * Update taxonomy tags
114 + *
115 + * @param $snippet_id
116 + * @param $tags
117 + */
118 + private function updateTaxonomyTags( $snippet_id, $tags ) {
119 + if ( ! empty( $tags ) ) {
120 + foreach ( $tags as $tag_slug ) {
121 + $term = get_term_by( 'slug', $tag_slug, WINP_SNIPPETS_TAXONOMY );
122 + if ( $term ) {
123 + wp_set_post_terms( $snippet_id, [ $term->term_id ], WINP_SNIPPETS_TAXONOMY, true );
124 + }
125 + }
126 + }
127 + }
128 +
129 + /**
130 + * Update post meta
131 + *
132 + * @param $post_id
133 + * @param $meta_name
134 + * @param $meta_value
135 + */
136 + private function updateMeta( $post_id, $meta_name, $meta_value ) {
137 + update_post_meta( $post_id, WINP_Plugin::app()->getPrefix() . $meta_name, $meta_value );
138 + }
139 +
140 + /**
141 + * Save snippet
142 + *
143 + * @param $snippet
144 + *
145 + * @return int
146 + */
147 + private function saveSnippet( $snippet ) {
148 + $content = $snippet['content'];
149 +
150 + if ( WINP_SNIPPET_TYPE_TEXT != $snippet['type'] ) {
151 + $content = empty( $content ) && isset( $snippet['code'] ) && ! empty( $snippet['code'] ) ? $snippet['code'] : $content;
152 + }
153 +
154 + $data = [
155 + 'post_title' => $snippet['title'],
156 + 'post_content' => $content,
157 + 'post_status' => 'publish',
158 + 'post_type' => WINP_SNIPPETS_POST_TYPE
159 + ];
160 +
161 + if ( isset( $snippet['id'] ) && 0 != $snippet['id'] ) {
162 + $data['ID'] = $snippet['id'];
163 + }
164 +
165 + $snippet['id'] = wp_insert_post( $data );
166 +
167 + $this->updateMeta( $snippet['id'], 'snippet_location', $snippet['location'] );
168 + $this->updateMeta( $snippet['id'], 'snippet_type', $snippet['type'] );
169 + $this->updateMeta( $snippet['id'], 'snippet_filters', $snippet['filters'] );
170 + $this->updateMeta( $snippet['id'], 'changed_filters', $snippet['changed_filters'] );
171 + $this->updateMeta( $snippet['id'], 'snippet_scope', $snippet['scope'] );
172 + $this->updateMeta( $snippet['id'], 'snippet_description', $snippet['description'] );
173 + $this->updateMeta( $snippet['id'], 'snippet_tags', $snippet['attributes'] );
174 + $this->updateMeta( $snippet['id'], 'snippet_activate', 0 );
175 +
176 + $this->updateTaxonomyTags( $snippet['id'], $snippet['tags'] );
177 +
178 + return $snippet['id'];
179 + }
180 +
181 + /**
182 + * Save imported snippets
183 + *
184 + * @param $snippets
185 + * @param $dup_action
186 + *
187 + * @return array
188 + */
189 + private function saveImportedSnippets( $snippets, $dup_action ) {
190 + $existing_snippets = [];
191 + if ( 'replace' === $dup_action || 'skip' === $dup_action ) {
192 + $all_snippets = get_posts( [ 'post_type' => WINP_SNIPPETS_POST_TYPE ] );
193 + foreach ( $all_snippets as $snippet ) {
194 + $existing_snippets[ $snippet->post_name ] = $snippet->ID;
195 + }
196 + }
197 +
198 + $imported = [];
199 +
200 + foreach ( $snippets as $snippet ) {
201 + if ( 'ignore' !== $dup_action && isset( $existing_snippets[ $snippet['name'] ] ) ) {
202 + if ( 'replace' === $dup_action ) {
203 + $snippet['id'] = $existing_snippets[ $snippet['name'] ];
204 + } else if ( 'skip' === $dup_action ) {
205 + continue;
206 + }
207 + }
208 +
209 + if ( $snippet_id = $this->saveSnippet( $snippet ) ) {
210 + $imported[] = $snippet_id;
211 + }
212 + }
213 +
214 + return $imported;
215 + }
216 +
217 +}