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