PluginProbe
MainWP Dashboard: Self-hosted WordPress Management for Agencies / 6.1.7
MainWP Dashboard: Self-hosted WordPress Management for Agencies v6.1.7
6.2.3 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 All 156 releases
mainwp / pages / page-mainwp-post-page-handler.php

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

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