Changeset 1681551
- Timestamp:
- 06/19/2017 11:32:15 PM (9 years ago)
- Location:
- stackcommerce-connect/trunk
- Files:
-
- 2 added
- 11 edited
-
css/stackcommerce-wp-settings.css (modified) (2 diffs)
-
includes/class-stackcommerce-wp-article.php (modified) (10 diffs)
-
includes/class-stackcommerce-wp-endpoint.php (modified) (3 diffs)
-
includes/class-stackcommerce-wp-search.php (added)
-
includes/class-stackcommerce-wp-settings.php (modified) (10 diffs)
-
includes/class-stackcommerce-wp.php (modified) (5 diffs)
-
index.php (modified) (1 diff)
-
js/stackcommerce-wp-settings.js (modified) (5 diffs)
-
readme.txt (modified) (3 diffs)
-
uninstall.php (modified) (1 diff)
-
version.txt (modified) (1 diff)
-
views/stackcommerce-wp-js.php (added)
-
views/stackcommerce-wp-page-settings.php (modified) (1 diff)
Legend:
- Unmodified
- Added
- Removed
-
stackcommerce-connect/trunk/css/stackcommerce-wp-settings.css
r1659819 r1681551 6 6 } 7 7 8 .stackcommerce-wp-form[data-stackcommerce-wp-status='disconnected'] .stackcommerce-wp-section .form-table:last-child tr:nth-child(2), 9 .stackcommerce-wp-form[data-stackcommerce-wp-status='disconnected'] .stackcommerce-wp-section .form-table:last-child tr:nth-child(3), 10 .stackcommerce-wp-form[data-stackcommerce-wp-status='disconnected'] .stackcommerce-wp-section .form-table:last-child tr:nth-child(4), 11 .stackcommerce-wp-form[data-stackcommerce-wp-status='disconnected'] .stackcommerce-wp-section .form-table:last-child tr:nth-child(5), 8 .stackcommerce-wp-form[data-stackcommerce-wp-status='disconnected'] .form-table:last-child tr:nth-child(1), 9 .stackcommerce-wp-form[data-stackcommerce-wp-status='disconnected'] .form-table:last-child tr:nth-child(2), 10 .stackcommerce-wp-form[data-stackcommerce-wp-status='disconnected'] .form-table:last-child tr:nth-child(3), 11 .stackcommerce-wp-form[data-stackcommerce-wp-status='disconnected'] .form-table:last-child tr:nth-child(4), 12 .stackcommerce-wp-form[data-stackcommerce-wp-status='disconnected'] .form-table:last-child tr:nth-child(5), 13 .stackcommerce-wp-form[data-stackcommerce-wp-status=''] .stackcommerce-wp-section .form-table:last-child tr:nth-child(1), 12 14 .stackcommerce-wp-form[data-stackcommerce-wp-status=''] .stackcommerce-wp-section .form-table:last-child tr:nth-child(2), 13 15 .stackcommerce-wp-form[data-stackcommerce-wp-status=''] .stackcommerce-wp-section .form-table:last-child tr:nth-child(3), 14 16 .stackcommerce-wp-form[data-stackcommerce-wp-status=''] .stackcommerce-wp-section .form-table:last-child tr:nth-child(4), 15 .stackcommerce-wp-form[data-stackcommerce-wp-status=''] .stackcommerce-wp-section .form-table:last-child tr:nth-child(5) { 17 .stackcommerce-wp-form[data-stackcommerce-wp-status=''] .stackcommerce-wp-section .form-table:last-child tr:nth-child(5), 18 .stackcommerce-wp-form[data-stackcommerce-wp-content-integration='false'] .stackcommerce-wp-section .form-table:last-child tr:nth-child(1), 19 .stackcommerce-wp-form[data-stackcommerce-wp-content-integration='false'] .stackcommerce-wp-section .form-table:last-child tr:nth-child(2), 20 .stackcommerce-wp-form[data-stackcommerce-wp-content-integration='false'] .stackcommerce-wp-section .form-table:last-child tr:nth-child(3), 21 .stackcommerce-wp-form[data-stackcommerce-wp-content-integration='false'] .stackcommerce-wp-section .form-table:last-child tr:nth-child(4), 22 .stackcommerce-wp-form[data-stackcommerce-wp-content-integration='false'] .stackcommerce-wp-section .form-table:last-child tr:nth-child(5) { 16 23 display: none; 24 } 25 26 .stackcommerce-wp-form[data-stackcommerce-wp-content-integration='true'] .stackcommerce-wp-section .form-table:last-child tr:nth-child(1), 27 .stackcommerce-wp-form[data-stackcommerce-wp-content-integration='true'] .stackcommerce-wp-section .form-table:last-child tr:nth-child(2), 28 .stackcommerce-wp-form[data-stackcommerce-wp-content-integration='true'] .stackcommerce-wp-section .form-table:last-child tr:nth-child(3), 29 .stackcommerce-wp-form[data-stackcommerce-wp-content-integration='true'] .stackcommerce-wp-section .form-table:last-child tr:nth-child(4), 30 .stackcommerce-wp-form[data-stackcommerce-wp-content-integration='true'] .stackcommerce-wp-section .form-table:last-child tr:nth-child(5) { 31 display: table-row !important; 17 32 } 18 33 … … 44 59 .stackcommerce-wp-status-icon-connecting { 45 60 background-image: url('../images/connecting.svg'); 46 /*background-image: url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAzMiAzMiIgd2lkdGg9IjMyIiBoZWlnaHQ9IjMyIiBmaWxsPSIjOTk5OTk5Ij4gIDxwYXRoIG9wYWNpdHk9Ii4yNSIgZD0iTTE2IDAgQTE2IDE2IDAgMCAwIDE2IDMyIEExNiAxNiAwIDAgMCAxNiAwIE0xNiA0IEExMiAxMiAwIDAgMSAxNiAyOCBBMTIgMTIgMCAwIDEgMTYgNCIvPiAgPHBhdGggZD0iTTE2IDAgQTE2IDE2IDAgMCAxIDMyIDE2IEwyOCAxNiBBMTIgMTIgMCAwIDAgMTYgNHoiPiAgICA8YW5pbWF0ZVRyYW5zZm9ybSBhdHRyaWJ1dGVOYW1lPSJ0cmFuc2Zvcm0iIHR5cGU9InJvdGF0ZSIgZnJvbT0iMCAxNiAxNiIgdG89IjM2MCAxNiAxNiIgZHVyPSIwLjhzIiByZXBlYXRDb3VudD0iaW5kZWZpbml0ZSIgLz4gIDwvcGF0aD48L3N2Zz4=);*/47 61 } 48 62 -
stackcommerce-connect/trunk/includes/class-stackcommerce-wp-article.php
r1659819 r1681551 22 22 $errors = array(); 23 23 24 if( strlen( wp_strip_all_tags( $fields['post_title'] ) ) == 0 ) {25 array_push( $errors, ' Post title field cannot be empty.' );26 } 27 28 if( strlen( $fields['post_content'] ) == 0 ) {29 array_push( $errors, ' Post content field cannot be empty.' );24 if( ! array_key_exists( 'post_title', $fields ) || strlen( wp_strip_all_tags( $fields['post_title'] ) ) == 0 ) { 25 array_push( $errors, 'Title field cannot be empty.' ); 26 } 27 28 if( ! array_key_exists( 'post_content', $fields ) || strlen( $fields['post_content'] ) == 0 ) { 29 array_push( $errors, 'Content field cannot be empty.' ); 30 30 } 31 31 … … 33 33 $this->insert( $fields ); 34 34 } else { 35 $request_errors = ' An error occurred while processing your request.';35 $request_errors = ''; 36 36 37 37 foreach( $errors as $error ) { … … 39 39 } 40 40 41 $stackcommerce_wp_endpoint->response( $request_errors, false, '400' ); 41 return $stackcommerce_wp_endpoint->response( $request_errors, 42 array( 43 'code' => 'stackcommerce_wp_missing_fields', 44 'status_code' => 400 45 ) 46 ); 42 47 } 43 48 } … … 59 64 return $post_status[$post_status_option]; 60 65 break; 66 case 'post_categories': 67 return get_option( 'stackcommerce_wp_categories' ); 68 break; 61 69 case 'post_tags': 62 70 return get_option( 'stackcommerce_wp_tags' ); 63 case 'strip_image': 64 $strip_image = ( implode( get_option( 'stackcommerce_wp_strip_image' ) ) === 'true'); 65 66 return $strip_image; 67 break; 68 } 71 break; 72 case 'featured_image': 73 return implode( get_option( 'stackcommerce_wp_featured_image' ) ); 74 break; 75 } 76 } 77 78 /** 79 * Get categories IDs 80 * 81 * @since 1.1.0 82 */ 83 protected function get_categories_ids( $categories ) { 84 if ( empty( $categories ) ) return false; 85 86 $categories_ids = []; 87 88 foreach( $categories as $category ) { 89 $category_id = get_category_by_slug( $category ); 90 91 array_push( $categories_ids, $category_id->term_id ); 92 } 93 94 return $categories_ids; 69 95 } 70 96 … … 75 101 */ 76 102 protected function schedule_post( $post, $fields ) { 103 if( empty( $fields['post_date_gmt'] ) ) return $post; 104 77 105 $post['post_date_gmt'] = get_gmt_from_date( $fields['post_date_gmt'] ); 78 106 $post['post_status'] = 'future'; … … 82 110 83 111 /** 84 * Handle media upload and post update 85 * 86 * @since 1.0.0 87 */ 88 protected function handle_media( $post_author, $post_id, $attachment ) { 89 $media = $this->save_media( $post_author, $post_id, $attachment ); 90 91 if( $media ) { 92 return $this->update_post( $post_id, $media ); 93 } else { 94 $stackcommerce_wp_endpoint->response( 'Post created but failed to upload media', false, '400' ); 95 return false; 96 } 97 } 98 99 /** 100 * Programmatically upload and save media to WordPress library 101 * 102 * @since 1.0.0 103 */ 104 protected function save_media( $post_author, $post_id, $attachment ) { 105 $filename = basename( $attachment ); 106 $upload_file = wp_upload_bits( $filename, null, file_get_contents( $attachment ) ); 107 108 if( ! $upload_file['error'] ) { 109 $wp_filetype = wp_check_filetype( $filename, null ); 110 111 $attachment = array( 112 'post_mime_type' => $wp_filetype['type'], 113 'post_parent' => $post_id, 114 'post_title' => preg_replace( '/\.[^.]+$/', '', $filename ), 115 'post_content' => '', 116 'post_status' => 'inherit', 117 'post_author' => $post_author, 118 ); 119 120 $attachment_id = wp_insert_attachment( $attachment, $upload_file['file'], $post_id ); 121 122 if( ! is_wp_error( $attachment_id ) ) { 123 require_once( ABSPATH . 'wp-admin' . '/includes/image.php' ); 124 125 $attachment_data = wp_generate_attachment_metadata( $attachment_id, $upload_file['file'] ); 126 wp_update_attachment_metadata( $attachment_id, $attachment_data ); 127 128 return $attachment_id; 129 } else { 130 return false; 131 } 132 } else { 133 return false; 134 } 135 } 136 137 /** 138 * Update post to insert a given featured media 139 * 140 * @since 1.0.0 141 */ 142 protected function update_post( $post_id, $attachment_id ) { 112 * Returns image mime types users are allowed to upload via the API 113 * 114 * @since 1.1.0 115 * @return array 116 */ 117 protected function allowed_image_mime_types() { 118 return array( 119 'jpg|jpeg|jpe' => 'image/jpeg', 120 'gif' => 'image/gif', 121 'png' => 'image/png', 122 'bmp' => 'image/bmp', 123 'tiff|tif' => 'image/tiff', 124 'ico' => 'image/x-icon', 125 ); 126 } 127 128 /** 129 * Upload image from URL 130 * 131 * @since 1.1.0 132 * @param string $image_url 133 * @return array|StackCommerce_WP_Endpoint->response attachment data or error message 134 */ 135 protected function upload_image_from_url( $image_url ) { 136 $stackcommerce_wp_endpoint = new StackCommerce_WP_Endpoint(); 137 138 $file_name = basename( current( explode( '?', $image_url ) ) ); 139 $parsed_url = @parse_url( $image_url ); 140 141 $errors = array(); 142 143 // Check parsed URL. 144 if ( ! $parsed_url || ! is_array( $parsed_url ) ) { 145 $data = sprintf( 'Invalid URL %s', $image_url ); 146 $error_args = array( 147 'code' => 'stackcommerce_wp_invalid_image_url', 148 'status_code' => 400 149 ); 150 151 $error = array( $data, $error_args ); 152 153 $stackcommerce_wp_endpoint->response( $data, $error_args ); 154 array_push( $errors, $error ); 155 } 156 157 // Ensure url is valid 158 $safe_image_url = esc_url_raw( $image_url ); 159 160 // Get the file 161 $response = wp_safe_remote_get( $safe_image_url, array( 162 'timeout' => 20, 163 ) ); 164 165 if ( is_wp_error( $response ) ) { 166 $data = sprintf( 'Error getting remote image %s.', $image_url ) . ' ' . sprintf( 'Error: %s', $response->get_error_message() ); 167 $error_args = array( 168 'code' => 'stackcommerce_wp_invalid_remote_image_url', 169 'status_code' => 400 170 ); 171 172 $error = array( $data, $error_args ); 173 174 $stackcommerce_wp_endpoint->response( $data, $error_args ); 175 array_push( $errors, $error ); 176 } elseif ( 200 !== wp_remote_retrieve_response_code( $response ) ) { 177 $data = sprintf( 'Error getting remote image %s', $image_url ); 178 $error_args = array( 179 'code' => 'stackcommerce_wp_invalid_remote_image_url', 180 'status_code' => 400 181 ); 182 183 $error = array( $data, $error_args ); 184 185 $stackcommerce_wp_endpoint->response( $data, $error_args ); 186 array_push( $errors, $error ); 187 } 188 189 // Ensure we have a file name and type 190 $wp_filetype = wp_check_filetype( $file_name, $this->allowed_image_mime_types() ); 191 192 if ( ! $wp_filetype['type'] ) { 193 $headers = wp_remote_retrieve_headers( $response ); 194 195 if ( isset( $headers['content-disposition'] ) && strstr( $headers['content-disposition'], 'filename=' ) ) { 196 $disposition = end( explode( 'filename=', $headers['content-disposition'] ) ); 197 $disposition = sanitize_file_name( $disposition ); 198 $file_name = $disposition; 199 } elseif ( isset( $headers['content-type'] ) && strstr( $headers['content-type'], 'image/' ) ) { 200 $file_name = 'image.' . str_replace( 'image/', '', $headers['content-type'] ); 201 } 202 unset( $headers ); 203 204 // Recheck filetype 205 $wp_filetype = wp_check_filetype( $file_name, $this->allowed_image_mime_types() ); 206 207 if ( ! $wp_filetype['type'] ) { 208 $data = sprintf( 'Invalid image type: %s', $image_url ); 209 $error_args = array( 210 'code' => 'stackcommerce_wp_invalid_image_type', 211 'status_code' => 400 212 ); 213 214 $error = array( $data, $error_args ); 215 216 $stackcommerce_wp_endpoint->response( $data, $error_args ); 217 array_push( $errors, $error ); 218 } 219 } 220 221 // Upload the file 222 $upload = wp_upload_bits( $file_name, '', wp_remote_retrieve_body( $response ) ); 223 224 if ( $upload['error'] ) { 225 $data = $upload['error']; 226 $error_args = array( 227 'code' => 'stackcommerce_wp_image_upload_error', 228 'status_code' => 400 229 ); 230 231 $error = array( $data, $error_args ); 232 233 $stackcommerce_wp_endpoint->response( $data, $error_args ); 234 array_push( $errors, $error ); 235 } 236 237 // Get filesize 238 $filesize = filesize( $upload['file'] ); 239 if ( 0 == $filesize ) { 240 @unlink( $upload['file'] ); 241 unset( $upload ); 242 243 $data = sprintf( 'Zero size file downloaded: %s', $image_url ); 244 $error_args = array( 245 'code' => 'stackcommerce_wp_image_upload_file_error', 246 'status_code' => 400 247 ); 248 249 $error = array( $data, $error_args ); 250 251 $stackcommerce_wp_endpoint->response( $data, $error_args ); 252 array_push( $errors, $error ); 253 } 254 255 if ( count( $errors ) > 0 ) { 256 $upload['error'] = $errors; 257 } 258 259 return $upload; 260 } 261 262 /** 263 * Set uploaded image as attachment 264 * 265 * @since 1.1.0 266 * @param array $upload Upload information from wp_upload_bits 267 * @param int $id Post ID. Default to 0 268 * @return int Attachment ID 269 */ 270 function set_uploaded_image_as_attachment( $upload, $id = 0 ) { 271 $info = wp_check_filetype( $upload['file'] ); 272 $title = ''; 273 $content = ''; 274 $post_author = $this->get_admin_fields( 'post_author' ); 275 276 if ( ! function_exists( 'wp_generate_attachment_metadata' ) ) { 277 include_once( ABSPATH . 'wp-admin/includes/image.php' ); 278 } 279 280 if ( $image_meta = wp_read_image_metadata( $upload['file'] ) ) { 281 if ( trim( $image_meta['title'] ) && ! is_numeric( sanitize_title( $image_meta['title'] ) ) ) { 282 $title = sanitize_text_field( $image_meta['title'] ); 283 } 284 285 if ( trim( $image_meta['caption'] ) ) { 286 $content = sanitize_text_field( $image_meta['caption'] ); 287 } 288 } 289 290 $attachment = array( 291 'post_mime_type' => $info['type'], 292 'guid' => $upload['url'], 293 'post_parent' => $id, 294 'post_title' => $title, 295 'post_content' => $content, 296 'post_author' => $post_author, 297 ); 298 299 $attachment_id = wp_insert_attachment( $attachment, $upload['file'], $id ); 300 301 if ( ! is_wp_error( $attachment_id ) ) { 302 wp_update_attachment_metadata( $attachment_id, wp_generate_attachment_metadata( $attachment_id, $upload['file'] ) ); 303 } 304 305 return $attachment_id; 306 } 307 308 /** 309 * Set featured media to a post 310 * 311 * @since 1.0.0 312 */ 313 protected function set_featured_media( $attachment_id, $post_id ) { 143 314 return update_post_meta( $post_id, '_thumbnail_id', $attachment_id ); 144 315 } … … 165 336 $posts = wp_get_recent_posts( array( 'numberposts' => 1 ), ARRAY_A ); 166 337 167 $post_title = $post['post_title']; 168 $post_content = $post['post_content']; 169 $last_post_title = $posts[0]['post_title']; 170 $last_post_content = $posts[0]['post_content']; 171 172 $post_title_check = ($post_title == $last_post_title); 173 $post_content_check = ($post_content == $last_post_content); 174 175 if($post_title_check && $post_content_check) { 176 $stackcommerce_wp_endpoint->response( 'Post sent has been recently published', false, '400' ); 338 $post_title = $post['post_title'][0]; 339 $post_content = $post['post_content'][0]; 340 341 if( array_key_exists( 'post_title', $posts ) && array_key_exists( 'post_content', $posts ) ) { 342 $last_post_title = $posts[0]['post_title']; 343 $last_post_content = $posts[0]['post_content']; 344 } 345 346 if( isset( $last_post_title ) && isset( $last_post_content ) ) { 347 $post_title_check = ($post_title == $last_post_title); 348 $post_content_check = ($post_content == $last_post_content); 349 350 if( $post_title_check && $post_content_check ) { 351 return $stackcommerce_wp_endpoint->response( 'Post cannot be posted because it has been recently published', 352 array( 353 'code' => 'stackcommerce_wp_already_posted', 354 'status_code' => 400 355 ) 356 ); 357 } 177 358 } 178 359 } … … 186 367 $post = array( 187 368 'post_title' => wp_strip_all_tags( $fields['post_title'] ), 188 'post_name' => $fields['post_name'],189 369 'post_content' => $fields['post_content'], 190 'post_excerpt' => $fields['post_excerpt'], 191 'post_type' => $fields['post_type'], 370 'post_type' => 'post', 192 371 'post_author' => $this->get_admin_fields( 'post_author' ), 193 'post_status' => $this->get_admin_fields( 'post_status' ), 194 'tags_input' => $this->get_admin_fields( 'post_tags' ), 372 'post_status' => $this->get_admin_fields( 'post_status' ) 195 373 ); 196 374 375 if( array_key_exists( 'post_name', $fields ) ) { 376 $post['post_name'] = $fields['post_name']; 377 } 378 379 if( array_key_exists( 'post_excerpt', $fields ) ) { 380 $post['post_excerpt'] = $fields['post_excerpt']; 381 } 382 383 $raw_categories = $this->get_admin_fields( 'post_categories' ); 384 $raw_tags = $this->get_admin_fields( 'post_tags' ); 385 386 if( is_array( $raw_categories ) && ! empty( $raw_categories ) ) { 387 $categories = $this->get_categories_ids( $raw_categories ); 388 } 389 390 if( is_array( $raw_tags ) && ! empty( $raw_tags ) ) { 391 $tags = $raw_tags; 392 } 393 394 if( isset( $categories ) ) { 395 $post['post_category'] = $categories; 396 } 397 398 if( isset( $tags ) ) { 399 $post['tags_input'] = $tags; 400 } 401 197 402 return $post; 198 403 } … … 204 409 */ 205 410 protected function insert( $fields ) { 411 $errors = []; 206 412 $stackcommerce_wp_endpoint = new StackCommerce_WP_Endpoint(); 207 413 … … 210 416 $this->check_duplicate( $fields ); 211 417 212 if( $fields['post_date_gmt']) {418 if( array_key_exists( 'post_date_gmt', $fields ) ) { 213 419 $post = $this->schedule_post( $post, $fields ); 214 420 } 215 421 216 if( ! $this->get_admin_fields( 'strip_image' ) ) { 217 $post = $this->strip_image( $post ); 218 } 219 220 $post_insertion = wp_insert_post( $post ); 221 222 if( $post_insertion ) { 223 if( empty( $fields['featured_media'] ) ) { 224 $stackcommerce_wp_endpoint->response( $post, true ); 422 $featured_image_options = $this->get_admin_fields( 'featured_image' ); 423 424 switch( $featured_image_options ) { 425 case 'featured_image_only': 426 $post = $this->strip_image( $post ); 427 break; 428 case 'no_featured_image': 429 unset( $fields['featured_media'] ); 430 unset( $post['featured_media'] ); 431 break; 432 } 433 434 if( array_key_exists( 'featured_media', $fields ) ) { 435 $upload_image = $this->upload_image_from_url( $fields['featured_media'] ); 436 437 if( array_key_exists( 'error', $upload_image ) && ! empty( $upload_image['error'] ) ) { 438 $featured_image_errors = true; 439 } 440 } 441 442 if( ! isset( $featured_image_errors ) ) { 443 $post_id = wp_insert_post( $post ); 444 445 if( $post_id ) { 446 if( array_key_exists( 'url', $upload_image ) ) { 447 $attachment_id = $this->set_uploaded_image_as_attachment( $upload_image, $post_id ); 448 $featured_media = $this->set_featured_media( $attachment_id, $post_id ); 449 450 $post['featured_media'] = $featured_media; 451 } 452 453 return $stackcommerce_wp_endpoint->response( $post, 454 array( 455 'status_code' => 200 456 ) 457 ); 225 458 } else { 226 $handle_media = $this->handle_media( $post['post_author'], $post_insertion, $fields['featured_media'] );227 228 if( $handle_media ) {229 $post['featured_media'] = $handle_media;230 $stackcommerce_wp_endpoint->response( $post, true );231 }459 return $stackcommerce_wp_endpoint->response( 'An error occurred while creating post', 460 array( 461 'code' => 'stackcommerce_wp_post_create_error', 462 'status_code' => 400 463 ) 464 ); 232 465 } 233 } else { 234 $stackcommerce_wp_endpoint->response( 'An error occurred while processing your request', false, '400' ); 235 } 236 } 237 466 } 467 } 238 468 } -
stackcommerce-connect/trunk/includes/class-stackcommerce-wp-endpoint.php
r1659819 r1681551 21 21 global $wp; 22 22 23 $raw_sc_fields = json_decode( file_get_contents( 'php://input' ), true ); 24 $sc_hash = $_SERVER['HTTP_X_HASH'] ? $_SERVER['HTTP_X_HASH'] : ''; 23 if( isset( $wp->query_vars['sc-api-version'] ) && isset( $wp->query_vars['sc-api-route'] ) && ! empty( $wp->query_vars['sc-api-version'] ) && ! empty( $wp->query_vars['sc-api-route'] ) ) { 24 $sc_api_version = $wp->query_vars['sc-api-version']; 25 $sc_api_route = $wp->query_vars['sc-api-route']; 25 26 26 if( ! empty( $wp->query_vars['sc-api-version'] ) ) { 27 $sc_api_version = $wp->query_vars['sc-api-version']; 28 } 29 30 if( ! empty( $wp->query_vars['sc-api-route'] ) ) { 31 $sc_api_route = $wp->query_vars['sc-api-route']; 32 } 33 34 if( ! empty( $raw_sc_fields ) ) { 35 $sc_fields = $raw_sc_fields; 27 $sc_fields = json_decode( file_get_contents( 'php://input' ), true ); 28 $sc_hash = @$_SERVER['HTTP_X_HASH'] ? $_SERVER['HTTP_X_HASH'] : ''; 36 29 } 37 30 … … 48 41 49 42 /** 50 * Authentication 51 * Compares provided X-HASH value with generated hash 43 * Performs authentication and generate a hash based on post content 52 44 * 53 45 * @since 1.0.0 54 46 */ 55 47 protected function authentication( $hash, $request ) { 56 $stackcommerce_wp_article = new StackCommerce_WP_Article();57 58 48 if( ! empty( $request ) && $request['post_content'] ) { 59 49 $secret = hash_hmac( 'sha256', $request['post_content'], get_option( 'stackcommerce_wp_secret' ) ); 60 50 61 if( function_exists( 'hash_equals' ) ) { 62 63 if( ! empty( $hash ) && hash_equals( $hash, $secret ) ) { 64 $stackcommerce_wp_article->validate( $request ); 65 } else { 66 $this->response( 'Hash is missing or invalid', false, '401' ); 67 } 68 51 if( $this->is_hash_valid( $hash, $secret ) ) { 52 $stackcommerce_wp_article = new StackCommerce_WP_Article(); 53 $stackcommerce_wp_article->validate( $request ); 69 54 } else { 70 71 if( ! empty( $hash ) && $this->custom_hash_equals( $hash, $secret ) ) { 72 $stackcommerce_wp_article->validate( $request ); 73 } else { 74 $this->response( 'Hash is missing or invalid', false, '401' ); 75 } 76 55 return $this->response( 'Hash missing or invalid', 56 array( 57 'code' => 'stackcommerce_wp_invalid_hash', 58 'status_code' => 400 59 ) 60 ); 77 61 } 78 62 } else { 79 $this->response( 'Post content field cannot be empty', false ); 63 return $this->response( 'Request is empty or post content is missing', 64 array( 65 'code' => 'stackcommerce_wp_empty', 66 'status_code' => 400 67 ) 68 ); 69 } 70 } 71 72 /** 73 * Makes hash comparison 74 * 75 * @since 1.1.0 76 */ 77 protected function is_hash_valid( $hash = '', $secret ) { 78 if( function_exists( 'hash_equals' ) ) { 79 if( ! empty( $hash ) && hash_equals( $hash, $secret ) ) { 80 return true; 81 } else { 82 return false; 83 } 84 } else { 85 if( ! empty( $hash ) && $this->custom_hash_equals( $hash, $secret ) ) { 86 return true; 87 } else { 88 return false; 89 } 80 90 } 81 91 } … … 103 113 * @since 1.0.0 104 114 */ 105 public function response( $data, $success, $status_code = null ) { 106 if( $success ) { 107 $response = is_array( $data ) ? $data : array( 'message' => $data ); 115 public function response( $data, $args = array() ) { 116 if( is_array( $data ) ) { 117 $response = $data; 118 } else { 119 $response = array( 120 'message' => $data 121 ); 108 122 123 if( $args['code'] ) { 124 $code = array( 'code' => $args['code'] ); 125 $response = $code + $response; 126 } 127 } 128 129 130 if( $args['status_code'] == 200 ) { 109 131 wp_send_json_success( $response ); 110 132 } else { 111 $response = is_array( $data ) ? $data : array( 'message' => $data ); 112 113 if( $status_code ) { 114 status_header( $status_code ); 115 } 116 133 status_header( $args['status_code'] ); 117 134 wp_send_json_error( $response ); 118 135 } -
stackcommerce-connect/trunk/includes/class-stackcommerce-wp-settings.php
r1662635 r1681551 37 37 38 38 /** 39 * Get WordPress categories 40 * 41 * @since 1.1.0 42 */ 43 private function get_categories() { 44 $categories_filter = array ( 45 'hide_empty' => false 46 ); 47 48 $categories = get_categories( $categories_filter ); 49 $categories_return = array(); 50 51 foreach( $categories as $category ) { 52 $categories_return[$category->slug] = $category->name; 53 } 54 55 return $categories_return; 56 } 57 58 /** 39 59 * Get WordPress tags 40 60 * … … 73 93 add_settings_section( 74 94 'stackcommerce_wp_section_two', 95 '', 96 array( $this, 'section_callback' ), 97 'stackcommerce_wp' 98 ); 99 100 add_settings_section( 101 'stackcommerce_wp_section_three', 102 '', 103 array( $this, 'section_callback' ), 104 'stackcommerce_wp' 105 ); 106 107 add_settings_section( 108 'stackcommerce_wp_section_four', 75 109 '', 76 110 array( $this, 'section_callback' ), … … 84 118 'section' => 'stackcommerce_wp_section_one', 85 119 'type' => 'text', 120 'default' => '', 86 121 'placeholder' => '', 87 122 'helper' => '', … … 93 128 'section' => 'stackcommerce_wp_section_one', 94 129 'type' => 'password', 130 'default' => '', 95 131 'placeholder' => '', 96 132 'helper' => '', … … 102 138 'section' => 'stackcommerce_wp_section_two', 103 139 'type' => 'hidden', 140 'default' => '', 104 141 'placeholder' => '', 105 142 'helper' => '', 106 143 'supplimental' => '', 144 ), 145 array( 146 'uid' => 'stackcommerce_wp_content_integration', 147 'label' => 'Content Integration', 148 'section' => 'stackcommerce_wp_section_three', 149 'type' => 'radio', 150 'options' => array( 151 'false' => 'Off', 152 'true' => 'On', 153 ), 154 'default' => array('false'), 155 'placeholder' => '', 156 'helper' => '', 157 'supplimental' => '' 107 158 ), 108 159 array( 109 160 'uid' => 'stackcommerce_wp_author', 110 161 'label' => 'Author', 111 'section' => 'stackcommerce_wp_section_ two',162 'section' => 'stackcommerce_wp_section_four', 112 163 'type' => 'select', 113 164 'options' => $this->get_authors(), … … 120 171 'uid' => 'stackcommerce_wp_post_status', 121 172 'label' => 'Post Status', 122 'section' => 'stackcommerce_wp_section_ two',173 'section' => 'stackcommerce_wp_section_four', 123 174 'type' => 'select', 124 175 'options' => array( … … 130 181 'placeholder' => '', 131 182 'helper' => '', 132 'supplimental' => "This will be the status of the post when we send it. The schedule option allows us to identify the date and time the post will go live. The draft and pending options will require you to manually schedule the posts.", 183 'supplimental' => 'This will be the status of the post when we send it. The schedule option allows us to identify the date and time the post will go live. The draft and pending options will require you to manually schedule the posts.', 184 ), 185 array( 186 'uid' => 'stackcommerce_wp_categories', 187 'label' => 'Categories', 188 'section' => 'stackcommerce_wp_section_four', 189 'type' => 'multiselect', 190 'options' => $this->get_categories(), 191 'default' => array(), 192 'placeholder' => '', 193 'helper' => '', 194 'supplimental' => 'Categories entered in this field will be sent with <b>all</b> posts. Only enter categories you want to be applied on everything.<br />e.g. StackCommerce, Sponsored, Partners', 133 195 ), 134 196 array( 135 197 'uid' => 'stackcommerce_wp_tags', 136 198 'label' => 'Tags', 137 'section' => 'stackcommerce_wp_section_ two',199 'section' => 'stackcommerce_wp_section_four', 138 200 'type' => 'multiselect', 139 201 'options' => $this->get_tags(), … … 141 203 'placeholder' => '', 142 204 'helper' => '', 143 'supplimental' => 'Tags entered in this field will be sent with <b>all</b> posts. Only enter tags you want to be applied on everything.<br />e.g. stackcommerce, sponsored' 144 ), 145 array( 146 'uid' => 'stackcommerce_wp_ strip_image',147 'label' => ' Keep featured image in body',148 'section' => 'stackcommerce_wp_section_ two',149 'type' => ' radio',205 'supplimental' => 'Tags entered in this field will be sent with <b>all</b> posts. Only enter tags you want to be applied on everything.<br />e.g. stackcommerce, sponsored', 206 ), 207 array( 208 'uid' => 'stackcommerce_wp_featured_image', 209 'label' => 'Featured Image Settings', 210 'section' => 'stackcommerce_wp_section_four', 211 'type' => 'select', 150 212 'options' => array( 151 'false' => 'No', 152 'true' => 'Yes', 213 'featured_image_only' => 'Set Featured Image', 214 'featured_image_plus_body' => 'Set Featured Image, plus include this image in article body', 215 'no_featured_image' => 'Do not set a Featured Image', 153 216 ), 154 'default' => array( 'false'),155 'placeholder' => '', 156 'helper' => '', 157 'supplimental' => ' Some WordPress templates show the featured image on the article page by default, while others do not. Check yes if the featured image does not appear on your article pages, and you want it to (rare). If the featured image already appears on your article pages OR you prefer that featured images do <b>not</b> appear, leave as no.'217 'default' => array(), 218 'placeholder' => '', 219 'helper' => '', 220 'supplimental' => '' 158 221 ) 159 222 ); … … 177 240 public function section_callback( $arguments ) { 178 241 switch( $arguments['id'] ) { 179 case 'stackcommerce_wp_section_ one':180 echo '<p> ' . SCWP_NAME . ' plugin allow us to automatically create posts in your WordPress account. Use the settings below to control how these articles get created in your WordPress installation.</p>';242 case 'stackcommerce_wp_section_two': 243 echo '<p>The Account ID and Secret Key will be provided during initial setup. This allows you to securely connect to our system. The connection status below will indicate when a successful connection is made. These values should not change after a successful connection.</p>'; 181 244 break; 182 case 'stackcommerce_wp_section_two': 183 echo '<p>Note: The Account ID and Secret Key will be provided during initial setup. This allows you to securely connect to our content system. The connection status below will indicate when a successful connection is made. These values should not change after a successful connection.</p>'; 245 case 'stackcommerce_wp_section_three': 246 echo '<h2>Content Settings</h2>'; 247 echo '<p>' . SCWP_NAME . ' allows posts to be scheduled directly in your WordPress CMS when you utilize our Brand Studio content service. Articles can be syndicated in draft, pending, or scheduled status. Turn ON content integration below if you are currently using this service.</p>'; 184 248 break; 185 249 } … … 205 269 case 'select': 206 270 case 'multiselect': 207 if( ! empty ( $arguments['options'] ) &&is_array( $arguments['options'] ) ) {271 if( is_array( $arguments['options'] ) ) { 208 272 $attributes = ''; 209 273 $options_markup = ''; 210 274 211 275 foreach( $arguments['options'] as $key => $label ) { 212 $options_markup .= sprintf( '<option value="%s" %s>%s</option>', $key, selected( $value[ array_search( $key, $value, true ) ], $key, false ), $label );276 $options_markup .= sprintf( '<option value="%s" %s>%s</option>', $key, selected( @$value[ array_search( $key, $value, true ) ], $key, false ), $label ); 213 277 } 214 278 -
stackcommerce-connect/trunk/includes/class-stackcommerce-wp.php
r1662635 r1681551 35 35 $this->register_endpoint(); 36 36 $this->enqueue_assets(); 37 $this->add_sc_js_code(); 38 $this->search(); 37 39 } 38 40 … … 56 58 require_once plugin_dir_path( dirname( __FILE__ ) ) . 'includes/class-stackcommerce-wp-settings.php'; 57 59 require_once plugin_dir_path( dirname( __FILE__ ) ) . 'includes/class-stackcommerce-wp-maintenance.php'; 60 require_once plugin_dir_path( dirname( __FILE__ ) ) . 'includes/class-stackcommerce-wp-search.php'; 58 61 59 62 $this->loader = new StackCommerce_WP_Loader(); … … 110 113 public function styles() { 111 114 wp_register_style( 'stackcommerce_wp_admin_style_select2', 'https://cdnjs.cloudflare.com/ajax/libs/select2/4.0.3/css/select2.min.css', array(), '', 'all' ); 112 wp_register_style( 'stackcommerce_wp_admin_style', plugin_dir_url( dirname(__FILE__) ) . 'css/stackcommerce-wp-settings.css', array(), ' ', 'all' );115 wp_register_style( 'stackcommerce_wp_admin_style', plugin_dir_url( dirname(__FILE__) ) . 'css/stackcommerce-wp-settings.css', array(), '1.1.0', 'all' ); 113 116 114 117 wp_enqueue_style( 'stackcommerce_wp_admin_style_select2' ); … … 123 126 public function scripts() { 124 127 wp_register_script( 'stackcommerce_wp_admin_script_select2', 'https://cdnjs.cloudflare.com/ajax/libs/select2/4.0.3/js/select2.min.js', array(), '', 'all' ); 125 wp_register_script( 'stackcommerce_wp_admin_script', plugin_dir_url( dirname(__FILE__) ) . 'js/stackcommerce-wp-settings.js', array( 'jquery' ), ' ', 'all' );128 wp_register_script( 'stackcommerce_wp_admin_script', plugin_dir_url( dirname(__FILE__) ) . 'js/stackcommerce-wp-settings.js', array( 'jquery' ), '1.1.0', 'all' ); 126 129 127 130 wp_enqueue_script( 'stackcommerce_wp_admin_script_select2' ); … … 153 156 154 157 /** 158 * Load StackCommerce JS Code 159 * 160 * @since 1.1.0 161 */ 162 public function load_sc_js_code() { 163 require_once( dirname( dirname( __FILE__ ) ) . '/views/stackcommerce-wp-js.php' ); 164 } 165 166 /** 167 * Add StackCommerce JS Code before ending body tag 168 * 169 * @since 1.1.0 170 */ 171 public function add_sc_js_code() { 172 $this->loader->add_action( 'wp_head', $this, 'load_sc_js_code', 10000 ); 173 } 174 175 /* 176 * Enable admin-ajax.php RESTful search of taxonomies 177 * 178 * @since 1.1.0 179 */ 180 public function search() { 181 $stackcommerce_wp_search = new StackCommerce_WP_Search(); 182 183 $this->loader->add_action( 'wp_ajax_sc_api_search', $stackcommerce_wp_search, 'sniff' ); 184 } 185 186 /** 155 187 * Run the loader to execute all of the hooks with WordPress. 156 188 * -
stackcommerce-connect/trunk/index.php
r1662635 r1681551 5 5 * Plugin URI: https://wordpress.org/plugins/stackcommerce-connect/ 6 6 * Description: The Connect plugin by StackCommerce connects your WordPress CMS to the StackCommerce Articles repository. 7 * Version: 1. 0.47 * Version: 1.1.0 8 8 * Author: StackCommerce, Inc 9 9 * Author URI: https://www.stackcommerce.com -
stackcommerce-connect/trunk/js/stackcommerce-wp-settings.js
r1659819 r1681551 2 2 3 3 ;(function(window, document, $) { 4 var endpoint = 'https://hive.stackcommerce.net';4 var endpoint = $('#stackcommerce_wp_cms_api_endpoint').val(); 5 5 6 6 $(document).ready(function() { 7 7 scwp_check(); 8 scwp_init_categories_search(); 9 scwp_init_tags_search(); 8 10 9 $('#stackcommerce_wp_tags').select2();10 11 $('.stackcommerce-wp-form-submit').click(scwp_validate); 11 12 $('form.stackcommerce-wp-form').keypress(scwp_keycheck); 13 $('input[name="stackcommerce_wp_content_integration[]"]').change(scwp_check); 12 14 }); 13 15 … … 43 45 post_status = ($('#stackcommerce_wp_post_status').val()) ? $('#stackcommerce_wp_post_status').val() : '', 44 46 tags = ($('#stackcommerce_wp_tags').val()) ? $('#stackcommerce_wp_tags').val() : [], 45 strip_image = ($('input[name="stackcommerce_wp_strip_image[]"]:checked').val() == 'true') ? true : false; 47 categories = ($('#stackcommerce_wp_categories').val()) ? $('#stackcommerce_wp_categories').val() : [], 48 featured_image = $('#stackcommerce_wp_featured_image').val(); 46 49 47 50 var data = { … … 54 57 'author_id': author_id, 55 58 'post_status': post_status, 59 'categories': categories, 56 60 'tags': tags, 57 ' strip_image': strip_image,61 'featured_image': featured_image, 58 62 }, 59 63 } … … 71 75 var status = $('#stackcommerce_wp_connection_status').val(), 72 76 form = $('form.stackcommerce-wp-form'), 73 submit = $('.stackcommerce-wp-form-submit'); 77 submit = $('.stackcommerce-wp-form-submit'), 78 content_integration = ($('input[name="stackcommerce_wp_content_integration[]"]:checked').val() == 'true') ? true : false; 74 79 75 80 form.attr('data-stackcommerce-wp-status', status); 81 form.attr('data-stackcommerce-wp-content-integration', content_integration); 76 82 submit.attr('disabled', (status == 'connecting' ? true : false)); 77 83 } … … 84 90 } 85 91 92 function scwp_search(options) { 93 $(options.selector).select2({ 94 ajax: { 95 type: 'POST', 96 url: ajaxurl, 97 dataType: 'json', 98 delay: 250, 99 data: function(params) { 100 return { 101 action: 'sc_api_search', 102 taxonomy: options.taxonomy, 103 q: params.term, 104 } 105 }, 106 processResults: function(data, params) { 107 var results = options.results.split('.').reduce(function(_data, key) { 108 return _data[key]; 109 }, data); 110 111 return { 112 results: results 113 } 114 }, 115 cache: true 116 }, 117 escapeMarkup: function(markup) { return markup; }, 118 minimumInputLength: 3, 119 }); 120 } 121 122 function scwp_init_categories_search() { 123 var options = { 124 selector: '#stackcommerce_wp_categories', 125 taxonomy: 'categories', 126 results: 'data.categories' 127 } 128 129 scwp_search(options); 130 } 131 132 function scwp_init_tags_search() { 133 var options = { 134 selector: '#stackcommerce_wp_tags', 135 taxonomy: 'tags', 136 results: 'data.tags' 137 } 138 139 scwp_search(options); 140 } 86 141 })(window, document, jQuery); -
stackcommerce-connect/trunk/readme.txt
r1662635 r1681551 4 4 Requires at least: 4.4 5 5 Tested up to: 4.7.5 6 Stable tag: 1. 0.46 Stable tag: 1.1.0 7 7 License: GPLv2 or later 8 8 License URI: http://www.gnu.org/licenses/gpl-2.0.html … … 21 21 * Control the status. Posts can be created as drafts, pending, or scheduled. 22 22 * Choose the author you want the post to be created by. 23 * Set tags to associate with all posts.23 * Set categories and tags to associate with all posts. 24 24 25 25 … … 53 53 == Changelog == 54 54 55 = 1.1.0 = 56 * Add categories option. 57 * Add additional options for Featured Image settings. 58 * Make Content Integration optional. 59 * Dynamically load tags & categories. 60 * General stability and performance improvements. 61 55 62 = 1.0.4 = 56 63 * Fix a bug that caused pages point to the homepage -
stackcommerce-connect/trunk/uninstall.php
r1662635 r1681551 49 49 'stackcommerce_wp_secret', 50 50 'stackcommerce_wp_connection_status', 51 'stackcommerce_wp_content_integration', 51 52 'stackcommerce_wp_author', 52 53 'stackcommerce_wp_post_status', 54 'stackcommerce_wp_categories', 53 55 'stackcommerce_wp_tags', 54 56 'stackcommerce_wp_featured_image' -
stackcommerce-connect/trunk/version.txt
r1662635 r1681551 1 1. 0.41 1.1.0 -
stackcommerce-connect/trunk/views/stackcommerce-wp-page-settings.php
r1659819 r1681551 21 21 ?> 22 22 23 <input type="hidden" id="stackcommerce_wp_endpoint" value="<?php echo site_url(); ?>/index.php?sc-api-version=<? = SCWP_API_VERSION?>&sc-api-route=posts" />23 <input type="hidden" id="stackcommerce_wp_endpoint" value="<?php echo site_url(); ?>/index.php?sc-api-version=<?php echo SCWP_API_VERSION; ?>&sc-api-route=posts" /> 24 24 25 <form method="post" class="stackcommerce-wp-form" id="stackcommerce-wp-form" action="options.php" autocomplete="off" data-stackcommerce-wp-status> 25 <input type="hidden" id="stackcommerce_wp_cms_api_endpoint" value="<?php echo CMS_API_ENDPOINT; ?>" /> 26 27 <form method="post" class="stackcommerce-wp-form" id="stackcommerce-wp-form" action="options.php" autocomplete="off" data-stackcommerce-wp-status data-stackcommerce-wp-content-integration> 26 28 27 29 <?php settings_fields( 'stackcommerce_wp' ); ?>
Note: See TracChangeset
for help on using the changeset viewer.