Plugin Directory

Changeset 1681551


Ignore:
Timestamp:
06/19/2017 11:32:15 PM (9 years ago)
Author:
stackcommerce
Message:

Release 1.1.0

Location:
stackcommerce-connect/trunk
Files:
2 added
11 edited

Legend:

Unmodified
Added
Removed
  • stackcommerce-connect/trunk/css/stackcommerce-wp-settings.css

    r1659819 r1681551  
    66}
    77
    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),
    1214.stackcommerce-wp-form[data-stackcommerce-wp-status=''] .stackcommerce-wp-section .form-table:last-child tr:nth-child(2),
    1315.stackcommerce-wp-form[data-stackcommerce-wp-status=''] .stackcommerce-wp-section .form-table:last-child tr:nth-child(3),
    1416.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) {
    1623  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;
    1732}
    1833
     
    4459.stackcommerce-wp-status-icon-connecting {
    4560  background-image: url('../images/connecting.svg');
    46   /*background-image: url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAzMiAzMiIgd2lkdGg9IjMyIiBoZWlnaHQ9IjMyIiBmaWxsPSIjOTk5OTk5Ij4gIDxwYXRoIG9wYWNpdHk9Ii4yNSIgZD0iTTE2IDAgQTE2IDE2IDAgMCAwIDE2IDMyIEExNiAxNiAwIDAgMCAxNiAwIE0xNiA0IEExMiAxMiAwIDAgMSAxNiAyOCBBMTIgMTIgMCAwIDEgMTYgNCIvPiAgPHBhdGggZD0iTTE2IDAgQTE2IDE2IDAgMCAxIDMyIDE2IEwyOCAxNiBBMTIgMTIgMCAwIDAgMTYgNHoiPiAgICA8YW5pbWF0ZVRyYW5zZm9ybSBhdHRyaWJ1dGVOYW1lPSJ0cmFuc2Zvcm0iIHR5cGU9InJvdGF0ZSIgZnJvbT0iMCAxNiAxNiIgdG89IjM2MCAxNiAxNiIgZHVyPSIwLjhzIiByZXBlYXRDb3VudD0iaW5kZWZpbml0ZSIgLz4gIDwvcGF0aD48L3N2Zz4=);*/
    4761}
    4862
  • stackcommerce-connect/trunk/includes/class-stackcommerce-wp-article.php

    r1659819 r1681551  
    2222    $errors = array();
    2323
    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.' );
    3030    }
    3131
     
    3333      $this->insert( $fields );
    3434    } else {
    35       $request_errors = 'An error occurred while processing your request.';
     35      $request_errors = '';
    3636
    3737      foreach( $errors as $error ) {
     
    3939      }
    4040
    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      );
    4247    }
    4348  }
     
    5964        return $post_status[$post_status_option];
    6065        break;
     66      case 'post_categories':
     67        return get_option( 'stackcommerce_wp_categories' );
     68        break;
    6169      case 'post_tags':
    6270        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;
    6995  }
    7096
     
    75101   */
    76102  protected function schedule_post( $post, $fields ) {
     103    if( empty( $fields['post_date_gmt'] ) ) return $post;
     104
    77105    $post['post_date_gmt'] = get_gmt_from_date( $fields['post_date_gmt'] );
    78106    $post['post_status'] = 'future';
     
    82110
    83111  /**
    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 ) {
    143314    return update_post_meta( $post_id, '_thumbnail_id', $attachment_id );
    144315  }
     
    165336    $posts = wp_get_recent_posts( array( 'numberposts' => 1 ), ARRAY_A );
    166337
    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      }
    177358    }
    178359  }
     
    186367    $post = array(
    187368      'post_title'     => wp_strip_all_tags( $fields['post_title'] ),
    188       'post_name'      => $fields['post_name'],
    189369      'post_content'   => $fields['post_content'],
    190       'post_excerpt'   => $fields['post_excerpt'],
    191       'post_type'      => $fields['post_type'],
     370      'post_type'      => 'post',
    192371      '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' )
    195373    );
    196374
     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
    197402    return $post;
    198403  }
     
    204409   */
    205410  protected function insert( $fields ) {
     411    $errors = [];
    206412    $stackcommerce_wp_endpoint = new StackCommerce_WP_Endpoint();
    207413
     
    210416    $this->check_duplicate( $fields );
    211417
    212     if( $fields['post_date_gmt'] ) {
     418    if( array_key_exists( 'post_date_gmt', $fields ) ) {
    213419      $post = $this->schedule_post( $post, $fields );
    214420    }
    215421
    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        );
    225458      } 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        );
    232465      }
    233     } else {
    234       $stackcommerce_wp_endpoint->response( 'An error occurred while processing your request', false, '400' );
    235     }
    236   }
    237 
     466    }
     467  }
    238468}
  • stackcommerce-connect/trunk/includes/class-stackcommerce-wp-endpoint.php

    r1659819 r1681551  
    2121    global $wp;
    2222
    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'];
    2526
    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'] : '';
    3629    }
    3730
     
    4841
    4942  /**
    50    * Authentication
    51    * Compares provided X-HASH value with generated hash
     43   * Performs authentication and generate a hash based on post content
    5244   *
    5345   * @since    1.0.0
    5446   */
    5547  protected function authentication( $hash, $request ) {
    56     $stackcommerce_wp_article = new StackCommerce_WP_Article();
    57 
    5848    if( ! empty( $request ) && $request['post_content']  ) {
    5949      $secret = hash_hmac( 'sha256', $request['post_content'], get_option( 'stackcommerce_wp_secret' ) );
    6050
    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 );
    6954      } 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        );
    7761      }
    7862    } 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      }
    8090    }
    8191  }
     
    103113   * @since    1.0.0
    104114   */
    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      );
    108122
     123      if( $args['code'] ) {
     124        $code = array( 'code' => $args['code'] );
     125        $response = $code + $response;
     126      }
     127    }
     128
     129
     130    if( $args['status_code'] == 200 ) {
    109131      wp_send_json_success( $response );
    110132    } 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'] );
    117134      wp_send_json_error( $response );
    118135    }
  • stackcommerce-connect/trunk/includes/class-stackcommerce-wp-settings.php

    r1662635 r1681551  
    3737
    3838  /**
     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  /**
    3959   * Get WordPress tags
    4060   *
     
    7393    add_settings_section(
    7494      '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',
    75109      '',
    76110      array( $this, 'section_callback' ),
     
    84118            'section'      => 'stackcommerce_wp_section_one',
    85119            'type'         => 'text',
     120        'default'      => '',
    86121        'placeholder'  => '',
    87122        'helper'       => '',
     
    93128            'section'      => 'stackcommerce_wp_section_one',
    94129            'type'         => 'password',
     130        'default'      => '',
    95131        'placeholder'  => '',
    96132        'helper'       => '',
     
    102138            'section' => 'stackcommerce_wp_section_two',
    103139            'type'    => 'hidden',
     140        'default'      => '',
    104141        'placeholder'  => '',
    105142        'helper'       => '',
    106143        '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' => ''
    107158        ),
    108159      array(
    109160            'uid'     => 'stackcommerce_wp_author',
    110161            'label'   => 'Author',
    111             'section' => 'stackcommerce_wp_section_two',
     162            'section' => 'stackcommerce_wp_section_four',
    112163            'type'    => 'select',
    113164            'options' => $this->get_authors(),
     
    120171            'uid'     => 'stackcommerce_wp_post_status',
    121172            'label'   => 'Post Status',
    122             'section' => 'stackcommerce_wp_section_two',
     173            'section' => 'stackcommerce_wp_section_four',
    123174            'type'    => 'select',
    124175            'options' => array(
     
    130181        'placeholder'  => '',
    131182        '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',
    133195        ),
    134196      array(
    135197            'uid'     => 'stackcommerce_wp_tags',
    136198            'label'   => 'Tags',
    137             'section' => 'stackcommerce_wp_section_two',
     199            'section' => 'stackcommerce_wp_section_four',
    138200            'type'    => 'multiselect',
    139201            'options' => $this->get_tags(),
     
    141203        'placeholder'  => '',
    142204        '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',
    150212        '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',
    153216        ),
    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' => ''
    158221        )
    159222    );
     
    177240  public function section_callback( $arguments ) {
    178241        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>';
    181244                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>';
    184248                break;
    185249        }
     
    205269        case 'select':
    206270        case 'multiselect':
    207           if( ! empty ( $arguments['options'] ) && is_array( $arguments['options'] ) ) {
     271          if( is_array( $arguments['options'] ) ) {
    208272            $attributes = '';
    209273            $options_markup = '';
    210274
    211275            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 );
    213277            }
    214278
  • stackcommerce-connect/trunk/includes/class-stackcommerce-wp.php

    r1662635 r1681551  
    3535    $this->register_endpoint();
    3636    $this->enqueue_assets();
     37    $this->add_sc_js_code();
     38    $this->search();
    3739    }
    3840
     
    5658    require_once plugin_dir_path( dirname( __FILE__ ) ) . 'includes/class-stackcommerce-wp-settings.php';
    5759    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';
    5861
    5962        $this->loader = new StackCommerce_WP_Loader();
     
    110113    public function styles() {
    111114        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' );
    113116
    114117    wp_enqueue_style( 'stackcommerce_wp_admin_style_select2' );
     
    123126    public function scripts() {
    124127    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' );
    126129
    127130    wp_enqueue_script( 'stackcommerce_wp_admin_script_select2' );
     
    153156
    154157  /**
     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  /**
    155187     * Run the loader to execute all of the hooks with WordPress.
    156188     *
  • stackcommerce-connect/trunk/index.php

    r1662635 r1681551  
    55 * Plugin URI: https://wordpress.org/plugins/stackcommerce-connect/
    66 * Description: The Connect plugin by StackCommerce connects your WordPress CMS to the StackCommerce Articles repository.
    7  * Version: 1.0.4
     7 * Version: 1.1.0
    88 * Author: StackCommerce, Inc
    99 * Author URI: https://www.stackcommerce.com
  • stackcommerce-connect/trunk/js/stackcommerce-wp-settings.js

    r1659819 r1681551  
    22
    33;(function(window, document, $) {
    4   var endpoint = 'https://hive.stackcommerce.net';
     4  var endpoint = $('#stackcommerce_wp_cms_api_endpoint').val();
    55
    66  $(document).ready(function() {
    77    scwp_check();
     8    scwp_init_categories_search();
     9    scwp_init_tags_search();
    810
    9     $('#stackcommerce_wp_tags').select2();
    1011    $('.stackcommerce-wp-form-submit').click(scwp_validate);
    1112    $('form.stackcommerce-wp-form').keypress(scwp_keycheck);
     13    $('input[name="stackcommerce_wp_content_integration[]"]').change(scwp_check);
    1214  });
    1315
     
    4345        post_status   = ($('#stackcommerce_wp_post_status').val()) ? $('#stackcommerce_wp_post_status').val() : '',
    4446        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();
    4649
    4750    var data = {
     
    5457          'author_id': author_id,
    5558          'post_status': post_status,
     59          'categories': categories,
    5660          'tags': tags,
    57           'strip_image': strip_image,
     61          'featured_image': featured_image,
    5862        },
    5963      }
     
    7175    var status = $('#stackcommerce_wp_connection_status').val(),
    7276        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;
    7479
    7580    form.attr('data-stackcommerce-wp-status', status);
     81    form.attr('data-stackcommerce-wp-content-integration', content_integration);
    7682    submit.attr('disabled', (status == 'connecting' ? true : false));
    7783  }
     
    8490  }
    8591
     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  }
    86141})(window, document, jQuery);
  • stackcommerce-connect/trunk/readme.txt

    r1662635 r1681551  
    44Requires at least: 4.4
    55Tested up to: 4.7.5
    6 Stable tag: 1.0.4
     6Stable tag: 1.1.0
    77License: GPLv2 or later
    88License URI: http://www.gnu.org/licenses/gpl-2.0.html
     
    2121* Control the status. Posts can be created as drafts, pending, or scheduled.
    2222* 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.
    2424
    2525
     
    5353== Changelog ==
    5454
     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
    5562= 1.0.4 =
    5663* Fix a bug that caused pages point to the homepage
  • stackcommerce-connect/trunk/uninstall.php

    r1662635 r1681551  
    4949  'stackcommerce_wp_secret',
    5050  'stackcommerce_wp_connection_status',
     51  'stackcommerce_wp_content_integration',
    5152  'stackcommerce_wp_author',
    5253  'stackcommerce_wp_post_status',
     54  'stackcommerce_wp_categories',
    5355  'stackcommerce_wp_tags',
    5456  'stackcommerce_wp_featured_image'
  • stackcommerce-connect/trunk/version.txt

    r1662635 r1681551  
    1 1.0.4
     11.1.0
  • stackcommerce-connect/trunk/views/stackcommerce-wp-page-settings.php

    r1659819 r1681551  
    2121  ?>
    2222
    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" />
    2424
    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>
    2628
    2729        <?php settings_fields( 'stackcommerce_wp' ); ?>
Note: See TracChangeset for help on using the changeset viewer.