PluginProbe
MainWP Dashboard: Self-hosted WordPress Management for Agencies / 5.2.2
MainWP Dashboard: Self-hosted WordPress Management for Agencies v5.2.2
6.2.2 6.2.1 6.2 6.1.8 6.1.7 6.1.6 6.1.5 6.1.4 6.1.3 6.1.2 6.1.1 6.1 6.0.12 6.0.11 4.6.0.1 5.0 5.0.1 5.0.2 5.0.3 5.0.3.1 5.0.3.2 5.1 5.1.1 5.2 5.2.1 All 155 releases
mainwp / pages / page-mainwp-post-page-handler.php

page-mainwp-post-page-handler.php in MainWP Dashboard: Self-hosted WordPress Management for Agencies 5.2.2, at pages/page-mainwp-post-page-handler.php

1,412 lines 65.2 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * Post Page Handler.
4 *
5 * @package MainWP/Dashboard
6 */
7
8 namespace MainWP\Dashboard;
9
10 /**
11 * Class MainWP_Post_Page_Handler
12 *
13 * @uses MainWP_Bulk_Add
14 */
15 class MainWP_Post_Page_Handler { // phpcs:ignore Generic.Classes.OpeningBraceSameLine.ContentAfterBrace -- NOSONAR.
16
17 /**
18 * Get Class Name
19 *
20 * @return string __CLASS__
21 */
22 public static function get_class_name() {
23 return __CLASS__;
24 }
25
26 /**
27 * Method add_meta()
28 *
29 * Add post meta data defined in $_POST superglobal for post with given ID.
30 *
31 * @since 1.2.0
32 *
33 * @param int $post_ID Post or Page ID.
34 * @return mixed False or add_post_meta()
35 */
36 public static function add_meta( $post_ID ) {
37 $post_ID = (int) $post_ID;
38
39 // phpcs:disable WordPress.Security.NonceVerification,WordPress.Security.ValidatedSanitizedInput.InputNotSanitized
40 $metakeyselect = isset( $_POST['metakeyselect'] ) ? sanitize_text_field( wp_unslash( $_POST['metakeyselect'] ) ) : '';
41 $metakeyinput = isset( $_POST['metakeyinput'] ) ? sanitize_text_field( wp_unslash( $_POST['metakeyinput'] ) ) : '';
42 $metavalue = isset( $_POST['metavalue'] ) ? sanitize_text_field( wp_unslash( $_POST['metavalue'] ) ) : '';
43 if ( is_string( $metavalue ) ) {
44 $metavalue = trim( $metavalue );
45 }
46 // phpcs:enable
47
48 if ( ( ( '#NONE#' !== $metakeyselect ) && ! empty( $metakeyselect ) ) || ! empty( $metakeyinput ) ) {
49 if ( '#NONE#' !== $metakeyselect ) {
50 $metakey = $metakeyselect;
51 }
52
53 if ( $metakeyinput ) {
54 $metakey = $metakeyinput;
55 }
56
57 if ( is_protected_meta( $metakey, 'post' ) || ! current_user_can( 'add_post_meta', $post_ID, $metakey ) ) {
58 return false;
59 }
60
61 $metakey = wp_slash( $metakey );
62
63 return add_post_meta( $post_ID, $metakey, $metavalue );
64 }
65
66 return false;
67 }
68
69 /**
70 * Method ajax_add_meta()
71 *
72 * Ajax process to add post meta data.
73 *
74 * @uses \MainWP\Dashboard\MainWP_Post_Handler::secure_request()
75 * @uses \MainWP\Dashboard\MainWP_Post::list_meta_row()
76 */
77 public static function ajax_add_meta() { // phpcs:ignore -- NOSONAR -Current complexity is the only way to achieve desired results, pull request solutions appreciated.
78
79 MainWP_Post_Handler::instance()->secure_request( 'mainwp_post_addmeta' );
80
81 $c = 0;
82 $pid = isset( $_POST['post_id'] ) ? (int) $_POST['post_id'] : 0;
83
84 if ( isset( $_POST['metakeyselect'] ) || isset( $_POST['metakeyinput'] ) ) {
85 if ( ! current_user_can( 'edit_post', $pid ) ) {
86 wp_die( -1 );
87 }
88 if ( isset( $_POST['metakeyselect'] ) && '#NONE#' === $_POST['metakeyselect'] && empty( $_POST['metakeyinput'] ) ) {
89 wp_die( 1 );
90 }
91 $mid = static::add_meta( $pid );
92 if ( ! $mid ) {
93 wp_send_json( array( 'error' => esc_html__( 'Please provide a custom field value.', 'mainwp' ) ) );
94 }
95
96 $meta = get_metadata_by_mid( 'post', $mid );
97 $meta = get_object_vars( $meta );
98 $data = MainWP_Post::list_meta_row( $meta, $c );
99
100 } elseif ( isset( $_POST['delete_meta'] ) && 'yes' === $_POST['delete_meta'] ) {
101 $id = isset( $_POST['id'] ) ? (int) $_POST['id'] : 0;
102
103 check_ajax_referer( "delete-meta_$id", 'meta_nonce' );
104 $meta = get_metadata_by_mid( 'post', $id );
105 if ( ! $meta ) {
106 wp_send_json( array( 'ok' => 1 ) );
107 }
108
109 if ( is_protected_meta( $meta->meta_key, 'post' ) || ! current_user_can( 'delete_post_meta', $meta->post_id, $meta->meta_key ) ) {
110 wp_die( -1 );
111 }
112
113 if ( delete_meta( $meta->meta_id ) ) {
114 wp_send_json( array( 'ok' => 1 ) );
115 }
116
117 wp_die( 0 );
118
119 } else {
120 $mid = isset( $_POST['meta'] ) ? (int) key( wp_unslash( $_POST['meta'] ) ) : 0; //phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized
121 $key = isset( $_POST['meta'][ $mid ]['key'] ) ? sanitize_text_field( wp_unslash( $_POST['meta'][ $mid ]['key'] ) ) : '';
122 $value = isset( $_POST['meta'][ $mid ]['value'] ) ? sanitize_text_field( wp_unslash( $_POST['meta'][ $mid ]['value'] ) ) : '';
123 if ( '' === trim( $key ) ) {
124 wp_send_json( array( 'error' => esc_html__( 'Please provide a custom field name.', 'mainwp' ) ) );
125 }
126 $meta = get_metadata_by_mid( 'post', $mid );
127 if ( ! $meta ) {
128 wp_die( 0 );
129 }
130 if ( is_protected_meta( $meta->meta_key, 'post' ) || is_protected_meta( $key, 'post' ) ||
131 ! current_user_can( 'edit_post_meta', $meta->post_id, $meta->meta_key ) ||
132 ! current_user_can( 'edit_post_meta', $meta->post_id, $key ) ) {
133 wp_die( -1 );
134 }
135 if ( $meta->meta_value !== $value || $meta->meta_key !== $key ) {
136 $u = update_metadata_by_mid( 'post', $mid, $value, $key );
137 if ( ! $u ) {
138 wp_die( 0 );
139 }
140 }
141
142 $data = MainWP_Post::list_meta_row(
143 array(
144 'meta_key' => $key, //phpcs:ignore WordPress.DB.SlowDBQuery.slow_db_query_meta_key -- deprecated, compatible.
145 'meta_value' => $value, //phpcs:ignore WordPress.DB.SlowDBQuery.slow_db_query_meta_value -- deprecated, compatible.
146 'meta_id' => $mid,
147 ),
148 $c
149 );
150 }
151
152 wp_send_json( array( 'result' => $data ) );
153 }
154
155
156 /**
157 * Method ajax_handle_get_categories()
158 *
159 * Get categories.
160 *
161 * @uses \MainWP\Dashboard\MainWP_DB::get_websites_by_ids()
162 * @uses \MainWP\Dashboard\MainWP_DB::get_websites_by_group_ids()
163 * @uses \MainWP\Dashboard\MainWP_Utility::ctype_digit()
164 */
165 public static function ajax_handle_get_categories() { // phpcs:ignore -- NOSONAR - complex method. Current complexity is the only way to achieve desired results, pull request solutions appreciated.
166 // phpcs:disable WordPress.Security.NonceVerification,WordPress.Security.ValidatedSanitizedInput.InputNotSanitized
167 $websites = array();
168 if ( isset( $_REQUEST['sites'] ) && ( '' !== $_REQUEST['sites'] ) ) {
169 $siteIds = explode( ',', urldecode( wp_unslash( $_REQUEST['sites'] ) ) ); // do not sanitize encoded values.
170 $siteIdsRequested = array();
171 foreach ( $siteIds as $siteId ) {
172 if ( ! MainWP_Utility::ctype_digit( $siteId ) ) {
173 continue;
174 }
175 $siteIdsRequested[] = $siteId;
176 }
177
178 $websites = MainWP_DB::instance()->get_websites_by_ids( $siteIdsRequested );
179 } elseif ( isset( $_REQUEST['groups'] ) && ( '' !== $_REQUEST['groups'] ) ) {
180 $groupIds = explode( ',', sanitize_text_field( urldecode( wp_unslash( $_REQUEST['groups'] ) ) ) ); // sanitize ok.
181 $groupIdsRequested = array();
182 foreach ( $groupIds as $groupId ) {
183 if ( ! MainWP_Utility::ctype_digit( $groupId ) ) {
184 continue;
185 }
186 $groupIdsRequested[] = $groupId;
187 }
188
189 $websites = MainWP_DB::instance()->get_websites_by_group_ids( $groupIdsRequested );
190 } elseif ( isset( $_REQUEST['clients'] ) && ( '' !== $_REQUEST['clients'] ) ) {
191 $clientIds = explode( ',', sanitize_text_field( urldecode( wp_unslash( $_REQUEST['clients'] ) ) ) ); // sanitize ok.
192 $clientIdsRequested = array();
193 foreach ( $clientIds as $clientId ) {
194
195 if ( ! MainWP_Utility::ctype_digit( $clientId ) ) {
196 continue;
197 }
198 $clientIdsRequested[] = $clientId;
199 }
200
201 $data_fields = array(
202 'id',
203 'url',
204 'name',
205 'categories',
206 'sync_errors',
207 );
208 $websites = MainWP_DB_Client::instance()->get_websites_by_client_ids(
209 $clientIdsRequested,
210 array(
211 'select_data' => $data_fields,
212 )
213 );
214 }
215
216 $selectedCategories = array();
217
218 $is_cpt = isset( $_POST['custom_post_type'] ) && ! empty( $_POST['custom_post_type'] ) ? true : false;
219
220 if ( isset( $_REQUEST['selected_categories'] ) && ( '' !== $_REQUEST['selected_categories'] ) ) {
221 $selectedCategories = explode( ',', sanitize_text_field( urldecode( wp_unslash( $_REQUEST['selected_categories'] ) ) ) );
222 }
223
224 if ( ! is_array( $selectedCategories ) ) {
225 $selectedCategories = array();
226 }
227
228 $allCategories_new_tree = array();
229 $allCategories = array( 'Uncategorized' );
230
231 if ( ! empty( $websites ) ) {
232 foreach ( $websites as $website ) {
233 if ( ! $is_cpt ) {
234 $new_cats = json_decode( $website->categories, true );
235 if ( is_array( $new_cats ) && ! empty( $new_cats ) ) {
236 $current = current( $new_cats );
237 if ( is_array( $current ) && ! empty( $current ) ) { // new site's category format data.
238 static::arrange_categories_list( $new_cats, $allCategories_new_tree );
239 } elseif ( is_string( $current ) ) { // old format.
240 $allCategories = array_unique( array_merge( $allCategories, $new_cats ) );
241 }
242 }
243 } else {
244 $custom_categories = apply_filters( 'mainwp_edit_post_get_categories', false, $website, $_REQUEST );
245 if ( is_array( $custom_categories ) && ! empty( $custom_categories ) ) {
246 static::arrange_categories_list( $custom_categories, $allCategories_new_tree );
247 }
248 }
249 }
250 }
251
252 $allCategories = array_unique( array_merge( $allCategories, $selectedCategories ) );
253
254 ob_start();
255 echo '<div class="item" data-value="Uncategorized" class="sitecategory-list">Uncategorized</div>';
256
257 if ( ! empty( $allCategories ) || ! empty( $allCategories_new_tree ) ) {
258 ?>
259 <?php
260 $check_printed_cats_names = array();
261
262 if ( ! empty( $allCategories_new_tree ) ) {
263 // print new casts list.
264 static::print_catergories_tree( $allCategories_new_tree, $check_printed_cats_names );
265 }
266
267 if ( ! $is_cpt && ! empty( $allCategories ) ) {
268 echo '<div class="ui horizontal divider"></div>';
269 natcasesort( $allCategories );
270 foreach ( $allCategories as $category ) {
271 if ( 'Uncategorized' === $category || isset( $check_printed_cats_names[ $category ] ) ) {
272 continue; // printed.
273 }
274 echo '<div class="item" data-value="' . esc_attr( $category ) . '" class="sitecategory-list">' . esc_html( $category ) . '</div>';
275 }
276 }
277 }
278 // phpcs:enable WordPress.Security.NonceVerification,WordPress.Security.ValidatedSanitizedInput.InputNotSanitized
279
280 $output = ob_get_clean();
281 wp_die( wp_json_encode( array( 'content' => $output ) ) );
282 }
283
284 /**
285 * Method print_catergories_tree()
286 *
287 * @param array $print_cats categories to print.
288 * @param array $check_printed_cats_names check printed cats slugs.
289 */
290 public static function print_catergories_tree( $print_cats, &$check_printed_cats_names = array() ) { // phpcs:ignore Squiz.Functions.MultiLineFunctionDeclaration.ContentAfterBrace -- NOSONAR - complexity.
291 foreach ( $print_cats as $item ) {
292
293 $level = isset( $item['level'] ) ? $item['level'] : 0;
294 $term_pt = isset( $item['term_post_type'] ) && ! empty( $item['term_post_type'] ) ? sanitize_text_field( wp_unslash( $item['term_post_type'] ) ) : '';
295
296 $print_slug = $item['slug'];
297
298 if ( ! empty( $term_pt ) ) {
299 $print_slug .= '_' . $term_pt;
300 }
301
302 if ( 'Uncategorized' !== $item['name'] && ! in_array( $print_slug, $check_printed_cats_names, true ) ) {
303 $cls = 'category-select-item-sub' . ( ! empty( $level ) ? intval( $level ) : '' );
304
305 $check_printed_cats_names[] = $print_slug;
306
307 if ( ! empty( $term_pt ) ) {
308 $cat_val = wp_json_encode(
309 array(
310 'name' => esc_html( $item['name'] ),
311 'slug' => esc_html( $item['slug'] ),
312 'taxonomy' => esc_html( $item['taxonomy'] ),
313 'parent' => esc_html( $item['parent'] ),
314 'description' => esc_html( $item['description'] ),
315 )
316 );
317 $cat_val = ! empty( $cat_val ) ? '_custom_term_' . esc_attr( base64_encode( $cat_val ) ) : ''; //phpcs:ignore -- ok.
318 } else {
319 $cat_val = esc_attr( $item['name'] );
320 }
321
322 $title = ! empty( $term_pt ) ? '<strong>' . esc_html( $item['name'] ) . '</strong>' : esc_html( $item['name'] );
323 echo '<div class="item ' . esc_attr( $cls ) . '" data-value="' . $cat_val . '" data-slug="' . esc_attr( $item['slug'] ) . '" post-type="' . esc_attr( $term_pt ) . '"class="sitecategory-list">' . $title . '</div>'; //phpcs:ignore -- ok.
324 }
325
326 if ( ! empty( $item['children'] ) ) {
327 static::print_catergories_tree( $item['children'], $check_printed_cats_names );
328 }
329 }
330 }
331
332 /**
333 * Method arrange_categories_list()
334 *
335 * Tweaked John#105641 at StackOver#4284616.
336 *
337 * @param array $categories categories.
338 * @param array $save_all_cats_tree all categories tree.
339 */
340 public static function arrange_categories_list( $categories, &$save_all_cats_tree ) { //phpcs:ignore -- NOSONAR - complex.
341
342 if ( ! is_array( $save_all_cats_tree ) ) {
343 $save_all_cats_tree = array();
344 }
345
346 if ( ! is_array( $categories ) ) {
347 return;
348 }
349
350 $tree_cats = $save_all_cats_tree;
351 $all_cats = array();
352 $child_cats = array();
353
354 foreach ( $categories as $cat ) {
355
356 if ( ! is_array( $cat ) || empty( $cat['name'] ) ) {
357 continue;
358 }
359
360 $cat['children'] = array();
361 $term_id = $cat['term_id'];
362
363 // If this is a top-level.
364 if ( empty( $cat['parent'] ) ) {
365 $cat['level'] = 0;
366 $all_cats[ $term_id ] = $cat;
367 $tree_cats[] =& $all_cats[ $term_id ];
368 // If this isn't a top-level.
369 } else {
370 $cat['level'] = isset( $all_cats[ $cat['parent'] ] ) && isset( $all_cats[ $cat['parent'] ]['level'] ) ? $all_cats[ $cat['parent'] ]['level'] + 1 : 1;
371 $child_cats[ $term_id ] = $cat;
372 }
373 }
374
375 $stop = count( $categories );
376 $limit = 0;
377 $count = count( $child_cats );
378 // Process child cats.
379 while ( $count > 0 && $limit < $stop ) {
380 foreach ( $child_cats as $cat ) {
381 $term_id = $cat['term_id'];
382 $pid = isset( $cat['parent'] ) ? $cat['parent'] : -1;
383
384 if ( isset( $all_cats[ $pid ] ) ) {
385 $cat['level'] = isset( $all_cats[ $pid ] ) && isset( $all_cats[ $pid ]['level'] ) ? $all_cats[ $pid ]['level'] + 1 : 1;
386 $all_cats[ $term_id ] = $cat;
387 $all_cats[ $pid ]['children'][] =& $all_cats[ $term_id ];
388 unset( $child_cats[ $cat['term_id'] ] );
389 }
390 }
391 ++$limit;
392 }
393 $save_all_cats_tree = $tree_cats; // to prevent it deleted by reference.
394 }
395
396 /**
397 * Method posting_bulk()
398 *
399 * Create bulk posts on sites.
400 */
401 public static function posting_bulk() {
402 $p_id = isset( $_GET['id'] ) ? intval( $_GET['id'] ) : false; // phpcs:ignore WordPress.Security.NonceVerification,WordPress.Security.ValidatedSanitizedInput.InputNotSanitized
403
404 if ( ! isset( $_GET['posting_nonce'] ) || ( isset( $_GET['posting_nonce'] ) && ! wp_verify_nonce( sanitize_key( $_GET['posting_nonce'] ), 'posting_nonce_' . $p_id ) ) ) { //phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotValidated
405 wp_die( 'Invalid request!' );
406 }
407
408 $posting_bulk_sites = apply_filters( 'mainwp_posts_posting_bulk_sites', false );
409 ?>
410 <input type="hidden" name="bulk_posting_id" id="bulk_posting_id" value="<?php echo intval( $p_id ); ?>"/>
411 <?php
412 if ( ! $posting_bulk_sites ) {
413 static::posting( $p_id );
414 } else {
415 static::posting_prepare( $p_id );
416 }
417 }
418
419 /**
420 * Method posting()
421 *
422 * Create bulk posts on sites.
423 *
424 * @param int $post_id Post or Page ID.
425 *
426 * @uses \MainWP\Dashboard\MainWP_Connect::fetch_url_authed()
427 * @uses \MainWP\Dashboard\MainWP_DB::query()
428 * @uses \MainWP\Dashboard\MainWP_DB::get_sql_websites_by_group_id()
429 * @uses \MainWP\Dashboard\MainWP_DB::fetch_object()
430 * @uses \MainWP\Dashboard\MainWP_DB::free_result()
431 * @uses \MainWP\Dashboard\MainWP_System_Utility::maybe_unserialyze()
432 * @uses \MainWP\Dashboard\MainWP_Bulk_Add::get_class_name()
433 * @uses \MainWP\Dashboard\MainWP_Utility::ctype_digit()
434 * @uses \MainWP\Dashboard\MainWP_Utility::map_site()
435 */
436 public static function posting( $post_id ) { // phpcs:ignore -- NOSONAR - complex method. Current complexity is the only way to achieve desired results, pull request solutions appreciated.
437 $p_id = $post_id;
438
439 $edit_id = get_post_meta( $post_id, '_mainwp_edit_post_id', true );
440
441 ?>
442 <div class="ui modal" id="mainwp-posting-post-modal">
443 <i class="close icon"></i>
444 <div class="header"><?php $edit_id ? esc_html_e( 'Edit Post', 'mainwp' ) : esc_html_e( 'New Post', 'mainwp' ); ?></div>
445 <div class="scrolling content">
446 <?php
447 /**
448 * Before Post post action
449 *
450 * Fires right before posting the 'bulkpost' to child sites.
451 *
452 * @param int $p_id Page ID.
453 *
454 * @since Unknown
455 */
456 do_action( 'mainwp_bulkpost_before_post', $p_id );
457
458 $skip_post = false;
459 if ( $p_id && 'yes' === get_post_meta( $p_id, '_mainwp_skip_posting', true ) ) {
460 $skip_post = true;
461 wp_delete_post( $p_id, true );
462 }
463
464 if ( ! $skip_post ) {
465 if ( $p_id ) {
466 static::posting_posts( $p_id, 'posting' );
467 } else {
468 ?>
469 <div class="error">
470 <p>
471 <strong><?php esc_html_e( 'ERROR', 'mainwp' ); ?></strong>: <?php esc_html_e( 'An undefined error occured!', 'mainwp' ); ?>
472 </p>
473 </div>
474 <?php
475 }
476 }
477 ?>
478 </div>
479 <div class="actions">
480 <?php do_action( 'mainwp_posts_posting_popup_actions', $post_id ); ?>
481 <a href="admin.php?page=PostBulkAdd" class="ui green button new-bulk-post"><?php esc_html_e( 'New Post', 'mainwp' ); ?></a>
482 </div>
483 </div>
484 <div class="ui active inverted dimmer" id="mainwp-posting-running">
485 <div class="ui indeterminate large text loader"><?php esc_html_e( 'Running ...', 'mainwp' ); ?></div>
486 </div>
487 <script type="text/javascript">
488 jQuery( document ).ready( function () {
489 jQuery( "#mainwp-posting-running" ).hide();
490 jQuery( "#mainwp-posting-post-modal" ).modal( {
491 closable: true,
492 onHide: function() {
493 location.href = 'admin.php?page=PostBulkManage';
494 }
495 } ).modal( 'show' );
496 } );
497 </script>
498 <?php
499 }
500
501 /**
502 * Method posting_prepare()
503 *
504 * Posting posts.
505 *
506 * @param int $post_id Post or Page ID.
507 */
508 public static function posting_prepare( $post_id ) {
509 $edit_id = get_post_meta( $post_id, '_mainwp_edit_post_id', true );
510 ?>
511 <div class="ui modal" id="mainwp-posting-post-modal">
512 <i class="close icon"></i>
513 <div class="header"><?php $edit_id ? esc_html_e( 'Edit Post', 'mainwp' ) : esc_html_e( 'New Post', 'mainwp' ); ?></div>
514 <div class="scrolling content">
515 <?php
516 if ( $post_id ) {
517 static::posting_posts( $post_id, 'preparing' );
518 } else {
519 ?>
520 <div class="error">
521 <p>
522 <strong><?php esc_html_e( 'ERROR', 'mainwp' ); ?></strong>: <?php esc_html_e( 'An undefined error occured!', 'mainwp' ); ?>
523 </p>
524 </div>
525 <?php
526 }
527 ?>
528 </div>
529 <div class="actions">
530 <a href="admin.php?page=PostBulkAdd" class="ui green button"><?php esc_html_e( 'New Post', 'mainwp' ); ?></a>
531 </div>
532 </div>
533 <div class="ui active inverted dimmer" id="mainwp-posting-running">
534 <div class="ui indeterminate large text loader"><?php esc_html_e( 'Running ...', 'mainwp' ); ?></div>
535 </div>
536 <script type="text/javascript">
537 jQuery( document ).ready( function () {
538 jQuery( "#mainwp-posting-running" ).hide();
539 jQuery( "#mainwp-posting-post-modal" ).modal( {
540 closable: true,
541 onHide: function() {
542 location.href = 'admin.php?page=PostBulkManage';
543 }
544 } ).modal( 'show' );
545 mainwp_post_posting_start_next( true );
546 } );
547 </script>
548 <?php
549 }
550
551
552 /**
553 * Method ajax_posting_posts()
554 *
555 * Ajax Posting posts.
556 */
557 public static function ajax_posting_posts() {
558 // phpcs:disable WordPress.Security.NonceVerification,WordPress.Security.ValidatedSanitizedInput.InputNotSanitized
559 MainWP_Post_Handler::instance()->secure_request( 'mainwp_post_postingbulk' );
560 $post_id = isset( $_POST['post_id'] ) ? intval( $_POST['post_id'] ) : false;
561 if ( $post_id ) {
562 static::posting_posts( $post_id, 'ajax_posting' );
563 }
564 // phpcs:enable
565 die();
566 }
567
568 /**
569 * Method ajax_get_sites_of_groups()
570 *
571 * Ajax Get sites of groups.
572 */
573 public static function ajax_get_sites_of_groups() {
574 // phpcs:disable WordPress.Security.NonceVerification,WordPress.Security.ValidatedSanitizedInput.InputNotSanitized
575 MainWP_Post_Handler::instance()->secure_request( 'mainwp_get_sites_of_groups' );
576 $groups = isset( $_POST['groups'] ) && is_array( $_POST['groups'] ) ? array_map( 'sanitize_text_field', wp_unslash( $_POST['groups'] ) ) : '';
577 $websites = MainWP_DB::instance()->get_websites_by_group_ids( $groups );
578 // phpcs:enable
579 $site_Ids = array();
580 if ( $websites ) {
581 foreach ( $websites as $website ) {
582 $site_Ids[] = $website->id;
583 }
584 }
585 die( wp_json_encode( $site_Ids ) );
586 }
587
588 /**
589 * Method posting_posts()
590 *
591 * Posting posts.
592 *
593 * @param int $post_id Post or Page ID.
594 * @param string $what What posting process.
595 */
596 public static function posting_posts( $post_id, $what ) { // phpcs:ignore -- NOSONAR -Current complexity is the only way to achieve desired results, pull request solutions appreciated.
597
598 if ( empty( $post_id ) ) {
599 return false;
600 }
601
602 $succes_message = '';
603 $edit_id = get_post_meta( $post_id, '_mainwp_edit_post_id', true );
604 if ( $edit_id ) {
605 $succes_message = esc_html__( 'Post has been updated successfully', 'mainwp' );
606 } else {
607 $succes_message = esc_html__( 'New post created', 'mainwp' );
608 }
609
610 $id = $post_id;
611 $_post = get_post( $id );
612
613 if ( $_post ) {
614 $selected_by = 'site';
615 $selected_groups = array();
616 $selected_sites = array();
617 $selected_clients = array();
618
619 if ( 'posting' === $what || 'preparing' === $what ) {
620 $selected_by = get_post_meta( $id, '_selected_by', true );
621 $val = get_post_meta( $id, '_selected_sites', true );
622 $selected_sites = MainWP_System_Utility::maybe_unserialyze( $val );
623 $val = get_post_meta( $id, '_selected_groups', true );
624 $selected_groups = MainWP_System_Utility::maybe_unserialyze( $val );
625 $selected_clients = get_post_meta( $id, '_selected_clients', true );
626 $selected_by = apply_filters( 'mainwp_posting_post_selected_by', $selected_by, $id );
627 } elseif ( 'ajax_posting' === $what ) {
628 $site_id = isset( $_POST['site_id'] ) ? intval( $_POST['site_id'] ) : 0; // phpcs:ignore WordPress.Security.NonceVerification,WordPress.Security.ValidatedSanitizedInput.InputNotSanitized
629 if ( $site_id ) {
630 $selected_sites = array( $site_id );
631 }
632 }
633
634 $selected_sites = apply_filters( 'mainwp_posting_post_selected_sites', $selected_sites, $id );
635 $selected_groups = apply_filters( 'mainwp_posting_selected_groups', $selected_groups, $id );
636 $selected_clients = apply_filters( 'mainwp_posting_selected_clients', $selected_clients, $id );
637
638 if ( 'preparing' !== $what ) {
639 $post_category = base64_decode( get_post_meta( $id, '_categories', true ) ); // phpcs:ignore WordPress.PHP.DiscouragedPHPFunctions -- base64_encode used for http encoding compatible.
640
641 $post_tags = base64_decode( get_post_meta( $id, '_tags', true ) ); // phpcs:ignore WordPress.PHP.DiscouragedPHPFunctions -- base64_encode used for http encoding compatible.
642 $post_slug = base64_decode( get_post_meta( $id, '_slug', true ) ); // phpcs:ignore WordPress.PHP.DiscouragedPHPFunctions -- base64_encode used for http encoding compatible.
643 $post_custom = get_post_custom( $id );
644
645 $galleries = get_post_galleries( $id, false );
646 $post_gallery_images = array();
647
648 if ( is_array( $galleries ) ) {
649 foreach ( $galleries as $gallery ) {
650 if ( isset( $gallery['ids'] ) ) {
651 $attached_images = explode( ',', $gallery['ids'] );
652 foreach ( $attached_images as $attachment_id ) {
653 $attachment = get_post( $attachment_id );
654 if ( $attachment ) {
655 $post_gallery_images[] = array(
656 'id' => $attachment_id,
657 'alt' => get_post_meta( $attachment->ID, '_wp_attachment_image_alt', true ),
658 'caption' => MainWP_Utility::esc_content( $attachment->post_excerpt, 'mixed' ),
659 'description' => $attachment->post_content,
660 'src' => $attachment->guid,
661 'image_url' => wp_get_attachment_image_url( $attachment_id ), // to fix src/guid missing the file name.
662 'title' => htmlspecialchars( $attachment->post_title ),
663 );
664 }
665 }
666 }
667 }
668 }
669
670 include_once ABSPATH . 'wp-includes' . DIRECTORY_SEPARATOR . 'post-thumbnail-template.php'; // NOSONAR - WP compatible.
671 $featured_image_id = get_post_thumbnail_id( $id );
672 $post_featured_image = null;
673 $featured_image_data = null;
674 $mainwp_upload_dir = wp_upload_dir();
675
676 // to fix.
677 $post_status = $_post->post_status;
678 if ( 'publish' === $post_status ) {
679 $post_status = get_post_meta( $id, '_edit_post_status', true );
680 }
681
682 /**
683 * Post status
684 *
685 * Sets post status when posting 'bulkpost' to child sites.
686 *
687 * @param int $id Post ID.
688 *
689 * @since Unknown
690 */
691 $post_status = apply_filters( 'mainwp_posting_bulkpost_post_status', $post_status, $id );
692 $new_post = array(
693 'post_title' => $_post->post_title,
694 'post_content' => $_post->post_content,
695 'post_status' => $post_status,
696 'post_date' => $_post->post_date,
697 'post_date_gmt' => $_post->post_date_gmt,
698 'post_tags' => $post_tags,
699 'post_name' => $post_slug,
700 'post_excerpt' => MainWP_Utility::esc_content( $_post->post_excerpt, 'mixed' ),
701 'post_password' => $_post->post_password,
702 'comment_status' => $_post->comment_status,
703 'ping_status' => $_post->ping_status,
704 'mainwp_post_id' => $_post->ID,
705 );
706
707 if ( ! empty( $featured_image_id ) ) {
708 $img = wp_get_attachment_image_src( $featured_image_id, 'full' );
709 $post_featured_image = $img[0];
710 $attachment = get_post( $featured_image_id );
711 $featured_image_data = array(
712 'alt' => get_post_meta( $featured_image_id, '_wp_attachment_image_alt', true ),
713 'caption' => MainWP_Utility::esc_content( $attachment->post_excerpt, 'mixed' ),
714 'description' => $attachment->post_content,
715 'title' => htmlspecialchars( $attachment->post_title ),
716 );
717 }
718 }
719
720 $data_fields = MainWP_System_Utility::get_default_map_site_fields();
721
722 $dbwebsites = array();
723
724 if ( 'site' === $selected_by ) {
725 foreach ( $selected_sites as $k ) {
726 if ( MainWP_Utility::ctype_digit( $k ) ) {
727 $website = MainWP_DB::instance()->get_website_by_id( $k );
728 if ( empty( $website->sync_errors ) && ! MainWP_System_Utility::is_suspended_site( $website ) ) {
729 $dbwebsites[ $website->id ] = MainWP_Utility::map_site( $website, $data_fields );
730 }
731 }
732 }
733 } elseif ( 'client' === $selected_by ) {
734 $websites = MainWP_DB_Client::instance()->get_websites_by_client_ids(
735 $selected_clients,
736 array(
737 'select_data' => $data_fields,
738 )
739 );
740 if ( $websites ) {
741 foreach ( $websites as $website ) {
742 if ( '' !== $website->sync_errors || MainWP_System_Utility::is_suspended_site( $website ) ) {
743 continue;
744 }
745 $dbwebsites[ $website->id ] = MainWP_Utility::map_site( $website, $data_fields );
746 }
747 }
748 } elseif ( 'group' === $selected_by ) {
749 foreach ( $selected_groups as $k ) {
750 if ( MainWP_Utility::ctype_digit( $k ) ) {
751 $websites = MainWP_DB::instance()->query( MainWP_DB::instance()->get_sql_websites_by_group_id( $k ) );
752 while ( $websites && ( $website = MainWP_DB::fetch_object( $websites ) ) ) {
753 if ( '' !== $website->sync_errors || MainWP_System_Utility::is_suspended_site( $website ) ) {
754 continue;
755 }
756 $dbwebsites[ $website->id ] = MainWP_Utility::map_site( $website, $data_fields );
757 }
758 MainWP_DB::free_result( $websites );
759 }
760 }
761 }
762
763 if ( 'preparing' === $what ) {
764 ?>
765 <div class="ui relaxed list">
766 <?php
767 foreach ( $dbwebsites as $website ) {
768 ?>
769 <div class="item site-bulk-posting" site-id="<?php echo intval( $website->id ); ?>" status="queue"><a href="<?php echo esc_url( admin_url( 'admin.php?page=managesites&dashboard=' . $website->id ) ); ?>"><?php echo esc_html( stripslashes( $website->name ) ); ?></a>
770 <div class="right floated content progress"><i class="clock outline icon"></i></div>
771 </div>
772 <?php } ?>
773 </div>
774 <?php
775 } else {
776
777 $output = new \stdClass();
778 $output->ok = array();
779 $output->errors = array();
780
781 if ( ! empty( $dbwebsites ) ) {
782
783 // prepare $post_custom values.
784 $new_post_custom = array();
785 foreach ( $post_custom as $meta_key => $meta_values ) {
786 $new_meta_values = array();
787 foreach ( $meta_values as $key_value => $meta_value ) {
788 if ( is_serialized( $meta_value ) ) {
789 $meta_value = unserialize( $meta_value ); // phpcs:ignore -- internal value safe.
790 }
791 $new_meta_values[ $key_value ] = $meta_value;
792 }
793 $new_post_custom[ $meta_key ] = $new_meta_values;
794 }
795 $post_data = array(
796 'new_post' => base64_encode( wp_json_encode( $new_post ) ), // phpcs:ignore WordPress.PHP.DiscouragedPHPFunctions -- base64_encode used for http encoding compatible.
797 'post_custom' => base64_encode( wp_json_encode( $new_post_custom ) ), // phpcs:ignore WordPress.PHP.DiscouragedPHPFunctions -- base64_encode used for http encoding compatible.
798 'post_category' => ! empty( $post_category ) ? base64_encode( $post_category ) : '', // phpcs:ignore WordPress.PHP.DiscouragedPHPFunctions -- base64_encode used for http encoding compatible.
799 'post_featured_image' => ( null !== $post_featured_image ) ? base64_encode( $post_featured_image ) : null, // phpcs:ignore WordPress.PHP.DiscouragedPHPFunctions -- base64_encode used for http encoding compatible.
800 'post_gallery_images' => base64_encode( wp_json_encode( $post_gallery_images ) ), // phpcs:ignore WordPress.PHP.DiscouragedPHPFunctions -- base64_encode used for http encoding compatible.
801 'mainwp_upload_dir' => base64_encode( wp_json_encode( $mainwp_upload_dir ) ), // phpcs:ignore WordPress.PHP.DiscouragedPHPFunctions -- base64_encode used for http encoding compatible.
802 'featured_image_data' => ( null !== $featured_image_data ) ? base64_encode( wp_json_encode( $featured_image_data ) ) : null, // phpcs:ignore WordPress.PHP.DiscouragedPHPFunctions -- base64_encode used for http encoding compatible.
803 );
804 MainWP_Connect::fetch_urls_authed(
805 $dbwebsites,
806 'newpost',
807 $post_data,
808 array(
809 MainWP_Bulk_Add::get_class_name(),
810 'posting_bulk_handler',
811 ),
812 $output
813 );
814 }
815
816 foreach ( $dbwebsites as $website ) {
817 if ( isset( $output->ok[ $website->id ] ) && ( 1 === (int) $output->ok[ $website->id ] ) && ( isset( $output->added_id[ $website->id ] ) ) ) {
818 $links = isset( $output->link[ $website->id ] ) ? $output->link[ $website->id ] : null;
819 do_action_deprecated( 'mainwp-post-posting-post', array( $website, $output->added_id[ $website->id ], $links ), '4.0.7.2', 'mainwp_post_posting_post' ); // @deprecated Use 'mainwp_post_posting_page' instead. NOSONAR - not IP.
820 do_action_deprecated( 'mainwp-bulkposting-done', array( $_post, $website, $output ), '4.0.7.2', 'mainwp_bulkposting_done' ); // @deprecated Use 'mainwp_bulkposting_done' instead. NOSONAR - not IP.
821
822 /**
823 * Posting post
824 *
825 * Fires while posting post.
826 *
827 * @param object $website Object containing child site data.
828 * @param int $output->added_id[ $website->id ] Child site ID.
829 * @param array $links Links.
830 *
831 * @since Unknown
832 */
833 do_action( 'mainwp_post_posting_post', $website, $output->added_id[ $website->id ], $links );
834
835 /**
836 * Posting post completed
837 *
838 * Fires after the post posting process is completed.
839 *
840 * @param array $_post Array containing the post data.
841 * @param object $website Object containing child site data.
842 * @param array $output Output data.
843 *
844 * @since Unknown
845 */
846 do_action( 'mainwp_bulkposting_done', $_post, $website, $output );
847 }
848 }
849
850 /**
851 * After posting a new post
852 *
853 * Sets data after the posting process to show the process feedback.
854 *
855 * @param array $_post Array containing the post data.
856 * @param array $dbwebsites Array containing processed sites.
857 * @param array $output Output data.
858 *
859 * @since Unknown
860 */
861 $newExtensions = apply_filters_deprecated( 'mainwp-after-posting-bulkpost-result', array( false, $_post, $dbwebsites, $output ), '4.0.7.2', 'mainwp_after_posting_bulkpost_result' ); // NOSONAR - not IP.
862
863 $after_posting = false;
864 if ( 'posting' === $what ) {
865 // supported for bulk posting, not for ajax posting.
866 $after_posting = apply_filters( 'mainwp_after_posting_bulkpost_result', $newExtensions, $_post, $dbwebsites, $output );
867 }
868
869 $posting_succeed = false;
870
871 if ( false === $after_posting ) {
872 if ( 'posting' === $what ) {
873 ?>
874 <div class="ui relaxed list">
875 <?php
876 foreach ( $dbwebsites as $website ) {
877 ?>
878 <div class="item"><a href="<?php echo esc_url( admin_url( 'admin.php?page=managesites&dashboard=' . $website->id ) ); ?>"><?php echo esc_html( stripslashes( $website->name ) ); ?></a>
879 :
880 <?php
881 if ( isset( $output->ok[ $website->id ] ) && 1 === (int) $output->ok[ $website->id ] ) {
882 echo esc_html( $succes_message ) . ' <a href="' . esc_html( $output->link[ $website->id ] ) . '" class="mainwp-may-hide-referrer" target="_blank">View Post</a>';
883 $posting_succeed = true;
884 } else {
885 echo $output->errors[ $website->id ]; // phpcs:ignore WordPress.Security.EscapeOutput
886 }
887 ?>
888 </div>
889 <?php } ?>
890 </div>
891 <?php } ?>
892 <?php
893 } else {
894 $posting_succeed = true;
895 }
896
897 $ajax_result = '';
898 if ( 'ajax_posting' === $what ) {
899 if ( isset( $output->ok[ $website->id ] ) && 1 === (int) $output->ok[ $website->id ] ) {
900 $ajax_result = esc_html( $succes_message ) . ' <a href="' . esc_html( $output->link[ $website->id ] ) . '" class="mainwp-may-hide-referrer" target="_blank">View Post</a>';
901 $posting_succeed = true;
902 } else {
903 $ajax_result = $output->errors[ $website->id ];
904 }
905 }
906
907 $delete_bulk_post = apply_filters( 'mainwp_after_posting_delete_bulk_post', true, $posting_succeed );
908 $do_not_del = get_post_meta( $id, '_bulkpost_do_not_del', true );
909
910 $last_ajax_posting = false;
911 if ( 'ajax_posting' === $what ) {
912 // phpcs:disable WordPress.Security.NonceVerification,WordPress.Security.ValidatedSanitizedInput.InputNotSanitized
913 $delete_bulkpost = isset( $_POST['delete_bulkpost'] ) && ! empty( $_POST['delete_bulkpost'] ) ? true : false;
914 // phpcs:enable
915 if ( $delete_bulkpost ) {
916 $last_ajax_posting = true;
917 }
918 }
919
920 $deleted_bulk_post = false;
921 if ( 'yes' !== $do_not_del && $delete_bulk_post && ( 'posting' === $what || $last_ajax_posting ) ) {
922 wp_delete_post( $id, true );
923 $deleted_bulk_post = true;
924 }
925
926 $edit_link = '';
927 if ( ! $deleted_bulk_post ) {
928 if ( 'posting' === $what ) {
929 ?>
930 <div class="item">
931 <a href="<?php echo esc_url( admin_url( 'admin.php?page=PostBulkEdit&post_id=' . $id ) ); ?>"><?php esc_html_e( 'Edit Post', 'mainwp' ); ?></a>
932 </div>
933 <?php
934 } elseif ( $last_ajax_posting ) {
935 $edit_link = '<div class="item"><a href="' . esc_url( admin_url( 'admin.php?page=PostBulkEdit&post_id=' . $id ) ) . '">' . esc_html__( 'Edit Post', 'mainwp' ) . '</a></div>';
936 }
937 }
938
939 if ( 'ajax_posting' === $what ) {
940 die(
941 wp_json_encode(
942 array(
943 'result' => $ajax_result,
944 'edit_link' => $edit_link,
945 )
946 )
947 );
948 }
949 }
950 }
951 }
952
953 /**
954 * Method get_post()
955 *
956 * Get post from child site to edit.
957 *
958 * @uses \MainWP\Dashboard\MainWP_Connect::fetch_url_authed()
959 * @uses \MainWP\Dashboard\MainWP_Error_Helper::get_error_message()
960 * @uses \MainWP\Dashboard\MainWP_DB::get_websites_by_id()
961 * @uses \MainWP\Dashboard\MainWP_Exception
962 * @uses \MainWP\Dashboard\MainWP_System_Utility::can_edit_website()
963 */
964 public static function get_post() { //phpcs:ignore -- NOSONAR - complex.
965 // phpcs:disable WordPress.Security.NonceVerification,WordPress.Security.ValidatedSanitizedInput.InputNotSanitized
966 $postId = isset( $_POST['postId'] ) ? intval( $_POST['postId'] ) : false;
967 $postType = isset( $_POST['postType'] ) ? sanitize_text_field( wp_unslash( $_POST['postType'] ) ) : '';
968 $websiteId = isset( $_POST['websiteId'] ) ? intval( $_POST['websiteId'] ) : false;
969 $replaceadvImg = isset( $_POST['replace_advance_img'] ) && ! empty( $_POST['replace_advance_img'] ) ? true : false;
970 // phpcs:enable
971 if ( empty( $postId ) || empty( $websiteId ) ) {
972 die( wp_json_encode( array( 'error' => 'Post ID or site ID not found. Please, reload the page and try again.' ) ) );
973 }
974
975 $website = MainWP_DB::instance()->get_website_by_id( $websiteId );
976 if ( ! MainWP_System_Utility::can_edit_website( $website ) ) {
977 die( wp_json_encode( array( 'error' => 'You can not edit this website!' ) ) );
978 }
979
980 try {
981 $information = MainWP_Connect::fetch_url_authed(
982 $website,
983 'post_action',
984 array(
985 'action' => 'get_edit',
986 'id' => $postId,
987 'post_type' => $postType,
988 )
989 );
990
991 } catch ( MainWP_Exception $e ) {
992 die( wp_json_encode( array( 'error' => MainWP_Error_Helper::get_error_message( $e ) ) ) );
993 }
994
995 if ( is_array( $information ) && isset( $information['error'] ) ) {
996 die( wp_json_encode( array( 'error' => esc_html( $information['error'] ) ) ) );
997 }
998
999 if ( ! isset( $information['status'] ) || ( 'SUCCESS' !== $information['status'] ) ) {
1000 die( wp_json_encode( array( 'error' => 'Unexpected error.' ) ) );
1001 } else {
1002 $ret = static::new_post( $information['my_post'], $replaceadvImg, $website );
1003 if ( is_array( $ret ) && isset( $ret['id'] ) ) {
1004 // to support edit post.
1005 update_post_meta( $ret['id'], '_selected_sites', array( $websiteId ) );
1006 update_post_meta( $ret['id'], '_mainwp_edit_post_site_id', $websiteId );
1007 }
1008 $ret = apply_filters( 'mainwp_manageposts_get_post_result', $ret, $information['my_post'], $websiteId );
1009 wp_send_json( $ret );
1010 }
1011 }
1012
1013 /**
1014 * Method new_post()
1015 *
1016 * Create new post.
1017 *
1018 * @param array $post_data Array of post data.
1019 * @param bool $replaceadvImg replace advanced images of post or not.
1020 * @param mixed $website The website object.
1021 *
1022 * @return array result
1023 */
1024 public static function new_post( $post_data = array(), $replaceadvImg = false, $website = false ) {
1025 $new_post = json_decode( base64_decode( $post_data['new_post'] ), true ); // phpcs:ignore WordPress.PHP.DiscouragedPHPFunctions -- base64_encode used for http encoding compatible.
1026 $post_custom = json_decode( base64_decode( $post_data['post_custom'] ), true ); // phpcs:ignore WordPress.PHP.DiscouragedPHPFunctions -- base64_encode used for http encoding compatible.
1027 $post_category = isset( $post_data['post_category'] ) ? rawurldecode( base64_decode( $post_data['post_category'] ) ) : ''; // phpcs:ignore WordPress.PHP.DiscouragedPHPFunctions -- base64_encode used for http encoding compatible.
1028 $post_tags = isset( $new_post['post_tags'] ) ? rawurldecode( $new_post['post_tags'] ) : '';
1029 $post_featured_image = base64_decode( $post_data['post_featured_image'] ); // phpcs:ignore WordPress.PHP.DiscouragedPHPFunctions -- base64_encode used for http encoding compatible.
1030 $upload_dir = json_decode( base64_decode( $post_data['child_upload_dir'] ), true ); // phpcs:ignore WordPress.PHP.DiscouragedPHPFunctions -- base64_encode used for http encoding compatible.
1031 $post_gallery_images = base64_decode( $post_data['post_gallery_images'] ); // phpcs:ignore WordPress.PHP.DiscouragedPHPFunctions -- base64_encode used for http encoding compatible.
1032 return static::create_post( $new_post, $post_custom, $post_category, $post_featured_image, $upload_dir, $post_tags, $post_gallery_images, $replaceadvImg, $website );
1033 }
1034
1035 /**
1036 * Method create_post()
1037 *
1038 * Create post.
1039 *
1040 * @param mixed $new_post Post type.
1041 * @param mixed $post_custom Custom Post.
1042 * @param mixed $post_category Post Category.
1043 * @param mixed $post_featured_image Post Featured Image.
1044 * @param mixed $upload_dir Child Site upload directory.
1045 * @param mixed $post_tags Post tags.
1046 * @param mixed $post_gallery_images Post Gallery Images.
1047 * @param bool $replaceadvImg replace advanced images of post or not.
1048 * @param mixed $website The website object.
1049 *
1050 * @return array result
1051 */
1052 public static function create_post( $new_post, $post_custom, $post_category, $post_featured_image, $upload_dir, $post_tags, $post_gallery_images, $replaceadvImg = false, $website = false ) { // phpcs:ignore -- NOSONAR - complex method. Current complexity is the only way to achieve desired results, pull request solutions appreciated.
1053
1054 /**
1055 * Current user global.
1056 *
1057 * @global string
1058 */
1059 global $current_user;
1060
1061 if ( ! isset( $new_post['edit_id'] ) ) {
1062 return array( 'error' => 'Empty post id' );
1063 }
1064
1065 $post_author = $current_user->ID;
1066 $new_post['post_author'] = $post_author;
1067 $post_type = isset( $new_post['post_type'] ) ? $new_post['post_type'] : '';
1068 $new_post['post_type'] = 'page' === $post_type ? 'bulkpage' : 'bulkpost';
1069
1070 $foundMatches = preg_match_all( '/(<a[^>]+href=\"(.*?)\"[^>]*>)?(<img[^>\/]*src=\"((.*?)(png|gif|jpg|jpeg))\")/ix', $new_post['post_content'], $matches, PREG_SET_ORDER );
1071 if ( 0 < $foundMatches ) {
1072 foreach ( $matches as $match ) {
1073 $hrefLink = $match[2];
1074 $imgUrl = $match[4];
1075
1076 if ( ! isset( $upload_dir['baseurl'] ) || ( false === strripos( $imgUrl, $upload_dir['baseurl'] ) ) ) { // url of image is not in child site.
1077 continue;
1078 }
1079
1080 if ( preg_match( '/-\d{3}x\d{3}\.[a-zA-Z0-9]{3,4}$/', $imgUrl, $imgMatches ) ) {
1081 $search = $imgMatches[0];
1082 $replace = '.' . $match[6];
1083 $originalImgUrl = str_replace( $search, $replace, $imgUrl );
1084 } else {
1085 $originalImgUrl = $imgUrl;
1086 }
1087
1088 try {
1089 $downloadfile = static::upload_image( $originalImgUrl );
1090 $localUrl = $downloadfile['url'];
1091
1092 $linkToReplaceWith = dirname( $localUrl );
1093 if ( '' !== $hrefLink ) {
1094 $server = $website->url;
1095 $serverHost = wp_parse_url( $server, PHP_URL_HOST );
1096 if ( ! empty( $serverHost ) && false !== strpos( $hrefLink, $serverHost ) ) {
1097 $serverHref = 'href="' . $serverHost;
1098 $replaceServerHref = 'href="' . wp_parse_url( $localUrl, PHP_URL_SCHEME ) . '://' . wp_parse_url( $localUrl, PHP_URL_HOST );
1099 $new_post['post_content'] = str_replace( $serverHref, $replaceServerHref, $new_post['post_content'] );
1100 }
1101 }
1102 $lnkToReplace = dirname( $imgUrl );
1103 if ( 'http:' !== $lnkToReplace && 'https:' !== $lnkToReplace ) {
1104 $new_post['post_content'] = str_replace( $imgUrl, $localUrl, $new_post['post_content'] ); // replace src image.
1105 $new_post['post_content'] = str_replace( $lnkToReplace, $linkToReplaceWith, $new_post['post_content'] );
1106 }
1107 } catch ( \Exception $e ) {
1108 // ok.
1109 }
1110 }
1111 }
1112
1113 if ( has_shortcode( $new_post['post_content'], 'gallery' ) && preg_match_all( '/\[gallery[^\]]+ids=\"(.*?)\"[^\]]*\]/ix', $new_post['post_content'], $matches, PREG_SET_ORDER ) ) {
1114 $replaceAttachedIds = array();
1115 if ( is_array( $post_gallery_images ) ) {
1116 foreach ( $post_gallery_images as $gallery ) {
1117 if ( isset( $gallery['src'] ) ) {
1118 try {
1119 $upload = static::upload_image( $gallery['src'], $gallery, true );
1120 if ( null !== $upload ) {
1121 $replaceAttachedIds[ $gallery['id'] ] = $upload['id'];
1122 }
1123 } catch ( \Exception $e ) {
1124 // ok.
1125 }
1126 }
1127 }
1128 }
1129 if ( ! empty( $replaceAttachedIds ) ) {
1130 foreach ( $matches as $match ) {
1131 $idsToReplace = $match[1];
1132 $idsToReplaceWith = '';
1133 $originalIds = explode( ',', $idsToReplace );
1134 foreach ( $originalIds as $attached_id ) {
1135 if ( ! empty( $originalIds ) && isset( $replaceAttachedIds[ $attached_id ] ) ) {
1136 $idsToReplaceWith .= $replaceAttachedIds[ $attached_id ] . ',';
1137 }
1138 }
1139 $idsToReplaceWith = rtrim( $idsToReplaceWith, ',' );
1140 if ( ! empty( $idsToReplaceWith ) ) {
1141 $new_post['post_content'] = str_replace( '"' . $idsToReplace . '"', '"' . $idsToReplaceWith . '"', $new_post['post_content'] );
1142 }
1143 }
1144 }
1145 }
1146
1147 if ( $replaceadvImg && $website ) {
1148 $new_post['post_content'] = static::replace_advanced_image( $new_post['post_content'], $upload_dir, $website );
1149 $new_post['post_content'] = static::replace_advanced_image( $new_post['post_content'], $upload_dir, $website, true ); // to fix images url with slashes.
1150 }
1151
1152 $is_sticky = false;
1153 if ( isset( $new_post['is_sticky'] ) ) {
1154 $is_sticky = ! empty( $new_post['is_sticky'] ) ? true : false;
1155 unset( $new_post['is_sticky'] );
1156 }
1157 $edit_id = $new_post['edit_id'];
1158 unset( $new_post['edit_id'] );
1159
1160 if ( isset( $new_post['post_title'] ) ) {
1161 $new_post['post_title'] = MainWP_Utility::esc_content( $new_post['post_title'], 'mixed' );
1162 }
1163
1164 $wp_error = null;
1165 remove_filter( 'content_save_pre', 'wp_filter_post_kses' );
1166 $post_status = $new_post['post_status'];
1167 $new_post['post_status'] = 'auto-draft';
1168 $new_post_id = wp_insert_post( $new_post, $wp_error );
1169
1170 if ( is_wp_error( $wp_error ) ) {
1171 return array( 'error' => $wp_error->get_error_message() );
1172 }
1173
1174 if ( empty( $new_post_id ) ) {
1175 return array( 'error' => 'Undefined error' );
1176 }
1177
1178 wp_update_post(
1179 array(
1180 'ID' => $new_post_id,
1181 'post_status' => $post_status,
1182 )
1183 );
1184
1185 foreach ( $post_custom as $meta_key => $meta_values ) {
1186 foreach ( $meta_values as $meta_value ) {
1187 update_post_meta( $new_post_id, $meta_key, $meta_value );
1188 }
1189 }
1190
1191 update_post_meta( $new_post_id, '_mainwp_edit_post_id', $edit_id );
1192 update_post_meta( $new_post_id, '_slug', base64_encode( $new_post['post_name'] ) ); // phpcs:ignore WordPress.PHP.DiscouragedPHPFunctions -- base64_encode used for http encoding compatible.
1193 if ( isset( $post_category ) && '' !== $post_category ) {
1194 update_post_meta( $new_post_id, '_categories', base64_encode( $post_category ) ); // phpcs:ignore WordPress.PHP.DiscouragedPHPFunctions -- base64_encode used for http encoding compatible.
1195 }
1196
1197 if ( isset( $post_tags ) && '' !== $post_tags ) {
1198 update_post_meta( $new_post_id, '_tags', base64_encode( $post_tags ) ); // phpcs:ignore WordPress.PHP.DiscouragedPHPFunctions -- base64_encode used for http encoding compatible.
1199 }
1200 if ( $is_sticky ) {
1201 update_post_meta( $new_post_id, '_sticky', base64_encode( 'sticky' ) ); // phpcs:ignore WordPress.PHP.DiscouragedPHPFunctions -- base64_encode used for http encoding compatible.
1202 }
1203
1204 if ( ! empty( $post_featured_image ) ) {
1205 try {
1206 $upload = static::upload_image( $post_featured_image );
1207
1208 if ( null !== $upload ) {
1209 update_post_meta( $new_post_id, '_thumbnail_id', $upload['id'] );
1210 }
1211 } catch ( \Exception $e ) {
1212 // ok.
1213 error_log($e->getMessage()); //phpcs:ignore -- NOSONAR - debugging.
1214 }
1215 }
1216
1217 $ret = array();
1218 $ret['success'] = true;
1219 $ret['id'] = $new_post_id;
1220 return $ret;
1221 }
1222
1223 /**
1224 * Method replace_advanced_image()
1225 *
1226 * Handle upload advanced image.
1227 *
1228 * @param array $content post content data.
1229 * @param array $upload_dir upload directory info.
1230 * @param mixed $website The website.
1231 * @param bool $withslashes to use preg pattern with slashes.
1232 *
1233 * @return mixed array of result.
1234 */
1235 public static function replace_advanced_image( $content, $upload_dir, $website, $withslashes = false ) { //phpcs:ignore -- NOSONAR - complex.
1236
1237 if ( empty( $upload_dir ) || ! isset( $upload_dir['baseurl'] ) ) {
1238 return $content;
1239 }
1240
1241 $dashboard_url = get_site_url();
1242 $site_url_source = $website->url;
1243
1244 // to fix url with slashes.
1245 if ( $withslashes ) {
1246 $site_url_source = str_replace( '/', '\/', $site_url_source );
1247 $dashboard_url = str_replace( '/', '\/', $dashboard_url );
1248 }
1249
1250 $foundMatches = preg_match_all( '#(' . preg_quote( $site_url_source, null ) . ')[^\.]*(\.(png|gif|jpg|jpeg))#ix', $content, $matches, PREG_SET_ORDER ); // phpcs:ignore -- NOSONAR -Current complexity.
1251
1252 if ( 0 < $foundMatches ) {
1253
1254 $matches_checked = array();
1255 $check_double = array();
1256 foreach ( $matches as $match ) {
1257 // to avoid double images.
1258 if ( ! in_array( $match[0], $check_double ) ) {
1259 $check_double[] = $match[0];
1260 $matches_checked[] = $match;
1261 }
1262 }
1263 foreach ( $matches_checked as $match ) {
1264
1265 $imgUrl = $match[0];
1266 if ( false === strripos( wp_unslash( $imgUrl ), $upload_dir['baseurl'] ) ) {
1267 continue;
1268 }
1269
1270 if ( preg_match( '/-\d{3}x\d{3}\.[a-zA-Z0-9]{3,4}$/', $imgUrl, $imgMatches ) ) {
1271 $search = $imgMatches[0];
1272 $replace = '.' . $match[3];
1273 $originalImgUrl = str_replace( $search, $replace, $imgUrl );
1274 } else {
1275 $originalImgUrl = $imgUrl;
1276 }
1277
1278 try {
1279 $downloadfile = static::upload_image( wp_unslash( $originalImgUrl ) );
1280 $localUrl = $downloadfile['url'];
1281 $linkToReplaceWith = dirname( $localUrl );
1282 $lnkToReplace = dirname( $imgUrl );
1283 if ( 'http:' !== $lnkToReplace && 'https:' !== $lnkToReplace ) {
1284 $content = str_replace( $imgUrl, $localUrl, $content ); // replace src image.
1285 $content = str_replace( $lnkToReplace, $linkToReplaceWith, $content );
1286 }
1287 } catch ( \Exception $e ) {
1288 // ok.
1289 }
1290 }
1291 if ( false === strripos( $site_url_source, $dashboard_url ) ) {
1292 // replace other images src outside upload folder.
1293 $content = str_replace( $site_url_source, $dashboard_url, $content );
1294 }
1295 }
1296 return $content;
1297 }
1298
1299 /**
1300 * Method upload_image()
1301 *
1302 * Handle upload image.
1303 *
1304 * @throws \MainWP_Exception Error upload file.
1305 *
1306 * @param string $img_url URL for the image.
1307 * @param array $img_data Array of image data.
1308 *
1309 * @return mixed array of result or null.
1310 *
1311 * @uses \MainWP\Dashboard\MainWP_System_Utility::get_wp_file_system()
1312 */
1313 public static function upload_image( $img_url, $img_data = array() ) { //phpcs:ignore -- NOSONAR - complex.
1314 if ( ! is_array( $img_data ) ) {
1315 $img_data = array();
1316 }
1317 include_once ABSPATH . 'wp-admin/includes/file.php'; // NOSONAR - WP compatible.
1318 $temporary_file = download_url( $img_url );
1319
1320 if ( is_wp_error( $temporary_file ) ) {
1321 throw new MainWP_Exception( 'Error: ' . $temporary_file->get_error_message() ); //phpcs:ignore WordPress.Security.EscapeOutput.ExceptionNotEscaped
1322 } else {
1323 $upload_dir = wp_upload_dir();
1324 $local_img_path = $upload_dir['path'] . DIRECTORY_SEPARATOR . basename( $img_url );
1325 $local_img_url = $upload_dir['url'] . '/' . basename( $img_url );
1326 $moved = false;
1327 if ( MainWP_Utility::check_image_file_name( $local_img_path ) ) {
1328 global $wp_filesystem;
1329 if ( $wp_filesystem ) {
1330 $moved = $wp_filesystem->move( $temporary_file, $local_img_path, true );
1331 }
1332 }
1333 if ( $moved ) {
1334 $wp_filetype = wp_check_filetype( basename( $img_url ), null );
1335 $attachment = array(
1336 'post_mime_type' => $wp_filetype['type'],
1337 'post_title' => isset( $img_data['title'] ) && ! empty( $img_data['title'] ) ? $img_data['title'] : preg_replace( '/\.[^.]+$/', '', basename( $img_url ) ),
1338 'post_content' => isset( $img_data['description'] ) && ! empty( $img_data['description'] ) ? $img_data['description'] : '',
1339 'post_excerpt' => isset( $img_data['caption'] ) && ! empty( $img_data['caption'] ) ? MainWP_Utility::esc_content( $img_data['caption'] ) : '',
1340 'post_status' => 'inherit',
1341 );
1342 $attach_id = wp_insert_attachment( $attachment, $local_img_path );
1343 require_once ABSPATH . 'wp-admin/includes/image.php'; // NOSONAR - WP compatible.
1344 $attach_data = wp_generate_attachment_metadata( $attach_id, $local_img_path );
1345 wp_update_attachment_metadata( $attach_id, $attach_data );
1346 if ( isset( $img_data['alt'] ) && ! empty( $img_data['alt'] ) ) {
1347 update_post_meta( $attach_id, '_wp_attachment_image_alt', $img_data['alt'] );
1348 }
1349 return array(
1350 'id' => $attach_id,
1351 'url' => $local_img_url,
1352 );
1353 }
1354 }
1355
1356 MainWP_System_Utility::get_wp_file_system();
1357
1358 /**
1359 * WordPress files system object.
1360 *
1361 * @global object
1362 */
1363 global $wp_filesystem;
1364
1365 if ( $wp_filesystem->exists( $temporary_file ) ) {
1366 $wp_filesystem->delete( $temporary_file );
1367 }
1368
1369 return null;
1370 }
1371
1372 /**
1373 * Method add_sticky_handle()
1374 *
1375 * Add post meta.
1376 *
1377 * @param mixed $post_id Post ID.
1378 *
1379 * @return int $post_id Post ID.
1380 */
1381 public static function add_sticky_handle( $post_id ) {
1382 $_post = get_post( $post_id );
1383 // phpcs:disable WordPress.Security.NonceVerification,WordPress.Security.ValidatedSanitizedInput.InputNotSanitized
1384 if ( 'bulkpost' === $_post->post_type && isset( $_POST['sticky'] ) ) {
1385 update_post_meta( $post_id, '_sticky', base64_encode( sanitize_text_field( wp_unslash( $_POST['sticky'] ) ) ) ); // phpcs:ignore WordPress.PHP.DiscouragedPHPFunctions -- base64_encode used for http encoding compatible.
1386 return base64_encode( sanitize_text_field( wp_unslash( $_POST['sticky'] ) ) ); // phpcs:ignore WordPress.PHP.DiscouragedPHPFunctions -- base64_encode used for http encoding compatible.
1387 }
1388 // phpcs:enable
1389 return $post_id;
1390 }
1391
1392
1393 /**
1394 * Method add_status_handle()
1395 *
1396 * Add edit post status handle.
1397 *
1398 * @param int $post_id Post ID.
1399 *
1400 * @return int $post_id Post id with status handle added to it.
1401 */
1402 public static function add_status_handle( $post_id ) {
1403 $_post = get_post( $post_id );
1404 // phpcs:disable WordPress.Security.NonceVerification,WordPress.Security.ValidatedSanitizedInput.InputNotSanitized
1405 if ( ( 'bulkpage' === $_post->post_type || 'bulkpost' === $_post->post_type ) && isset( $_POST['mainwp_edit_post_status'] ) ) {
1406 update_post_meta( $post_id, '_edit_post_status', sanitize_text_field( wp_unslash( $_POST['mainwp_edit_post_status'] ) ) );
1407 }
1408 // phpcs:enable
1409 return $post_id;
1410 }
1411 }
1412