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