Changeset 918102
- Timestamp:
- 05/20/2014 06:37:29 PM (12 years ago)
- Location:
- maven-algolia/trunk
- Files:
-
- 11 edited
-
admin/controllers/indexer.php (modified) (4 diffs)
-
admin/controllers/settings.php (modified) (8 diffs)
-
admin/views/settings.php (modified) (1 diff)
-
core/fields-helper.php (modified) (7 diffs)
-
core/indexer.php (modified) (1 diff)
-
core/initializer.php (modified) (3 diffs)
-
core/registry.php (modified) (2 diffs)
-
front/assets/scripts/predictions.js (modified) (7 diffs)
-
lib/algoliasearch.min.js (modified) (1 diff)
-
lib/algoliasearch.php (modified) (41 diffs)
-
maven-algolia.php (modified) (2 diffs)
Legend:
- Unmodified
- Added
- Removed
-
maven-algolia/trunk/admin/controllers/indexer.php
r915533 r918102 14 14 */ 15 15 public function __construct ( ) { 16 // Delete the post in the index when it was deleted in the site 17 add_action( 'deleted_post', array( &$this, 'postDeleted' ) ); 18 // Delete the post in the index when it was unpublished 19 add_action( 'transition_post_status', array( &$this, 'postUnpublished' ), 10, 3 ); 20 // Update the post in the index when it was updated 21 // JUST WHEN IT IS publish 22 add_action( 'save_post', array( &$this, 'postUpdated' ), 11, 3 ); 16 17 if( Registry::instance()->isEnabled() ){ 18 // Delete the post in the index when it was deleted in the site 19 add_action( 'deleted_post', array( &$this, 'postDeleted' ) ); 20 // Delete the post in the index when it was unpublished 21 add_action( 'transition_post_status', array( &$this, 'postUnpublished' ), 10, 3 ); 22 // Update the post in the index when it was updated 23 // JUST WHEN IT IS publish 24 add_action( 'save_post', array( &$this, 'postUpdated' ), 11, 3 ); 25 26 // Update the term in the index when the counter was updated in WP 27 add_action( "edited_term_taxonomy", array( &$this, 'termTaxonomyUpdated' ), 10, 2 ); 28 // Insert the term in the index when it was created 29 add_action( "created_term", array( &$this, 'termCreated' ), 10, 3 ); 30 // Delete the term in the index when it was deleted in the site 31 add_action( 'delete_term', array( &$this, 'termDeleted' ), 10, 4 ); 32 } 23 33 } 24 34 … … 45 55 if ( isset( $postTypesToIndex[$post->post_type] ) && $old_status == 'publish' && $new_status != 'publish' && !empty( $post->ID ) ) { 46 56 // Post is unpublished so remove from index 47 // Init the index 48 $indexer = new Core\Indexer( Registry::instance()->getAppId(), Registry::instance()->getApiKey() ); 49 // TODO: remember to add the index by post type when we have it implemented 50 $indexer->removeObject( Registry::instance()->getDefaultIndex(), $post->ID ); 57 try { 58 // Init the index 59 $indexer = new Core\Indexer( Registry::instance()->getAppId(), Registry::instance()->getApiKey() ); 60 // TODO: remember to add the index by post type when we have it implemented 61 $indexer->deleteObject( Registry::instance()->getDefaultIndex(), $post->ID ); 62 } catch ( Exception $exc ) { 63 64 } 51 65 } 52 66 } … … 68 82 $postTypesToIndex = Core\FieldsHelper::getPostTypesObject(); 69 83 if ( !isset( $postTypesToIndex[$post->post_type] ) ) { return $postID; } 70 // Init the index 71 $indexer = new Core\Indexer( Registry::instance()->getAppId(), Registry::instance()->getApiKey() ); 72 $objectToIndex = $indexer->postToAlgoliaObject( $post,$postTypesToIndex[$post->post_type] ); 73 if( $objectToIndex ){ 74 // TODO: remember to add the index by post type when we have it implemented 75 $indexer->indexObject( Registry::instance()->getDefaultIndex(), $objectToIndex ); 84 try { 85 // Init the index 86 $indexer = new Core\Indexer( Registry::instance()->getAppId(), Registry::instance()->getApiKey() ); 87 $objectToIndex = $indexer->postToAlgoliaObject( $post, $postTypesToIndex[$post->post_type] ); 88 if( $objectToIndex ){ 89 // TODO: remember to add the index by post type when we have it implemented 90 $indexer->indexObject( Registry::instance()->getDefaultIndex(), $objectToIndex ); 91 } 92 } catch ( Exception $exc ) { 93 76 94 } 77 95 } … … 80 98 * Remove the post from the index when it was deleted in WP 81 99 * Called from deleted_post action 82 * @param int $post id100 * @param int $postId 83 101 */ 84 public function postDeleted( $postid ) { 85 if ( !empty( $postid ) ) { 86 // Post is unpublished so remove from index 102 public function postDeleted( $postId ) { 103 if ( !empty( $postId ) ) { 104 try { 105 // Post is unpublished so remove from index 106 $indexer = new Core\Indexer( Registry::instance()->getAppId(), Registry::instance()->getApiKey() ); 107 // TODO: remember to add the index by post type when we have it implemented 108 $indexer->deleteObject( Registry::instance()->getDefaultIndex(), $postId ); 109 } catch ( Exception $exc ) { 110 111 } 112 } 113 } 114 115 /** 116 * Update term in the index when it was unpdated in WP 117 * Called from edited_term and created_term actions 118 * @param integer $ttId 119 * @param object $taxonomy 120 */ 121 public function termTaxonomyUpdated( $ttId, $taxonomy ) { 122 if( empty( $taxonomy->name ) ){ return $ttId; } 123 124 $taxonomyToIndex = Core\FieldsHelper::getTaxonomyObjectByType( $taxonomy->name ); 125 126 if ( empty( $taxonomyToIndex ) || ! $taxonomyToIndex->getIndexName() ) { return $ttId; } 127 128 // Get the object before deletion so we can pass to actions below 129 $termUpdated = get_term_by( 'term_taxonomy_id', $ttId, $taxonomy->name ); 130 if( !is_wp_error( $termUpdated ) && $termUpdated ){ 131 try { 132 // Init the index 133 $indexer = new Core\Indexer( Registry::instance()->getAppId(), Registry::instance()->getApiKey() ); 134 // Convert the term in a algolia object 135 $objectToIndex = $indexer->termToAlgoliaObject( $termUpdated, $taxonomyToIndex ); 136 if( $objectToIndex ){ 137 $indexer->indexObject( $taxonomyToIndex->getIndexName(), $objectToIndex ); 138 } 139 } catch ( Exception $exc ) { 140 141 } 142 } 143 } 144 145 /** 146 * Update term in the index when it was unpdated in WP 147 * Called from edited_term and created_term actions 148 * @param integer $termId 149 * @param integer $ttId 150 * @param string $taxonomy 151 */ 152 public function termCreated( $termId, $ttId, $taxonomy ) { 153 $taxonomyToIndex = Core\FieldsHelper::getTaxonomyObjectByType( $taxonomy ); 154 if ( empty( $taxonomyToIndex ) || ! $taxonomyToIndex->getIndexName() ) { return $termId; } 155 156 // Get the object before deletion so we can pass to actions below 157 $termUpdated = get_term( $termId, $taxonomy ); 158 if( !is_wp_error( $termUpdated ) && $termUpdated ){ 159 try { 160 // Init the index 161 $indexer = new Core\Indexer( Registry::instance()->getAppId(), Registry::instance()->getApiKey() ); 162 // Convert the term in a algolia object 163 $objectToIndex = $indexer->termToAlgoliaObject( $termUpdated, $taxonomyToIndex ); 164 if( $objectToIndex ){ 165 $indexer->indexObject( $taxonomyToIndex->getIndexName(), $objectToIndex ); 166 } 167 } catch ( Exception $exc ) { 168 169 } 170 } 171 } 172 173 /** 174 * Remove the term from the index when it was deleted in WP 175 * Called from delete_term action 176 * @param integer $termId 177 * @param integer $ttId 178 * @param string $taxonomy 179 * @param object $deleted_term 180 */ 181 public function termDeleted( $termId, $ttId, $taxonomy, $deleted_term ) { 182 $taxonomyToIndex = Core\FieldsHelper::getTaxonomyObjectByType( $taxonomy ); 183 if ( empty( $ttId ) || empty( $taxonomyToIndex ) || ! $taxonomyToIndex->getIndexName() ) { return $termId; } 184 try { 185 // Term was removed so remove it from index 87 186 $indexer = new Core\Indexer( Registry::instance()->getAppId(), Registry::instance()->getApiKey() ); 88 // TODO: remember to add the index by post type when we have it implemented 89 $indexer->removeObject( Registry::instance()->getDefaultIndex(), $postid ); 187 $indexer->deleteObject( $taxonomyToIndex->getIndexName(), $ttId ); 188 } catch ( Exception $exc ) { 189 90 190 } 91 191 } -
maven-algolia/trunk/admin/controllers/settings.php
r915533 r918102 185 185 $offset = !empty( $_POST['queryOffset'] ) ? (int)$_POST['queryOffset'] : 0; 186 186 187 // Init the index188 $indexer = new Core\Indexer( Registry::instance()->getAppId(), Registry::instance()->getApiKey() );189 187 190 188 … … 194 192 $postType = $postTypesToIndex[$indexPostType]; 195 193 try { 194 // Init the index 195 $indexer = new Core\Indexer( Registry::instance()->getAppId(), Registry::instance()->getApiKey() ); 196 196 // indexing in a tmp index to avoid breaking something in the current site functionality 197 197 // Then it will be moved to the correct name with the new info … … 234 234 $indexTaxonomyType = !empty( $_POST['indexTaxonomyType'] ) ? sanitize_text_field( $_POST['indexTaxonomyType'] ) : 0; 235 235 $offset = !empty( $_POST['queryOffset'] ) ? (int)$_POST['queryOffset'] : 0; 236 237 // Init the index 238 $indexer = new Core\Indexer( Registry::instance()->getAppId(), Registry::instance()->getApiKey() ); 239 240 236 241 237 $taxonomyTypeToIndex = Core\FieldsHelper::getTaxonomyObjectByType( $indexTaxonomyType ); 242 238 // var_dump($taxonomyTypeToIndex); … … 244 240 if( $taxonomyTypeToIndex && $taxonomyTypeToIndex->getIndexName() ){ 245 241 try { 242 // Init the index 243 $indexer = new Core\Indexer( Registry::instance()->getAppId(), Registry::instance()->getApiKey() ); 246 244 // indexing in a tmp index to avoid breaking something in the current site functionality 247 245 // Then it will be moved to the correct name with the new info … … 357 355 $offset = !empty( $_POST['queryOffset'] ) ? (int)$_POST['queryOffset'] : 0; 358 356 359 // Init the index360 $indexer = new Core\Indexer( Registry::instance()->getAppId(), Registry::instance()->getApiKey() );361 357 362 358 $errorMessage = ''; … … 366 362 if( $postTypesToIndex && is_array( $postTypesToIndex ) ){ 367 363 try { 364 // Init the index 365 $indexer = new Core\Indexer( Registry::instance()->getAppId(), Registry::instance()->getApiKey() ); 368 366 $totalRemoved = $indexer->removeIndexData( Registry::instance()->getDefaultIndex(), $postTypesToIndex, $this->postsPerPageToRemove, $offset ); 369 367 } catch ( Exception $exc ) { … … 389 387 if( !empty( $_POST['runMoveIndex'] ) && Registry::instance()->isValidApp() ) 390 388 { 391 // Init the index392 $indexer = new Core\Indexer( Registry::instance()->getAppId(), Registry::instance()->getApiKey() );393 389 394 390 $errorMessage = ''; … … 397 393 if( $postTypesToIndex && is_array( $postTypesToIndex ) ){ 398 394 try { 395 // Init the index 396 $indexer = new Core\Indexer( Registry::instance()->getAppId(), Registry::instance()->getApiKey() ); 399 397 $indexName = Registry::instance()->getDefaultIndex(); 400 398 $tmpIndexName = sprintf( '%s_tmp', $indexName ); -
maven-algolia/trunk/admin/views/settings.php
r915533 r918102 11 11 <input type="hidden" value="<?php echo Settings::updateAction; ?>" name="mvnAlg_action"> 12 12 <?php wp_nonce_field( Settings::updateAction ); ?> 13 <table class="widefat" style="width: 75%"> 14 <thead> 15 <tr> 16 <th class="row-title" colspan="2"><strong><?php esc_html_e( 'Configure your App Credentials', $langDomain ); ?></strong></th> 17 </tr> 18 </thead> 19 <tbody> 20 <tr valign="top"> 21 <th scope="row"><label for="mvnAlg_appId"><?php esc_html_e( 'APP ID', $langDomain ); ?></label></th> 22 <td><input type="text" class="regular-text" value="<?php echo esc_attr( $registry->getAppId() ); ?>" id="mvnAlg_appId" name="<?php echo Settings::settingsField; ?>[appId]"></td> 23 </tr> 24 <tr valign="top"> 25 <th scope="row"><label for="mvnAlg_apiKey"><?php esc_html_e( 'API Key', $langDomain ); ?></label></th> 26 <td><input type="text" class="regular-text" value="<?php echo esc_attr( $registry->getApiKey() ); ?>" id="mvnAlg_apiKey" name="<?php echo Settings::settingsField; ?>[apiKey]"></td> 27 </tr> 28 <tr valign="top"> 29 <th scope="row"><label for="mvnAlg_apiKeySearch"><?php esc_html_e( 'API Key for Search Only', $langDomain ); ?></label></th> 30 <td><input type="text" class="regular-text" value="<?php echo esc_attr( $registry->getApiKeySearch() ); ?>" id="mvnAlg_apiKeySearch" name="<?php echo Settings::settingsField; ?>[apiKeySearch]"></td> 31 </tr> 32 <tr> 33 <td> 34 <p class="submit"><input type="submit" value="<?php esc_attr_e( 'Save Changes', $langDomain ); ?>" class="button button-primary" id="submit" name="submit"></p> 35 </td> 36 </tr> 37 </tbody> 13 <table style="width: 100%"> 14 <tr> 15 <td style="width:45%; vertical-align: top;"> 16 <table class="widefat"> 17 <thead> 18 <tr> 19 <th class="row-title" colspan="2"><strong><?php esc_html_e( 'Configure your App Credentials', $langDomain ); ?></strong></th> 20 </tr> 21 </thead> 22 <tbody> 23 <tr valign="top"> 24 <th scope="row"><label for="mvnAlg_appId"><?php esc_html_e( 'APP ID', $langDomain ); ?></label></th> 25 <td><input type="text" class="regular-text" value="<?php echo esc_attr( $registry->getAppId() ); ?>" id="mvnAlg_appId" name="<?php echo Settings::settingsField; ?>[appId]"></td> 26 </tr> 27 <tr valign="top"> 28 <th scope="row"><label for="mvnAlg_apiKey"><?php esc_html_e( 'API Key', $langDomain ); ?></label></th> 29 <td><input type="text" class="regular-text" value="<?php echo esc_attr( $registry->getApiKey() ); ?>" id="mvnAlg_apiKey" name="<?php echo Settings::settingsField; ?>[apiKey]"></td> 30 </tr> 31 <tr valign="top"> 32 <th scope="row"><label for="mvnAlg_apiKeySearch"><?php esc_html_e( 'API Key for Search Only', $langDomain ); ?></label></th> 33 <td><input type="text" class="regular-text" value="<?php echo esc_attr( $registry->getApiKeySearch() ); ?>" id="mvnAlg_apiKeySearch" name="<?php echo Settings::settingsField; ?>[apiKeySearch]"></td> 34 </tr> 35 <tr> 36 <td> 37 <p class="submit"><input type="submit" value="<?php esc_attr_e( 'Save Changes', $langDomain ); ?>" class="button button-primary" id="submit" name="submit"></p> 38 </td> 39 </tr> 40 </tbody> 41 </table> 42 43 <?php if ( Core\UtilsAlgolia::readyToIndex() ): ?> 44 <table class="widefat" style="margin-top: 30px; "> 45 <thead> 46 <tr> 47 <th class="row-title" colspan="2"><strong><?php esc_html_e( 'Index Content', $langDomain ); ?></strong></th> 48 </tr> 49 </thead> 50 <tbody> 51 <tr valign="top"> 52 <th scope="row"><label for="mvnAlg_defaultIndex"><?php esc_html_e( 'Index Name', $langDomain ); ?></label></th> 53 <td><input type="text" class="regular-text" value="<?php echo esc_attr( $registry->getDefaultIndex() ); ?>" id="mvnAlg_defaultIndex" name="<?php echo Settings::settingsField; ?>[defaultIndex]"></td> 54 </tr> 55 <?php if ( $registry->getDefaultIndex() ): ?> 56 57 <tr valign="top" class="index-action-row index-action-button"> 58 <th scope="row"><label for="mvnAlg_index"><?php esc_html_e( 'Click to index content', $langDomain ); ?></label></th> 59 <td> 60 <div class="algolia-action-button" style="width:50%;"> 61 <button type="button" class="button button-secondary" id="mvnAlg_index" name="mvnAlg_index"><?php esc_html_e( 'Index Content', $langDomain ); ?></button> 62 <span class="spinner algolia-index-spinner"></span> 63 </div> 64 </td> 65 </tr> 66 <tr class="index-action-row index-messages"> 67 <th> </th> 68 <td> 69 <div class="success"><ul id="mvn-alg-index-result"></ul></div> 70 <div class="error error-message" style="display: none;"><p id="mvn-alg-index-error" ></p></div> 71 </td> 72 </tr> 73 <?php else: ?> 74 <tr> 75 <td colspan="2"> 76 <p><?php _e( 'Please set an "Index Name" and then update the settings to start indexing content.', $langDomain ) ?></p> 77 </td> 78 </tr> 79 <?php endif; ?> 80 <tr> 81 <td> 82 <p class="submit"><input type="submit" value="<?php esc_attr_e( 'Save Changes', $langDomain ); ?>" class="button button-primary" id="submit" name="submit"></p> 83 </td> 84 </tr> 85 </tbody> 86 </table> 87 <?php endif; ?> 88 </td> 89 <td style="width: 45%; vertical-align: top;"> 90 <table class="widefat"> 91 <thead> 92 <tr> 93 <th class="row-title" colspan="2"><strong><?php esc_html_e( 'Customization', $langDomain ); ?></strong></th> 94 </tr> 95 </thead> 96 <tbody> 97 <tr valign="top"> 98 <td> 99 <label for="mvnAlg_indexTaxonomies"><?php esc_html_e( 'Check if you want to index taxonomies', $langDomain ); ?></label> 100 <input type="hidden" value="0" name="<?php echo Settings::settingsField; ?>[indexTaxonomies]"> 101 <input type="checkbox" class="checkbox" <?php checked( $registry->indexTaxonomies() ); ?> value="1" id="mvnAlg_indexTaxonomies" name="<?php echo Settings::settingsField; ?>[indexTaxonomies]"> 102 </td> 103 </tr> 104 <tr valign="top"> 105 <th scope="row"> 106 <?php esc_html_e( 'This is the list of Taxonomies that would be indexed, please remember that each taxonomy will have its own index name and they will appear separately in the "suggestions search" popup.', $langDomain ); ?><br> 107 <ul><?php 108 $taxonomiesToIndex = Core\FieldsHelper::getTaxonomyObjects(); 109 if( $taxonomiesToIndex ): 110 $taxonomiesLabels = Core\FieldsHelper::getTaxonomyLabels(); 111 foreach ( $taxonomiesToIndex as $taxKey => $tax ) : 112 ?> 113 <li><?php echo sprintf( '<strong>%s</strong>: %s <br> <strong>%s</strong>: %s', __('Taxonomy'), $taxonomiesLabels[$taxKey], __('Index Name'), $tax->getIndexName() ); ?></li> 114 <?php 115 endforeach; 116 endif; 117 ?> 118 </ul> 119 </td> 120 </tr> 121 <tr> 122 <td> 123 <p class="submit"><input type="submit" value="<?php esc_attr_e( 'Save Changes', $langDomain ); ?>" class="button button-primary" id="submit" name="submit"></p> 124 </td> 125 </tr> 126 </tbody> 127 </table> 128 </td> 129 </tr> 38 130 </table> 39 131 40 <?php if ( Core\UtilsAlgolia::readyToIndex() ): ?>41 <table class="widefat" style="width: 75%; margin-top: 30px; ">42 <thead>43 <tr>44 <th class="row-title" colspan="2"><strong><?php esc_html_e( 'Index Content', $langDomain ); ?></strong></th>45 </tr>46 </thead>47 <tbody>48 <tr valign="top">49 <th scope="row"><label for="mvnAlg_defaultIndex"><?php esc_html_e( 'Index Name', $langDomain ); ?></label></th>50 <td><input type="text" class="regular-text" value="<?php echo esc_attr( $registry->getDefaultIndex() ); ?>" id="mvnAlg_defaultIndex" name="<?php echo Settings::settingsField; ?>[defaultIndex]"></td>51 </tr>52 <?php if ( $registry->getDefaultIndex() ): ?>53 54 <tr valign="top" class="index-action-row index-action-button">55 <th scope="row"><label for="mvnAlg_index"><?php esc_html_e( 'Click to index content', $langDomain ); ?></label></th>56 <td>57 <div class="algolia-action-button" style="width:50%;">58 <button type="button" class="button button-secondary" id="mvnAlg_index" name="mvnAlg_index"><?php esc_html_e( 'Index Content', $langDomain ); ?></button>59 <span class="spinner algolia-index-spinner"></span>60 </div>61 </td>62 </tr>63 <tr class="index-action-row index-messages">64 <th> </th>65 <td>66 <div class="success"><ul id="mvn-alg-index-result"></ul></div>67 <div class="error error-message" style="display: none;"><p id="mvn-alg-index-error" ></p></div>68 </td>69 </tr>70 <?php else: ?>71 <tr>72 <td colspan="2">73 <p><?php _e( 'Please set an "Index Name" and then update the settings to start indexing content.', $langDomain ) ?></p>74 </td>75 </tr>76 <?php endif; ?>77 <tr>78 <td>79 <p class="submit"><input type="submit" value="<?php esc_attr_e( 'Save Changes', $langDomain ); ?>" class="button button-primary" id="submit" name="submit"></p>80 </td>81 </tr>82 </tbody>83 </table>84 <?php endif; ?>85 132 </form> 86 133 </div> -
maven-algolia/trunk/core/fields-helper.php
r915533 r918102 101 101 'taxonomies' => array( 102 102 'category' => array( 'algoliaName' => 'category', 'isTag' => FALSE, 'forFaceting' => TRUE ), 103 ' tag' => array( 'algoliaName' => 'tag', 'isTag' => TRUE, 'forFaceting' => FALSE ),103 'post_tag' => array( 'algoliaName' => '_tags', 'isTag' => TRUE, 'forFaceting' => FALSE ), 104 104 ), 105 105 //'metas' => array( '{{META_KEY}}' => array( 'algoliaName' => '{{FIELD_NAME_IN_ALGOLIA}}', 'isSingle' => TRUE, 'type' => '{{FIELD_TYPE}}' ) ) … … 180 180 $fieldsNames = array( 181 181 'term_taxonomy_id' => array ( 'label' => "objectID", 'type' => 'integer' ), 182 'term_id' => array ( 'label' => "termId", 'type' => 'integer' ), 182 'term_id' => array ( 'label' => "termId", 'type' => 'integer' ), 183 183 'name' => array ( 'label' => "title", 'type' => 'string' ), 184 184 'slug' => array ( 'label' => "slug", 'type' => 'string' ), … … 186 186 'parent' => array ( 'label' => "parent", 'type' => 'integer' ), 187 187 'count' => array ( 'label' => "postsRelated", 'type' => 'integer' ), 188 'taxonomy' => array ( 'label' => "taxonomy", 'type' => 'string' ), 188 189 ); 189 190 … … 218 219 219 220 220 221 /** 222 * 223 * @param object $term 224 * @param string $field 225 * @param mixed $value 226 * @return mixed 227 */ 221 228 public static function getTaxCompoundFieldValue( $term, $field, $value = '' ) { 222 229 switch ( $field ) { … … 231 238 } 232 239 240 /** 241 * Get the domain name 242 * @return string 243 */ 244 public static function getDomainName ( ) { 245 $host = parse_url ( site_url(), PHP_URL_HOST ); 246 $domainName = array_shift( explode( '.', str_replace( 'www.', '', $host ) ) ); 247 return ( $domainName ) ? $domainName : '' ; 248 } 249 250 251 /** 252 * Return the array of taxonomies to index with their fields 253 * @return array 254 */ 233 255 public static function getTaxonomiesToIndex(){ 256 $indexPrefix = self::getDomainName(); 257 if( !empty( $indexPrefix ) ){ 258 $indexPrefix = sprintf( '%s-', $indexPrefix ); 259 } 234 260 235 261 $defaultTaxonomies = array( 236 262 'category' => array( 237 'indexName' => 'WP-Categories',263 'indexName' => sprintf( '%sWP-Categories', $indexPrefix ), 238 264 //'metas' => array( '{{META_KEY}}' => array( 'algoliaName' => '{{FIELD_NAME_IN_ALGOLIA}}', 'isSingle' => TRUE, 'type' => '{{FIELD_TYPE}}' ) ) 239 265 ), 240 266 'post_tag' => array( 241 'indexName' => 'WP-Tags',267 'indexName' => sprintf( '%sWP-Tags', $indexPrefix ), 242 268 //'metas' => array( '{{META_KEY}}' => array( 'algoliaName' => '{{FIELD_NAME_IN_ALGOLIA}}', 'isSingle' => TRUE, 'type' => '{{FIELD_TYPE}}' ) ) 243 269 ), 244 270 ); 245 return apply_filters( 'mvnAlgTaxonomiesToIndex', $defaultTaxonomies ); 246 } 247 271 return apply_filters( 'mvnAlgTaxonomiesToIndex', $defaultTaxonomies, $indexPrefix ); 272 } 273 274 /** 275 * 276 * @return array 277 */ 248 278 public static function getTaxonomyObjects( ){ 249 279 $taxonomyObjects = array(); 250 $taxonomies = self::get PostTypesToIndex();280 $taxonomies = self::getTaxonomiesToIndex(); 251 281 foreach ( $taxonomies as $taxonomyType => $fields ) { 252 282 $taxonomyObjects[$taxonomyType] = self::getTaxonomyObject( $taxonomyType, $fields ); … … 256 286 } 257 287 288 /** 289 * 290 * @param string $taxonomyType 291 * @return \MavenAlgolia\Core\Domain\Taxonomy|null 292 */ 258 293 public static function getTaxonomyObjectByType( $taxonomyType ){ 259 294 $taxonomies = self::getTaxonomiesToIndex(); … … 264 299 } 265 300 301 /** 302 * 303 * @param strings $taxonomyType 304 * @param array $fields 305 * @return \MavenAlgolia\Core\Domain\Taxonomy 306 */ 266 307 public static function getTaxonomyObject( $taxonomyType, $fields ){ 267 308 $taxObj = new Domain\Taxonomy(); -
maven-algolia/trunk/core/indexer.php
r915533 r918102 512 512 */ 513 513 public function termToAlgoliaObject( $term, $taxonomy = null ) { 514 global $wpdb;515 514 516 515 if( empty( $taxonomy ) && !empty( $term->taxonomy ) ){ -
maven-algolia/trunk/core/initializer.php
r915533 r918102 28 28 $adminUrl = admin_url(); 29 29 $homeUrl = set_url_scheme( home_url() ); 30 31 30 // Front js script 32 31 $settings = array( … … 36 35 'apiKeySearch' => Registry::instance()->getApiKeySearch(), 37 36 'indexName' => Registry::instance()->getDefaultIndex(), 38 'showExcerpt' => FALSE, 37 'showExcerpt' => 0, // Should be an Integer 0 | 1 38 'indexTaxonomies' => (int)Registry::instance()->indexTaxonomies(), // Should be an Integer 0 | 1 39 'taxonomiesToIndex' => (Registry::instance()->indexTaxonomies()) ? FieldsHelper::getTaxonomiesToIndex() : array(), 40 'labels' => array( 'taxonomies' => FieldsHelper::getTaxonomyLabels(), 'posts' => __('Posts') ) 39 41 ); 40 42 wp_localize_script( 'mvnAlgoliaSearch', 'mvnAlgSettings', $settings, Registry::instance()->getPluginVersion() ); … … 48 50 'inputSearchName' => 's', 49 51 'containerId' => 'mvn-alg-predictions', 50 'showExcerpt' => FALSE,51 52 'postsPerPage' => 5, 52 53 // 'labels' => array( 53 // 'indexationError' => 'There was an error trying to run indexation, please contact to the support team.',54 // 'starting' => 'Starting...',55 // 'indexing' => 'Indexing ',56 // 'complete' => 'Complete!',57 // 'running' => 'Indexation is running as background process, it could take several minutes.',58 // 'removing' => 'Removing unpublish posts from the index',59 // 'postsLabels' => $postLabels,60 54 // ), 61 55 ); -
maven-algolia/trunk/core/registry.php
r915533 r918102 37 37 'appValid' => '0', 38 38 'appSearchValid' => '0', 39 'indexTaxonomies' => '0', 39 40 ); 40 41 … … 274 275 } 275 276 277 public function indexTaxonomies( ) { 278 return (bool)$this->getValue('indexTaxonomies'); 279 } 280 276 281 } -
maven-algolia/trunk/front/assets/scripts/predictions.js
r915533 r918102 2 2 var algolia; 3 3 var that; 4 var algoliaQueries = []; 4 5 var self = { 5 6 initialize: function() { … … 12 13 algolia = new AlgoliaSearch( mvnAlgSettings.appId, mvnAlgSettings.apiKeySearch ); // public credentials 13 14 }, 15 indexTaxonomies: function() { 16 if( typeof mvnAlgSettings.indexTaxonomies !== 'undefined' 17 && parseInt( mvnAlgSettings.indexTaxonomies ) === 1 18 && typeof mvnAlgSettings.taxonomiesToIndex !== 'undefined' 19 && mvnAlgSettings.taxonomiesToIndex ){ 20 return true; 21 } 22 return false; 23 }, 14 24 searchCallback: function(success, content, response) { 15 if ( success && content.results.length > 0 && that.lastQuery === content.results[0].query ) { // do not consider outdated answers 16 var data = []; 17 var posts = content.results[0]; 25 var data = []; 26 var resultIndex = jQuery.inArray( 'posts', algoliaQueries ); 27 if ( success && content.results.length > 0 && that.lastQuery === content.results[resultIndex].query ) { // do not consider outdated answers 28 var posts = content.results[resultIndex]; 18 29 if( posts.hits.length > 0 ){ 19 30 for (var i = 0; i < posts.hits.length; ++i) { 20 31 var hit = posts.hits[i]; 21 data[i]= {32 var hitInfo = { 22 33 label: hit.title, 23 34 value: hit.title, … … 29 40 description: (hit._highlightResult.content && hit._highlightResult.content.value) || hit.content, 30 41 date: hit.date, 31 featuredImage: hit.featuredImage 42 featuredImage: hit.featuredImage, 43 category: (mvnAlgSettings.labels.posts) ? mvnAlgSettings.labels.posts : '' // Posts LABEL 32 44 }; 45 data.push( hitInfo ); 33 46 } 34 47 } 35 response(data);36 48 } 49 if( self.indexTaxonomies() ){ 50 jQuery.each(mvnAlgSettings.taxonomiesToIndex, function(index, element){ 51 resultIndex = jQuery.inArray( index, algoliaQueries ); 52 var terms = content.results[resultIndex]; 53 if( terms.hits.length > 0 ){ 54 for (var i = 0; i < terms.hits.length; ++i) { 55 var hit = terms.hits[i]; 56 var hitInfo = { 57 label: hit.title, 58 value: hit.objectID, 59 title: (hit._highlightResult.title && hit._highlightResult.title.value) || hit.title, 60 permalink: hit.permalink, 61 featuredImage: hit.image, 62 termId: hit.termId, 63 parent: hit.parent, 64 postsRelated: hit.postsRelated, 65 taxonomy: hit.taxonomy, 66 category: (mvnAlgSettings.labels.taxonomies[index]) ? mvnAlgSettings.labels.taxonomies[index] : '' // TAXONOMY LABEL 67 }; 68 data.push( hitInfo ); 69 } 70 } 71 }); 72 } 73 response(data); 37 74 }, 38 75 getDisplayPost: function( hit ) { … … 47 84 htmlPost += ' <br /><span class="mvn-alg-ls-item-cats">' + hit.categories.join() + '</span>'; 48 85 } 49 if( mvnAlgSe archVars.showExcerpt && typeof hit.excerpt !== 'undefined' && hit.excerpt ){86 if( mvnAlgSettings.showExcerpt && typeof hit.excerpt !== 'undefined' && hit.excerpt ){ 50 87 htmlPost += ' <br /><span class="mvn-alg-ls-item-desc">' + hit.excerpt + '</span>'; 51 88 } … … 53 90 return htmlPost; 54 91 }, 92 getDisplayTerm: function( hit ) { 93 var html = ''; 94 html += '<a href="' + hit.permalink + '" class="mvn-alg-ls-item-title">'; 95 if( typeof hit.featuredImage !== 'undefined' && hit.featuredImage ){ 96 html += ' <img src="'+hit.featuredImage+'" width="40" height="60" />'; 97 } 98 html += ' <strong>' + hit.title + '</strong>'; 99 html += '</a>'; 100 return html; 101 }, 55 102 search: function( request, response ) { 56 103 if( typeof algolia !== 'undefined' ){ 104 algoliaQueries = []; 57 105 algolia.startQueriesBatch(); 106 58 107 algolia.addQueryInBatch( mvnAlgSettings.indexName, request.term, { 59 108 attributesToRetrieve: ['objectID', 'title', 'permalink', 'excerpt', 'content', 'date', 'featuredImage' , 'category', '_tags'], 60 109 hitsPerPage: mvnAlgSearchVars.postsPerPage 61 110 }); 111 algoliaQueries.push( 'posts' ); 112 113 if( self.indexTaxonomies() ){ 114 jQuery.each(mvnAlgSettings.taxonomiesToIndex, function(index, element){ 115 if( typeof element.indexName !== 'undefined' && element.indexName ){ 116 algolia.addQueryInBatch( element.indexName, request.term, { 117 hitsPerPage: mvnAlgSearchVars.postsPerPage 118 }); 119 algoliaQueries.push( index ); 120 } 121 }); 122 } 123 62 124 algolia.sendQueriesBatch(function(success, content) { 63 125 // forward 'response' to Algolia's callback in order to call it with up-to-date results … … 73 135 jQuery(document).ready(function($) { 74 136 mvnAlgoliaPrediction.initialize(); 75 76 137 // The autocomplete function is called on the input textbox with id input_element 77 138 $("input[name='" + mvnAlgSearchVars.inputSearchName + "']").each(function(index){ … … 87 148 $(this).val(ui.item.label); 88 149 return false; 89 },90 // This function is executed when the users focuses on a item with the mouse91 // or keyboard92 focus: function(event, ui) {93 // Sets the text of the input textbox to the title of the object referenced94 // by the focused list item95 $(this).val(ui.item.label);96 return false;97 150 } 98 151 // Here we alter the standard behavior when rendering items in the list 99 }).data("ui-autocomplete")._renderItem = function(ul, item) { 152 }); 153 $(this).autocomplete().data("ui-autocomplete")._renderItem = function(ul, item) { 100 154 // ul is the unordered suggestion list 101 155 // item is a object in the data object that was send to the response function 102 156 // after the JSON request 103 157 // We append a custom formatted list item to the suggestion list 104 return $("<li></li>").data("item.autocomplete", item).append(mvnAlgoliaPrediction.getDisplayPost(item)).appendTo(ul); 105 }; 158 var itemHtml = ''; 159 if( typeof item.taxonomy !== 'undefined' ){ 160 itemHtml = mvnAlgoliaPrediction.getDisplayTerm(item); 161 }else{ 162 itemHtml = mvnAlgoliaPrediction.getDisplayPost(item); 163 } 164 return $("<li></li>").data("item.autocomplete", item).append(itemHtml).appendTo(ul); 165 }; 166 // Render menu just if index taxonomies is enabled 167 if( typeof mvnAlgSettings.indexTaxonomies !== 'undefined' && mvnAlgSettings.indexTaxonomies > 0 && typeof mvnAlgSettings.taxonomiesToIndex !== 'undefined' ){ 168 169 $(this).autocomplete().data("ui-autocomplete")._renderMenu = function(ul, items) { 170 var that = this, 171 currentCategory = ""; 172 $.each(items, function(index, item) { 173 if ( item.category && item.category !== currentCategory) { 174 ul.append("<li class='ui-autocomplete-category'><span>" + item.category + "</span></li>"); 175 currentCategory = item.category; 176 } 177 that._renderItemData(ul, item); 178 }); 179 }; 180 } 106 181 }); 107 182 }); -
maven-algolia/trunk/lib/algoliasearch.min.js
r915533 r918102 1 1 /*! 2 * algoliasearch 2. 4.62 * algoliasearch 2.5.1 3 3 * https://github.com/algolia/algoliasearch-client-js 4 4 * Copyright 2014 Algolia SAS; Licensed MIT 5 5 */ 6 6 7 function AlgoliaExplainResults(a,b,c){function d(a,b){var c=[];if("object"==typeof a&&"matchedWords"in a&&"value"in a){for(var e=!1,f=0;f<a.matchedWords.length;++f){var g=a.matchedWords[f];g in b||(b[g]=1,e=!0)}e&&c.push(a.value)}else if("[object Array]"===Object.prototype.toString.call(a))for(var h=0;h<a.length;++h){var i=d(a[h],b);c=c.concat(i)}else if("object"==typeof a)for(var j in a)a.hasOwnProperty(j)&&(c=c.concat(d(a[j],b)));return c}function e(a,b,c){var f=a._highlightResult||a;if(-1===c.indexOf("."))return c in f?d(f[c],b):[];for(var g=c.split("."),h=f,i=0;i<g.length;++i){if("[object Array]"===Object.prototype.toString.call(h)){for(var j=[],k=0;k<h.length;++k)j=j.concat(e(h[k],b,g.slice(i).join(".")));return j}if(!(g[i]in h))return[];h=h[g[i]]}return d(h,b)}var f={},g={},h=e(a,g,b);if(f.title=h.length>0?h[0]:"",f.subtitles=[],"undefined"!=typeof c)for(var i=0;i<c.length;++i)for(var j=e(a,g,c[i]),k=0;k<j.length;++k)f.subtitles.push({attr:c[i],value:j[k]});return f}var ALGOLIA_VERSION="2. 4.6",AlgoliaSearch=function(a,b,c,d,e){this.applicationID=a,this.apiKey=b,this._isUndefined(e)&&(e=[a+"-1.algolia.io",a+"-2.algolia.io",a+"-3.algolia.io"]),this.hosts=[];for(var f=0;f<e.length;++f)Math.random()>.5&&this.hosts.reverse(),this._isUndefined(c)||null==c?this.hosts.push(("https:"==document.location.protocol?"https":"http")+"://"+e[f]):"https"===c||"HTTPS"===c?this.hosts.push("https://"+e[f]):this.hosts.push("http://"+e[f]);Math.random()>.5&&this.hosts.reverse(),(this._isUndefined(d)||d)&&this._jsonRequest({method:"GET",url:"/1/isalive"}),this.extraHeaders=[]};AlgoliaSearch.prototype={deleteIndex:function(a,b){this._jsonRequest({method:"DELETE",url:"/1/indexes/"+encodeURIComponent(a),callback:b})},moveIndex:function(a,b,c){var d={operation:"move",destination:b};this._jsonRequest({method:"POST",url:"/1/indexes/"+encodeURIComponent(a)+"/operation",body:d,callback:c})},copyIndex:function(a,b,c){var d={operation:"copy",destination:b};this._jsonRequest({method:"POST",url:"/1/indexes/"+encodeURIComponent(a)+"/operation",body:d,callback:c})},getLogs:function(a,b,c){this._isUndefined(b)&&(b=0),this._isUndefined(c)&&(c=10),this._jsonRequest({method:"GET",url:"/1/logs?offset="+b+"&length="+c,callback:a})},listIndexes:function(a){this._jsonRequest({method:"GET",url:"/1/indexes/",callback:a})},initIndex:function(a){return new this.Index(this,a)},listUserKeys:function(a){this._jsonRequest({method:"GET",url:"/1/keys",callback:a})},getUserKeyACL:function(a,b){this._jsonRequest({method:"GET",url:"/1/keys/"+a,callback:b})},deleteUserKey:function(a,b){this._jsonRequest({method:"DELETE",url:"/1/keys/"+a,callback:b})},addUserKey:function(a,b){var c={};c.acl=a,this._jsonRequest({method:"POST",url:"/1/keys",body:c,callback:b})},addUserKeyWithValidity:function(a,b,c,d,e){var f=this,g={};g.acl=a,g.validity=b,g.maxQueriesPerIPPerHour=c,g.maxHitsPerQuery=d,this._jsonRequest({method:"POST",url:"/1/indexes/"+f.indexName+"/keys",body:g,callback:e})},setSecurityTags:function(a){if("[object Array]"===Object.prototype.toString.call(a)){for(var b=[],c=0;c<a.length;++c)if("[object Array]"===Object.prototype.toString.call(a[c])){for(var d=[],e=0;e<a[c].length;++e)d.push(a[c][e]);b.push("("+d.join(",")+")")}else b.push(a[c]);a=b.join(",")}this.tagFilters=a},setUserToken:function(a){this.userToken=a},startQueriesBatch:function(){this.batch=[]},addQueryInBatch:function(a,b,c){var d="query="+encodeURIComponent(b);this._isUndefined(c)||null==c||(d=this._getSearchParams(c,d)),this.batch.push({indexName:a,params:d})},clearCache:function(){this.cache={}},sendQueriesBatch:function(a,b){var c=this,d={requests:[],apiKey:this.apiKey,appID:this.applicationID};this.userToken&&(d["X-Algolia-UserToken"]=this.userToken),this.tagFilters&&(d["X-Algolia-TagFilters"]=this.tagFilters);for(var e=0;e<c.batch.length;++e)d.requests.push(c.batch[e]);if(window.clearTimeout(c.onDelayTrigger),!this._isUndefined(b)&&null!=b&&b>0){var f=window.setTimeout(function(){c._sendQueriesBatch(d,a)},b);c.onDelayTrigger=f}else this._sendQueriesBatch(d,a)},Index:function(a,b){this.indexName=b,this.as=a,this.typeAheadArgs=null,this.typeAheadValueOption=null},setExtraHeader:function(a,b){this.extraHeaders.push({key:a,value:b})},_sendQueriesBatch:function(a,b){this._jsonRequest({cache:this.cache,method:"POST",url:"/1/indexes/*/queries",body:a,callback:b})},_jsonRequest:function(a){var b=this,c=a.callback,d=null,e=a.url;if(this._isUndefined(a.body)||(e=a.url+"_body_"+JSON.stringify(a.body)),!this._isUndefined(a.cache)&&(d=a.cache,!this._isUndefined(d[e])))return this._isUndefined(c)||c(!0,d[e]),void 0;var f=function(g){var h=0;return b._isUndefined(g)||(h=g),b.hosts.length<=h?(b._isUndefined(c)||c(!1,{message:"Cannot contact server"}),void 0):(a.callback=function(g,i,j,k){i||b._isUndefined(k)||console.log("Error: "+k.message),i&&!b._isUndefined(a.cache)&&(d[e]=k),!i&&g&&h+1<b.hosts.length?f(h+1):b._isUndefined(c)||c(i,k)},a.hostname=b.hosts[h],b._jsonRequestByHost(a),void 0)};f()},_jsonRequestByHost:function(a){var b=null,c=this;this._isUndefined(a.body)||(b=JSON.stringify(a.body));var d=a.hostname+a.url,e=null;if(e=new XMLHttpRequest,"withCredentials"in e){e.open(a.method,d,!0),e.setRequestHeader("X-Algolia-API-Key",this.apiKey),e.setRequestHeader("X-Algolia-Application-Id",this.applicationID);for(var f=0;f<this.extraHeaders.length;++f)e.setRequestHeader(this.extraHeaders[f].key,this.extraHeaders[f].value);null!=b&&e.setRequestHeader("Content-type","application/json")}else"undefined"!=typeof XDomainRequest?(e=new XDomainRequest,e.open(a.method,d)):console.log("your browser is too old to support CORS requests");e.send(b),e.onload=function(b){if(c._isUndefined(b)||null==b.target)a.callback(!1,!0,b,JSON.parse(e.responseText));else{var d=0===b.target.status||503===b.target.status,f=200===b.target.status||201===b.target.status;a.callback(d,f,b.target,null!=b.target.response?JSON.parse(b.target.response):null)}},e.onerror=function(){a.callback(!0,!1,null,{message:"Could not connect to Host"})}},_getSearchParams:function(a,b){if(this._isUndefined(a)||null==a)return b;for(var c in a)null!=c&&a.hasOwnProperty(c)&&(b+=0===b.length?"?":"&",b+=c+"="+encodeURIComponent("[object Array]"===Object.prototype.toString.call(a[c])?JSON.stringify(a[c]):a[c]));return b},_isUndefined:function(a){return void 0===a},applicationID:null,apiKey:null,tagFilters:null,userToken:null,hosts:[],cache:{},extraHeaders:[]},AlgoliaSearch.prototype.Index.prototype={clearCache:function(){this.cache={}},addObject:function(a,b,c){var d=this;this.as._isUndefined(c)?this.as._jsonRequest({method:"POST",url:"/1/indexes/"+encodeURIComponent(d.indexName),body:a,callback:b}):this.as._jsonRequest({method:"PUT",url:"/1/indexes/"+encodeURIComponent(d.indexName)+"/"+encodeURIComponent(c),body:a,callback:b})},addObjects:function(a,b){for(var c=this,d={requests:[]},e=0;e<a.length;++e){var f={action:"addObject",body:a[e]};d.requests.push(f)}this.as._jsonRequest({method:"POST",url:"/1/indexes/"+encodeURIComponent(c.indexName)+"/batch",body:d,callback:b})},getObject:function(a,b,c){var d=this,e="";if(!this.as._isUndefined(c)){e="?attributes=";for(var f=0;f<c.length;++f)0!==f&&(e+=","),e+=c[f]}this.as._jsonRequest({method:"GET",url:"/1/indexes/"+encodeURIComponent(d.indexName)+"/"+encodeURIComponent(a)+e,callback:b})},partialUpdateObject:function(a,b){var c=this;this.as._jsonRequest({method:"POST",url:"/1/indexes/"+encodeURIComponent(c.indexName)+"/"+encodeURIComponent(a.objectID)+"/partial",body:a,callback:b})},partialUpdateObjects:function(a,b){for(var c=this,d={requests:[]},e=0;e<a.length;++e){var f={action:"partialUpdateObject",objectID:a[e].objectID,body:a[e]};d.requests.push(f)}this.as._jsonRequest({method:"POST",url:"/1/indexes/"+encodeURIComponent(c.indexName)+"/batch",body:d,callback:b})},saveObject:function(a,b){var c=this;this.as._jsonRequest({method:"PUT",url:"/1/indexes/"+encodeURIComponent(c.indexName)+"/"+encodeURIComponent(a.objectID),body:a,callback:b})},saveObjects:function(a,b){for(var c=this,d={requests:[]},e=0;e<a.length;++e){var f={action:"updateObject",objectID:a[e].objectID,body:a[e]};d.requests.push(f)}this.as._jsonRequest({method:"POST",url:"/1/indexes/"+encodeURIComponent(c.indexName)+"/batch",body:d,callback:b})},deleteObject:function(a,b){if(null==a||0===a.length)return b(!1,{message:"empty objectID"}),void 0;var c=this;this.as._jsonRequest({method:"DELETE",url:"/1/indexes/"+encodeURIComponent(c.indexName)+"/"+encodeURIComponent(a),callback:b})},search:function(a,b,c,d){var e=this,f="query="+encodeURIComponent(a);if(this.as._isUndefined(c)||null==c||(f=this.as._getSearchParams(c,f)),window.clearTimeout(e.onDelayTrigger),!this.as._isUndefined(d)&&null!=d&&d>0){var g=window.setTimeout(function(){e._search(f,b)},d);e.onDelayTrigger=g}else this._search(f,b)},browse:function(a,b,c){var d=this,e="?page="+a;_.isUndefined(c)||(e+="&hitsPerPage="+c),this.as._jsonRequest({method:"GET",url:"/1/indexes/"+encodeURIComponent(d.indexName)+"/browse"+e,callback:b})},ttAdapter:function(a){var b=this;return function(c,d){b.search(c,function(a,b){a&&d(b.hits)},a)}},waitTask:function(a,b){var c=this;this.as._jsonRequest({method:"GET",url:"/1/indexes/"+encodeURIComponent(c.indexName)+"/task/"+a,callback:function(d,e){d?"published"===e.status?b(!0,e):setTimeout(function(){c.waitTask(a,b)},100):b(!1,e)}})},clearIndex:function(a){var b=this;this.as._jsonRequest({method:"POST",url:"/1/indexes/"+encodeURIComponent(b.indexName)+"/clear",callback:a})},getSettings:function(a){var b=this;this.as._jsonRequest({method:"GET",url:"/1/indexes/"+encodeURIComponent(b.indexName)+"/settings",callback:a})},setSettings:function(a,b){var c=this;this.as._jsonRequest({method:"PUT",url:"/1/indexes/"+encodeURIComponent(c.indexName)+"/settings",body:a,callback:b})},listUserKeys:function(a){var b=this;this.as._jsonRequest({method:"GET",url:"/1/indexes/"+encodeURIComponent(b.indexName)+"/keys",callback:a})},getUserKeyACL:function(a,b){var c=this;this.as._jsonRequest({method:"GET",url:"/1/indexes/"+encodeURIComponent(c.indexName)+"/keys/"+a,callback:b})},deleteUserKey:function(a,b){var c=this;this.as._jsonRequest({method:"DELETE",url:"/1/indexes/"+encodeURIComponent(c.indexName)+"/keys/"+a,callback:b})},addUserKey:function(a,b){var c=this,d={};d.acl=a,this.as._jsonRequest({method:"POST",url:"/1/indexes/"+encodeURIComponent(c.indexName)+"/keys",body:d,callback:b})},addUserKeyWithValidity:function(a,b,c,d,e){var f=this,g={};g.acl=a,g.validity=b,g.maxQueriesPerIPPerHour=c,g.maxHitsPerQuery=d,this.as._jsonRequest({method:"POST",url:"/1/indexes/"+encodeURIComponent(f.indexName)+"/keys",body:g,callback:e})},_search:function(a,b){var c={params:a,apiKey:this.as.apiKey,appID:this.as.applicationID};this.as.tagFilters&&(c["X-Algolia-TagFilters"]=this.as.tagFilters),this.as.userToken&&(c["X-Algolia-UserToken"]=this.as.userToken),this.as._jsonRequest({cache:this.cache,method:"POST",url:"/1/indexes/"+encodeURIComponent(this.indexName)+"/query",body:c,callback:b})},as:null,indexName:null,cache:{},typeAheadArgs:null,typeAheadValueOption:null,emptyConstructor:function(){}},function(){var a,b=function(a){a=a||{};for(var b=1;b<arguments.length;b++)if(arguments[b])for(var c in arguments[b])arguments[b].hasOwnProperty(c)&&(a[c]=arguments[b][c]);return a};window.AlgoliaSearchHelper=function(c,d,e){var f={facets:[],disjunctiveFacets:[],hitsPerPage:20};this.init(c,d,b({},f,e)),a=this},AlgoliaSearchHelper.prototype={init:function(a,b,c){this.client=a,this.index=b,this.options=c,this.page=0,this.refinements={},this.disjunctiveRefinements={}},search:function(a,b,c){this.q=a,this.searchCallback=b,this.searchParams=c||{},this.page=this.page||0,this.refinements=this.refinements||{},this.disjunctiveRefinements=this.disjunctiveRefinements||{},this._search()},toggleRefine:function(a,b){for(var c=0;c<this.options.facets.length;++c)if(this.options.facets[c]==a){var d=a+":"+b;return this.refinements[d]=!this.refinements[d],this.page=0,this._search(),!0}this.disjunctiveRefinements[a]=this.disjunctiveRefinements[a]||{};for(var e=0;e<this.options.disjunctiveFacets.length;++e)if(this.options.disjunctiveFacets[e]==a)return this.disjunctiveRefinements[a][b]=!this.disjunctiveRefinements[a][b],this.page=0,this._search(),!0;return!1},isRefined:function(a,b){var c=a+":"+b;return this.refinements[c]?!0:this.disjunctiveRefinements[a]&&this.disjunctiveRefinements[a][b]?!0:!1},nextPage:function(){this._gotoPage(this.page+1)},previousPage:function(){this.page>0&&this._gotoPage(this.page-1)},_gotoPage:function(a){this.page=a,this._search()},_search:function(){this.client.startQueriesBatch(),this.client.addQueryInBatch(this.index,this.q,this._getHitsSearchParams());for(var b=0;b<this.options.disjunctiveFacets.length;++b)this.client.addQueryInBatch(this.index,this.q,this._getDisjunctiveFacetSearchParams(this.options.disjunctiveFacets[b]));this.client.sendQueriesBatch(function(b,c){if(!b)return a.searchCallback(!1,c),void 0;var d=c.results[0];d.disjunctiveFacets={};for(var e=1;e<c.results.length;++e)for(var f in c.results[e].facets)if(d.disjunctiveFacets[f]=c.results[e].facets[f],a.disjunctiveRefinements[f])for(var g in a.disjunctiveRefinements[f])!d.disjunctiveFacets[f][g]&&a.disjunctiveRefinements[f][g]&&(d.disjunctiveFacets[f][g]=0);a.searchCallback(!0,d)})},_getHitsSearchParams:function(){return b({},this.searchParams,{hitsPerPage:this.options.hitsPerPage,page:this.page,facets:this.options.facets,facetFilters:this._getFacetFilters()})},_getDisjunctiveFacetSearchParams:function(a){return b({},this.searchParams,{hitsPerPage:1,page:0,facets:a,facetFilters:this._getFacetFilters(a)})},_getFacetFilters:function(a){var b=[];for(var c in this.refinements)this.refinements[c]&&b.push(c);for(var d in this.disjunctiveRefinements)if(d!=a){var e=[];for(var f in this.disjunctiveRefinements[d])this.disjunctiveRefinements[d][f]&&e.push(d+":"+f);e.length>0&&b.push(e)}return b}}}();7 function AlgoliaExplainResults(a,b,c){function d(a,b){var c=[];if("object"==typeof a&&"matchedWords"in a&&"value"in a){for(var e=!1,f=0;f<a.matchedWords.length;++f){var g=a.matchedWords[f];g in b||(b[g]=1,e=!0)}e&&c.push(a.value)}else if("[object Array]"===Object.prototype.toString.call(a))for(var h=0;h<a.length;++h){var i=d(a[h],b);c=c.concat(i)}else if("object"==typeof a)for(var j in a)a.hasOwnProperty(j)&&(c=c.concat(d(a[j],b)));return c}function e(a,b,c){var f=a._highlightResult||a;if(-1===c.indexOf("."))return c in f?d(f[c],b):[];for(var g=c.split("."),h=f,i=0;i<g.length;++i){if("[object Array]"===Object.prototype.toString.call(h)){for(var j=[],k=0;k<h.length;++k)j=j.concat(e(h[k],b,g.slice(i).join(".")));return j}if(!(g[i]in h))return[];h=h[g[i]]}return d(h,b)}var f={},g={},h=e(a,g,b);if(f.title=h.length>0?h[0]:"",f.subtitles=[],"undefined"!=typeof c)for(var i=0;i<c.length;++i)for(var j=e(a,g,c[i]),k=0;k<j.length;++k)f.subtitles.push({attr:c[i],value:j[k]});return f}var ALGOLIA_VERSION="2.5.1",AlgoliaSearch=function(a,b,c,d,e){var f=this;this.applicationID=a,this.apiKey=b,this._isUndefined(e)&&(e=[a+"-1.algolia.io",a+"-2.algolia.io",a+"-3.algolia.io"]),this.hosts=[];for(var g=0;g<e.length;++g)Math.random()>.5&&this.hosts.reverse(),this._isUndefined(c)||null==c?this.hosts.push(("https:"==document.location.protocol?"https":"http")+"://"+e[g]):"https"===c||"HTTPS"===c?this.hosts.push("https://"+e[g]):this.hosts.push("http://"+e[g]);Math.random()>.5&&this.hosts.reverse(),this.jsonp=null,this.jsonpWait=0,this._jsonRequest({method:"GET",url:"/1/isalive",callback:function(a){f.jsonp=!a}}),this.extraHeaders=[]};AlgoliaSearch.prototype={deleteIndex:function(a,b){this._jsonRequest({method:"DELETE",url:"/1/indexes/"+encodeURIComponent(a),callback:b})},moveIndex:function(a,b,c){var d={operation:"move",destination:b};this._jsonRequest({method:"POST",url:"/1/indexes/"+encodeURIComponent(a)+"/operation",body:d,callback:c})},copyIndex:function(a,b,c){var d={operation:"copy",destination:b};this._jsonRequest({method:"POST",url:"/1/indexes/"+encodeURIComponent(a)+"/operation",body:d,callback:c})},getLogs:function(a,b,c){this._isUndefined(b)&&(b=0),this._isUndefined(c)&&(c=10),this._jsonRequest({method:"GET",url:"/1/logs?offset="+b+"&length="+c,callback:a})},listIndexes:function(a){this._jsonRequest({method:"GET",url:"/1/indexes",callback:a})},initIndex:function(a){return new this.Index(this,a)},listUserKeys:function(a){this._jsonRequest({method:"GET",url:"/1/keys",callback:a})},getUserKeyACL:function(a,b){this._jsonRequest({method:"GET",url:"/1/keys/"+a,callback:b})},deleteUserKey:function(a,b){this._jsonRequest({method:"DELETE",url:"/1/keys/"+a,callback:b})},addUserKey:function(a,b){var c={};c.acl=a,this._jsonRequest({method:"POST",url:"/1/keys",body:c,callback:b})},addUserKeyWithValidity:function(a,b,c,d,e){var f=this,g={};g.acl=a,g.validity=b,g.maxQueriesPerIPPerHour=c,g.maxHitsPerQuery=d,this._jsonRequest({method:"POST",url:"/1/indexes/"+f.indexName+"/keys",body:g,callback:e})},setSecurityTags:function(a){if("[object Array]"===Object.prototype.toString.call(a)){for(var b=[],c=0;c<a.length;++c)if("[object Array]"===Object.prototype.toString.call(a[c])){for(var d=[],e=0;e<a[c].length;++e)d.push(a[c][e]);b.push("("+d.join(",")+")")}else b.push(a[c]);a=b.join(",")}this.tagFilters=a},setUserToken:function(a){this.userToken=a},startQueriesBatch:function(){this.batch=[]},addQueryInBatch:function(a,b,c){var d="query="+encodeURIComponent(b);this._isUndefined(c)||null==c||(d=this._getSearchParams(c,d)),this.batch.push({indexName:a,params:d})},clearCache:function(){this.cache={}},sendQueriesBatch:function(a,b){var c=this,d={requests:[],apiKey:this.apiKey,appID:this.applicationID};this.userToken&&(d["X-Algolia-UserToken"]=this.userToken),this.tagFilters&&(d["X-Algolia-TagFilters"]=this.tagFilters);for(var e=0;e<c.batch.length;++e)d.requests.push(c.batch[e]);if(window.clearTimeout(c.onDelayTrigger),!this._isUndefined(b)&&null!=b&&b>0){var f=window.setTimeout(function(){c._sendQueriesBatch(d,a)},b);c.onDelayTrigger=f}else this._sendQueriesBatch(d,a)},Index:function(a,b){this.indexName=b,this.as=a,this.typeAheadArgs=null,this.typeAheadValueOption=null},setExtraHeader:function(a,b){this.extraHeaders.push({key:a,value:b})},_sendQueriesBatch:function(a,b){if(null==this.jsonp){var c=this;return this._waitReady(function(){c._sendQueriesBatch(a,b)}),void 0}if(this.jsonp){for(var d="",e=0;e<a.requests.length;++e){var f="/1/indexes/"+encodeURIComponent(a.requests[e].indexName)+"?"+a.requests[e].params;d+=e+"="+encodeURIComponent(f)+"&"}this._jsonRequest({cache:this.cache,method:"GET",jsonp:!0,url:"/1/indexes/*",body:{params:d},callback:b})}else this._jsonRequest({cache:this.cache,method:"POST",url:"/1/indexes/*/queries",body:a,callback:b})},_jsonRequest:function(a){var b=this,c=a.callback,d=null,e=a.url;if(this._isUndefined(a.body)||(e=a.url+"_body_"+JSON.stringify(a.body)),!this._isUndefined(a.cache)&&(d=a.cache,!this._isUndefined(d[e])))return this._isUndefined(c)||c(!0,d[e]),void 0;var f=function(g){var h=0;return b._isUndefined(g)||(h=g),b.hosts.length<=h?(b._isUndefined(c)||c(!1,{message:"Cannot contact server"}),void 0):(a.callback=function(g,i,j,k){i||b._isUndefined(k)||window.console&&console.log("Error: "+k.message),i&&!b._isUndefined(a.cache)&&(d[e]=k),!i&&g&&h+1<b.hosts.length?f(h+1):b._isUndefined(c)||c(i,k)},a.hostname=b.hosts[h],b._jsonRequestByHost(a),void 0)};f()},_jsonRequestByHost:function(a){var b=this,c=a.hostname+a.url;if(this.jsonp){if(!a.jsonp)return a.callback(!0,!1,null,{message:"Method "+a.method+" "+c+" is not supported by JSONP."}),void 0;this.jsonpCounter=this.jsonpCounter||0,this.jsonpCounter+=1;var d="algoliaJSONP_"+this.jsonpCounter;window[d]=function(b){a.callback(!1,!0,null,b);try{delete window[d]}catch(c){window[d]=void 0}};var e=document.createElement("script");e.type="text/javascript",e.src=c+"?callback="+d+","+this.applicationID+","+this.apiKey,a["X-Algolia-TagFilters"]&&(e.src+="&X-Algolia-TagFilters="+a["X-Algolia-TagFilters"]),a["X-Algolia-UserToken"]&&(e.src+="&X-Algolia-UserToken="+a["X-Algolia-UserToken"]),a.body&&a.body.params&&(e.src+="&"+a.body.params);var f=document.getElementsByTagName("head")[0];e.onerror=function(){a.callback(!0,!1,null,{message:"Failed to load JSONP script."}),f.removeChild(e);try{delete window[d]}catch(b){window[d]=void 0}};var g=!1;e.onload=e.onreadystatechange=function(){if(!(g||this.readyState&&"loaded"!=this.readyState&&"complete"!=this.readyState)){if(g=!0,"undefined"==typeof window[d+"_loaded"]){a.callback(!0,!1,null,{message:"Failed to load JSONP script."});try{delete window[d]}catch(b){window[d]=void 0}}else try{delete window[d+"_loaded"]}catch(b){window[d+"_loaded"]=void 0}e.onload=e.onreadystatechange=null,f.removeChild(e)}},f.appendChild(e)}else{var h=null;this._isUndefined(a.body)||(h=JSON.stringify(a.body));var i=window.XMLHttpRequest?new XMLHttpRequest:{};if("withCredentials"in i){i.open(a.method,c,!0),i.setRequestHeader("X-Algolia-API-Key",this.apiKey),i.setRequestHeader("X-Algolia-Application-Id",this.applicationID);for(var j=0;j<this.extraHeaders.length;++j)i.setRequestHeader(this.extraHeaders[j].key,this.extraHeaders[j].value);null!=h&&i.setRequestHeader("Content-type","application/json")}else{if("undefined"==typeof XDomainRequest)return window.console&&console.log("Your browser is too old to support CORS requests"),a.callback(!1,!1,null,{message:"CORS not supported"}),void 0;i=new XDomainRequest,i.open(a.method,c)}i.send(h),i.onload=function(c){if(b._isUndefined(c)||null==c.target)a.callback(!1,!0,c,JSON.parse(i.responseText));else{var d=0===c.target.status||503===c.target.status,e=200===c.target.status||201===c.target.status;a.callback(d,e,c.target,null!=c.target.response?JSON.parse(c.target.response):null)}},i.onerror=function(b){a.callback(!0,!1,null,{message:"Could not connect to host",error:b})}}},_waitReady:function(a){null==this.jsonp&&(this.jsonpWait+=100,this.jsonpWait>2e3&&(this.jsonp=!0),setTimeout(a,100))},_getSearchParams:function(a,b){if(this._isUndefined(a)||null==a)return b;for(var c in a)null!=c&&a.hasOwnProperty(c)&&(b+=0===b.length?"?":"&",b+=c+"="+encodeURIComponent("[object Array]"===Object.prototype.toString.call(a[c])?JSON.stringify(a[c]):a[c]));return b},_isUndefined:function(a){return void 0===a},applicationID:null,apiKey:null,tagFilters:null,userToken:null,hosts:[],cache:{},extraHeaders:[]},AlgoliaSearch.prototype.Index.prototype={clearCache:function(){this.cache={}},addObject:function(a,b,c){var d=this;this.as._isUndefined(c)?this.as._jsonRequest({method:"POST",url:"/1/indexes/"+encodeURIComponent(d.indexName),body:a,callback:b}):this.as._jsonRequest({method:"PUT",url:"/1/indexes/"+encodeURIComponent(d.indexName)+"/"+encodeURIComponent(c),body:a,callback:b})},addObjects:function(a,b){for(var c=this,d={requests:[]},e=0;e<a.length;++e){var f={action:"addObject",body:a[e]};d.requests.push(f)}this.as._jsonRequest({method:"POST",url:"/1/indexes/"+encodeURIComponent(c.indexName)+"/batch",body:d,callback:b})},getObject:function(a,b,c){if(null==this.as.jsonp){var d=this;return this.as._waitReady(function(){d.getObject(a,b,c)}),void 0}var e=this,f="";if(!this.as._isUndefined(c)){f="?attributes=";for(var g=0;g<c.length;++g)0!==g&&(f+=","),f+=c[g]}this.as._jsonRequest({method:"GET",jsonp:!0,url:"/1/indexes/"+encodeURIComponent(e.indexName)+"/"+encodeURIComponent(a)+f,callback:b})},partialUpdateObject:function(a,b){var c=this;this.as._jsonRequest({method:"POST",url:"/1/indexes/"+encodeURIComponent(c.indexName)+"/"+encodeURIComponent(a.objectID)+"/partial",body:a,callback:b})},partialUpdateObjects:function(a,b){for(var c=this,d={requests:[]},e=0;e<a.length;++e){var f={action:"partialUpdateObject",objectID:a[e].objectID,body:a[e]};d.requests.push(f)}this.as._jsonRequest({method:"POST",url:"/1/indexes/"+encodeURIComponent(c.indexName)+"/batch",body:d,callback:b})},saveObject:function(a,b){var c=this;this.as._jsonRequest({method:"PUT",url:"/1/indexes/"+encodeURIComponent(c.indexName)+"/"+encodeURIComponent(a.objectID),body:a,callback:b})},saveObjects:function(a,b){for(var c=this,d={requests:[]},e=0;e<a.length;++e){var f={action:"updateObject",objectID:a[e].objectID,body:a[e]};d.requests.push(f)}this.as._jsonRequest({method:"POST",url:"/1/indexes/"+encodeURIComponent(c.indexName)+"/batch",body:d,callback:b})},deleteObject:function(a,b){if(null==a||0===a.length)return b(!1,{message:"empty objectID"}),void 0;var c=this;this.as._jsonRequest({method:"DELETE",url:"/1/indexes/"+encodeURIComponent(c.indexName)+"/"+encodeURIComponent(a),callback:b})},search:function(a,b,c,d){var e=this,f="query="+encodeURIComponent(a);if(this.as._isUndefined(c)||null==c||(f=this.as._getSearchParams(c,f)),window.clearTimeout(e.onDelayTrigger),!this.as._isUndefined(d)&&null!=d&&d>0){var g=window.setTimeout(function(){e._search(f,b)},d);e.onDelayTrigger=g}else this._search(f,b)},browse:function(a,b,c){var d=this,e="?page="+a;_.isUndefined(c)||(e+="&hitsPerPage="+c),this.as._jsonRequest({method:"GET",url:"/1/indexes/"+encodeURIComponent(d.indexName)+"/browse"+e,callback:b})},ttAdapter:function(a){var b=this;return function(c,d){b.search(c,function(a,b){a&&d(b.hits)},a)}},waitTask:function(a,b){var c=this;this.as._jsonRequest({method:"GET",url:"/1/indexes/"+encodeURIComponent(c.indexName)+"/task/"+a,callback:function(d,e){d?"published"===e.status?b(!0,e):setTimeout(function(){c.waitTask(a,b)},100):b(!1,e)}})},clearIndex:function(a){var b=this;this.as._jsonRequest({method:"POST",url:"/1/indexes/"+encodeURIComponent(b.indexName)+"/clear",callback:a})},getSettings:function(a){var b=this;this.as._jsonRequest({method:"GET",url:"/1/indexes/"+encodeURIComponent(b.indexName)+"/settings",callback:a})},setSettings:function(a,b){var c=this;this.as._jsonRequest({method:"PUT",url:"/1/indexes/"+encodeURIComponent(c.indexName)+"/settings",body:a,callback:b})},listUserKeys:function(a){var b=this;this.as._jsonRequest({method:"GET",url:"/1/indexes/"+encodeURIComponent(b.indexName)+"/keys",callback:a})},getUserKeyACL:function(a,b){var c=this;this.as._jsonRequest({method:"GET",url:"/1/indexes/"+encodeURIComponent(c.indexName)+"/keys/"+a,callback:b})},deleteUserKey:function(a,b){var c=this;this.as._jsonRequest({method:"DELETE",url:"/1/indexes/"+encodeURIComponent(c.indexName)+"/keys/"+a,callback:b})},addUserKey:function(a,b){var c=this,d={};d.acl=a,this.as._jsonRequest({method:"POST",url:"/1/indexes/"+encodeURIComponent(c.indexName)+"/keys",body:d,callback:b})},addUserKeyWithValidity:function(a,b,c,d,e){var f=this,g={};g.acl=a,g.validity=b,g.maxQueriesPerIPPerHour=c,g.maxHitsPerQuery=d,this.as._jsonRequest({method:"POST",url:"/1/indexes/"+encodeURIComponent(f.indexName)+"/keys",body:g,callback:e})},_search:function(a,b){if(null==this.as.jsonp){var c=this;return this.as._waitReady(function(){c._search(a,b)}),void 0}var d={params:a,apiKey:this.as.apiKey,appID:this.as.applicationID};this.as.tagFilters&&(d["X-Algolia-TagFilters"]=this.as.tagFilters),this.as.userToken&&(d["X-Algolia-UserToken"]=this.as.userToken),this.as.jsonp?this.as._jsonRequest({cache:this.cache,method:"GET",jsonp:!0,url:"/1/indexes/"+encodeURIComponent(this.indexName),body:d,callback:b}):this.as._jsonRequest({cache:this.cache,method:"POST",url:"/1/indexes/"+encodeURIComponent(this.indexName)+"/query",body:d,callback:b})},as:null,indexName:null,cache:{},typeAheadArgs:null,typeAheadValueOption:null,emptyConstructor:function(){}},function(){var a=function(a){a=a||{};for(var b=1;b<arguments.length;b++)if(arguments[b])for(var c in arguments[b])arguments[b].hasOwnProperty(c)&&(a[c]=arguments[b][c]);return a};window.AlgoliaSearchHelper=function(b,c,d){var e={facets:[],disjunctiveFacets:[],hitsPerPage:20};this.init(b,c,a({},e,d))},AlgoliaSearchHelper.prototype={init:function(a,b,c){this.client=a,this.index=b,this.options=c,this.page=0,this.refinements={},this.disjunctiveRefinements={}},search:function(a,b,c){this.q=a,this.searchCallback=b,this.searchParams=c||{},this.page=this.page||0,this.refinements=this.refinements||{},this.disjunctiveRefinements=this.disjunctiveRefinements||{},this._search()},toggleRefine:function(a,b){for(var c=0;c<this.options.facets.length;++c)if(this.options.facets[c]==a){var d=a+":"+b;return this.refinements[d]=!this.refinements[d],this.page=0,this._search(),!0}this.disjunctiveRefinements[a]=this.disjunctiveRefinements[a]||{};for(var e=0;e<this.options.disjunctiveFacets.length;++e)if(this.options.disjunctiveFacets[e]==a)return this.disjunctiveRefinements[a][b]=!this.disjunctiveRefinements[a][b],this.page=0,this._search(),!0;return!1},isRefined:function(a,b){var c=a+":"+b;return this.refinements[c]?!0:this.disjunctiveRefinements[a]&&this.disjunctiveRefinements[a][b]?!0:!1},nextPage:function(){this._gotoPage(this.page+1)},previousPage:function(){this.page>0&&this._gotoPage(this.page-1)},_gotoPage:function(a){this.page=a,this._search()},_search:function(){this.client.startQueriesBatch(),this.client.addQueryInBatch(this.index,this.q,this._getHitsSearchParams());for(var a=0;a<this.options.disjunctiveFacets.length;++a)this.client.addQueryInBatch(this.index,this.q,this._getDisjunctiveFacetSearchParams(this.options.disjunctiveFacets[a]));var b=this;this.client.sendQueriesBatch(function(a,c){if(!a)return b.searchCallback(!1,c),void 0;var d=c.results[0];d.disjunctiveFacets={};for(var e=1;e<c.results.length;++e)for(var f in c.results[e].facets)if(d.disjunctiveFacets[f]=c.results[e].facets[f],b.disjunctiveRefinements[f])for(var g in b.disjunctiveRefinements[f])!d.disjunctiveFacets[f][g]&&b.disjunctiveRefinements[f][g]&&(d.disjunctiveFacets[f][g]=0);b.searchCallback(!0,d)})},_getHitsSearchParams:function(){return a({},this.searchParams,{hitsPerPage:this.options.hitsPerPage,page:this.page,facets:this.options.facets,facetFilters:this._getFacetFilters()})},_getDisjunctiveFacetSearchParams:function(b){return a({},this.searchParams,{hitsPerPage:1,page:0,facets:b,facetFilters:this._getFacetFilters(b)})},_getFacetFilters:function(a){var b=[];for(var c in this.refinements)this.refinements[c]&&b.push(c);for(var d in this.disjunctiveRefinements)if(d!=a){var e=[];for(var f in this.disjunctiveRefinements[d])this.disjunctiveRefinements[d][f]&&e.push(d+":"+f);e.length>0&&b.push(e)}return b}}}(),"object"!=typeof JSON&&(JSON={}),function(){"use strict";function f(a){return 10>a?"0"+a:a}function quote(a){return escapable.lastIndex=0,escapable.test(a)?'"'+a.replace(escapable,function(a){var b=meta[a];return"string"==typeof b?b:"\\u"+("0000"+a.charCodeAt(0).toString(16)).slice(-4)})+'"':'"'+a+'"'}function str(a,b){var c,d,e,f,g,h=gap,i=b[a];switch(i&&"object"==typeof i&&"function"==typeof i.toJSON&&(i=i.toJSON(a)),"function"==typeof rep&&(i=rep.call(b,a,i)),typeof i){case"string":return quote(i);case"number":return isFinite(i)?String(i):"null";case"boolean":case"null":return String(i);case"object":if(!i)return"null";if(gap+=indent,g=[],"[object Array]"===Object.prototype.toString.apply(i)){for(f=i.length,c=0;f>c;c+=1)g[c]=str(c,i)||"null";return e=0===g.length?"[]":gap?"[\n"+gap+g.join(",\n"+gap)+"\n"+h+"]":"["+g.join(",")+"]",gap=h,e}if(rep&&"object"==typeof rep)for(f=rep.length,c=0;f>c;c+=1)"string"==typeof rep[c]&&(d=rep[c],e=str(d,i),e&&g.push(quote(d)+(gap?": ":":")+e));else for(d in i)Object.prototype.hasOwnProperty.call(i,d)&&(e=str(d,i),e&&g.push(quote(d)+(gap?": ":":")+e));return e=0===g.length?"{}":gap?"{\n"+gap+g.join(",\n"+gap)+"\n"+h+"}":"{"+g.join(",")+"}",gap=h,e}}"function"!=typeof Date.prototype.toJSON&&(Date.prototype.toJSON=function(){return isFinite(this.valueOf())?this.getUTCFullYear()+"-"+f(this.getUTCMonth()+1)+"-"+f(this.getUTCDate())+"T"+f(this.getUTCHours())+":"+f(this.getUTCMinutes())+":"+f(this.getUTCSeconds())+"Z":null},String.prototype.toJSON=Number.prototype.toJSON=Boolean.prototype.toJSON=function(){return this.valueOf()});var cx,escapable,gap,indent,meta,rep;"function"!=typeof JSON.stringify&&(escapable=/[\\\"\x00-\x1f\x7f-\x9f\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g,meta={"\b":"\\b"," ":"\\t","\n":"\\n","\f":"\\f","\r":"\\r",'"':'\\"',"\\":"\\\\"},JSON.stringify=function(a,b,c){var d;if(gap="",indent="","number"==typeof c)for(d=0;c>d;d+=1)indent+=" ";else"string"==typeof c&&(indent=c);if(rep=b,b&&"function"!=typeof b&&("object"!=typeof b||"number"!=typeof b.length))throw new Error("JSON.stringify");return str("",{"":a})}),"function"!=typeof JSON.parse&&(cx=/[\u0000\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g,JSON.parse=function(text,reviver){function walk(a,b){var c,d,e=a[b];if(e&&"object"==typeof e)for(c in e)Object.prototype.hasOwnProperty.call(e,c)&&(d=walk(e,c),void 0!==d?e[c]=d:delete e[c]);return reviver.call(a,b,e)}var j;if(text=String(text),cx.lastIndex=0,cx.test(text)&&(text=text.replace(cx,function(a){return"\\u"+("0000"+a.charCodeAt(0).toString(16)).slice(-4)})),/^[\],:{}\s]*$/.test(text.replace(/\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g,"@").replace(/"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g,"]").replace(/(?:^|:|,)(?:\s*\[)+/g,"")))return j=eval("("+text+")"),"function"==typeof reviver?walk({"":j},""):j;throw new SyntaxError("JSON.parse")})}(); -
maven-algolia/trunk/lib/algoliasearch.php
r915533 r918102 23 23 * 24 24 * 25 * VERSION 1.1. 825 * VERSION 1.1.9 26 26 * 27 27 */ … … 29 29 30 30 class AlgoliaException extends \Exception { } 31 32 class ClientContext { 33 function __construct($applicationID, $apiKey, $hostsArray) { 34 $this->applicationID = $applicationID; 35 $this->apiKey = $apiKey; 36 $this->hostsArray = $hostsArray; 37 38 if ($this->applicationID == null || mb_strlen($this->applicationID) == 0) { 39 throw new \Exception('AlgoliaSearch requires an applicationID.'); 40 } 41 if ($this->apiKey == null || mb_strlen($this->apiKey) == 0) { 42 throw new \Exception('AlgoliaSearch requires an apiKey.'); 43 } 44 if ($this->hostsArray == null || count($this->hostsArray) == 0) { 45 throw new \Exception('AlgoliaSearch requires a list of hostnames.'); 46 } else { 47 // randomize elements of hostsArray (act as a kind of load-balancer) 48 shuffle($this->hostsArray); 49 } 50 51 $this->curlMHandle = NULL; 52 $this->adminAPIKey = NULL; 53 $this->endUserIP = NULL; 54 $this->rateLimitAPIKey = NULL; 55 } 56 57 function __destruct() { 58 if ($this->curlMHandle != null) { 59 curl_multi_close($this->curlMHandle); 60 } 61 } 62 63 public function getMHandle($curlHandle) { 64 if ($this->curlMHandle == null) { 65 $this->curlMHandle = curl_multi_init(); 66 } 67 curl_multi_add_handle($this->curlMHandle, $curlHandle); 68 69 return $this->curlMHandle; 70 } 71 72 public function releaseMHandle($curlHandle) { 73 curl_multi_remove_handle($this->curlMHandle, $curlHandle); 74 } 75 76 public function setRateLimit($adminAPIKey, $endUserIP, $rateLimitAPIKey) { 77 $this->adminAPIKey = $adminAPIKey; 78 $this->endUserIP = $endUserIP; 79 $this->rateLimitAPIKey = $rateLimitAPIKey; 80 } 81 82 public function disableRateLimit() { 83 $this->adminAPIKey = NULL; 84 $this->endUserIP = NULL; 85 $this->rateLimitAPIKey = NULL; 86 87 } 88 89 public $applicationID; 90 public $apiKey; 91 public $hostsArray; 92 public $curlMHandle; 93 public $adminAPIKey; 94 } 31 95 32 96 /** … … 42 106 * @param hostsArray the list of hosts that you have received for the service 43 107 */ 44 public function __construct($applicationID, $apiKey, $hostsArray = null) { 45 $this->applicationID = $applicationID; 46 $this->apiKey = $apiKey; 108 function __construct($applicationID, $apiKey, $hostsArray = null) { 47 109 if ($hostsArray == null) { 48 $this-> hostsArray = array($applicationID . "-1.algolia.io", $applicationID . "-2.algolia.io", $applicationID . "-3.algolia.io");110 $this->context = new ClientContext($applicationID, $apiKey, array($applicationID . "-1.algolia.io", $applicationID . "-2.algolia.io", $applicationID . "-3.algolia.io")); 49 111 } else { 50 $this->hostsArray = $hostsArray; 51 } 52 112 $this->context = new ClientContext($applicationID, $apiKey, $hostsArray); 113 } 53 114 if(!function_exists('curl_init')){ 54 115 throw new \Exception('AlgoliaSearch requires the CURL PHP extension.'); 55 116 } 56 57 117 if(!function_exists('json_decode')){ 58 118 throw new \Exception('AlgoliaSearch requires the JSON PHP extension.'); 59 119 } 60 if ($this->applicationID == null || mb_strlen($this->applicationID) == 0) { 61 throw new \Exception('AlgoliaSearch requires an applicationID.'); 62 } 63 if ($this->apiKey == null || mb_strlen($this->apiKey) == 0) { 64 throw new \Exception('AlgoliaSearch requires an apiKey.'); 65 } 66 if ($this->hostsArray == null || count($this->hostsArray) == 0) { 67 throw new \Exception('AlgoliaSearch requires a list of hostnames.'); 68 } else { 69 // randomize elements of hostsArray (act as a kind of load-balancer) 70 shuffle($this->hostsArray); 71 } 72 73 // initialize curl library 74 $this->curlHandle = curl_init(); 75 curl_setopt($this->curlHandle, CURLOPT_HTTPHEADER, array( 76 'X-Algolia-Application-Id: ' . $this->applicationID, 77 'X-Algolia-API-Key: ' . $this->apiKey, 78 'Content-type: application/json' 79 )); 80 curl_setopt($this->curlHandle, CURLOPT_USERAGENT, "Algolia for PHP 1.1.8"); 81 //Return the output instead of printing it 82 curl_setopt($this->curlHandle, CURLOPT_RETURNTRANSFER, true); 83 curl_setopt($this->curlHandle, CURLOPT_FAILONERROR, true); 84 curl_setopt($this->curlHandle, CURLOPT_ENCODING, ''); 85 curl_setopt($this->curlHandle, CURLOPT_SSL_VERIFYPEER, true); 86 curl_setopt($this->curlHandle, CURLOPT_SSL_VERIFYHOST, 2); 87 curl_setopt($this->curlHandle, CURLOPT_CAINFO, __DIR__ . '/resources/ca-bundle.crt'); 120 } 121 122 /* 123 * Release curl handle 124 */ 125 function __destruct() { 88 126 } 89 127 … … 96 134 */ 97 135 public function enableRateLimitForward($adminAPIKey, $endUserIP, $rateLimitAPIKey) { 98 curl_setopt($this->curlHandle, CURLOPT_HTTPHEADER, array( 99 'X-Algolia-Application-Id: ' . $this->applicationID, 100 'X-Algolia-API-Key: ' . $adminAPIKey, 101 'X-Forwarded-For: ' . $endUserIP, 102 'X-Forwarded-API-Key: ' . $rateLimitAPIKey, 103 'Content-type: application/json' 104 )); 136 $this->context->setRateLimit($adminAPIKey, $endUserIP, $rateLimitAPIKey); 105 137 } 106 138 … … 109 141 */ 110 142 public function disableRateLimitForward() { 111 curl_setopt($this->curlHandle, CURLOPT_HTTPHEADER, array( 112 'X-Algolia-Application-Id: ' . $this->applicationID, 113 'X-Algolia-API-Key: ' . $this->apiKey, 114 'Content-type: application/json' 115 )); 143 $this->context->disableRateLimit(); 116 144 } 117 145 … … 135 163 array_push($requests, $req); 136 164 } 137 return AlgoliaUtils_request($this->c urlHandle, $this->hostsArray, "POST", "/1/indexes/*/queries", array(), array("requests" => $requests));165 return AlgoliaUtils_request($this->context, "POST", "/1/indexes/*/queries", array(), array("requests" => $requests)); 138 166 } 139 167 … … 147 175 */ 148 176 public function listIndexes() { 149 return AlgoliaUtils_request($this->c urlHandle, $this->hostsArray, "GET", "/1/indexes/");177 return AlgoliaUtils_request($this->context, "GET", "/1/indexes/"); 150 178 } 151 179 … … 157 185 */ 158 186 public function deleteIndex($indexName) { 159 return AlgoliaUtils_request($this->c urlHandle, $this->hostsArray, "DELETE", "/1/indexes/" . urlencode($indexName));187 return AlgoliaUtils_request($this->context, "DELETE", "/1/indexes/" . urlencode($indexName)); 160 188 } 161 189 … … 167 195 public function moveIndex($srcIndexName, $dstIndexName) { 168 196 $request = array("operation" => "move", "destination" => $dstIndexName); 169 return AlgoliaUtils_request($this->c urlHandle, $this->hostsArray, "POST", "/1/indexes/" . urlencode($srcIndexName) . "/operation", array(), $request);197 return AlgoliaUtils_request($this->context, "POST", "/1/indexes/" . urlencode($srcIndexName) . "/operation", array(), $request); 170 198 } 171 199 … … 177 205 public function copyIndex($srcIndexName, $dstIndexName) { 178 206 $request = array("operation" => "copy", "destination" => $dstIndexName); 179 return AlgoliaUtils_request($this->c urlHandle, $this->hostsArray, "POST", "/1/indexes/" . urlencode($srcIndexName) . "/operation", array(), $request);207 return AlgoliaUtils_request($this->context, "POST", "/1/indexes/" . urlencode($srcIndexName) . "/operation", array(), $request); 180 208 } 181 209 … … 186 214 */ 187 215 public function getLogs($offset = 0, $length = 10, $onlyErrors = false) { 188 return AlgoliaUtils_request($this->c urlHandle, $this->hostsArray, "GET", "/1/logs?offset=" . $offset . "&length=" . $length . "&onlyErrors=" . $onlyErrors);216 return AlgoliaUtils_request($this->context, "GET", "/1/logs?offset=" . $offset . "&length=" . $length . "&onlyErrors=" . $onlyErrors); 189 217 } 190 218 … … 195 223 */ 196 224 public function initIndex($indexName) { 197 return new Index($this->c urlHandle, $this->hostsArray, $indexName);225 return new Index($this->context, $indexName); 198 226 } 199 227 … … 203 231 */ 204 232 public function listUserKeys() { 205 return AlgoliaUtils_request($this->c urlHandle, $this->hostsArray, "GET", "/1/keys");233 return AlgoliaUtils_request($this->context, "GET", "/1/keys"); 206 234 } 207 235 … … 211 239 */ 212 240 public function getUserKeyACL($key) { 213 return AlgoliaUtils_request($this->c urlHandle, $this->hostsArray, "GET", "/1/keys/" . $key);241 return AlgoliaUtils_request($this->context, "GET", "/1/keys/" . $key); 214 242 } 215 243 … … 219 247 */ 220 248 public function deleteUserKey($key) { 221 return AlgoliaUtils_request($this->c urlHandle, $this->hostsArray, "DELETE", "/1/keys/" . $key);249 return AlgoliaUtils_request($this->context, "DELETE", "/1/keys/" . $key); 222 250 } 223 251 … … 254 282 $params['indexes'] = $indexes; 255 283 } 256 return AlgoliaUtils_request($this->c urlHandle, $this->hostsArray, "POST", "/1/keys", array(), $params);284 return AlgoliaUtils_request($this->context, "POST", "/1/keys", array(), $params); 257 285 } 258 286 … … 285 313 } 286 314 287 protected $applicationID; 288 protected $apiKey; 289 protected $hostsArray; 290 protected $curlHandle; 315 protected $context; 291 316 } 292 317 … … 299 324 * Index initialization (You should not call this initialized yourself) 300 325 */ 301 public function __construct($curlHandle, $hostsArray, $indexName) { 302 $this->curlHandle = $curlHandle; 303 $this->hostsArray = $hostsArray; 326 public function __construct($context, $indexName) { 327 $this->context = $context; 304 328 $this->indexName = $indexName; 305 329 $this->urlIndexName = urlencode($indexName); … … 348 372 349 373 if ($objectID === null) { 350 return AlgoliaUtils_request($this->c urlHandle, $this->hostsArray, "POST", "/1/indexes/" . $this->urlIndexName, array(), $content);374 return AlgoliaUtils_request($this->context, "POST", "/1/indexes/" . $this->urlIndexName, array(), $content); 351 375 } else { 352 return AlgoliaUtils_request($this->c urlHandle, $this->hostsArray, "PUT", "/1/indexes/" . $this->urlIndexName . "/" . urlencode($objectID), array(), $content);376 return AlgoliaUtils_request($this->context, "PUT", "/1/indexes/" . $this->urlIndexName . "/" . urlencode($objectID), array(), $content); 353 377 } 354 378 } … … 373 397 $id = urlencode($objectID); 374 398 if ($attributesToRetrieve === null) 375 return AlgoliaUtils_request($this->c urlHandle, $this->hostsArray, "GET", "/1/indexes/" . $this->urlIndexName . "/" . $id);399 return AlgoliaUtils_request($this->context, "GET", "/1/indexes/" . $this->urlIndexName . "/" . $id); 376 400 else 377 return AlgoliaUtils_request($this->c urlHandle, $this->hostsArray, "GET", "/1/indexes/" . $this->urlIndexName . "/" . $id, array("attributes" => $attributesToRetrieve));401 return AlgoliaUtils_request($this->context, "GET", "/1/indexes/" . $this->urlIndexName . "/" . $id, array("attributes" => $attributesToRetrieve)); 378 402 } 379 403 … … 385 409 */ 386 410 public function partialUpdateObject($partialObject) { 387 return AlgoliaUtils_request($this->c urlHandle, $this->hostsArray, "POST", "/1/indexes/" . $this->urlIndexName . "/" . urlencode($partialObject["objectID"]) . "/partial", array(), $partialObject);411 return AlgoliaUtils_request($this->context, "POST", "/1/indexes/" . $this->urlIndexName . "/" . urlencode($partialObject["objectID"]) . "/partial", array(), $partialObject); 388 412 } 389 413 … … 404 428 */ 405 429 public function saveObject($object) { 406 return AlgoliaUtils_request($this->c urlHandle, $this->hostsArray, "PUT", "/1/indexes/" . $this->urlIndexName . "/" . urlencode($object["objectID"]), array(), $object);430 return AlgoliaUtils_request($this->context, "PUT", "/1/indexes/" . $this->urlIndexName . "/" . urlencode($object["objectID"]), array(), $object); 407 431 } 408 432 … … 426 450 throw new \Exception('objectID is mandatory'); 427 451 } 428 return AlgoliaUtils_request($this->c urlHandle, $this->hostsArray, "DELETE", "/1/indexes/" . $this->urlIndexName . "/" . urlencode($objectID));452 return AlgoliaUtils_request($this->context, "DELETE", "/1/indexes/" . $this->urlIndexName . "/" . urlencode($objectID)); 429 453 } 430 454 … … 511 535 } 512 536 $args["query"] = $query; 513 return AlgoliaUtils_request($this->c urlHandle, $this->hostsArray, "GET", "/1/indexes/" . $this->urlIndexName, $args);537 return AlgoliaUtils_request($this->context, "GET", "/1/indexes/" . $this->urlIndexName, $args); 514 538 } 515 539 … … 522 546 */ 523 547 public function browse($page = 0, $hitsPerPage = 1000) { 524 return AlgoliaUtils_request($this->c urlHandle, $this->hostsArray, "GET", "/1/indexes/" . $this->urlIndexName . "/browse",548 return AlgoliaUtils_request($this->context, "GET", "/1/indexes/" . $this->urlIndexName . "/browse", 525 549 array("page" => $page, "hitsPerPage" => $hitsPerPage)); 526 550 } … … 535 559 public function waitTask($taskID, $timeBeforeRetry = 100) { 536 560 while (true) { 537 $res = AlgoliaUtils_request($this->c urlHandle, $this->hostsArray, "GET", "/1/indexes/" . $this->urlIndexName . "/task/" . $taskID);561 $res = AlgoliaUtils_request($this->context, "GET", "/1/indexes/" . $this->urlIndexName . "/task/" . $taskID); 538 562 if ($res["status"] === "published") 539 563 return $res; … … 547 571 */ 548 572 public function getSettings() { 549 return AlgoliaUtils_request($this->c urlHandle, $this->hostsArray, "GET", "/1/indexes/" . $this->urlIndexName . "/settings");573 return AlgoliaUtils_request($this->context, "GET", "/1/indexes/" . $this->urlIndexName . "/settings"); 550 574 } 551 575 … … 554 578 */ 555 579 public function clearIndex() { 556 return AlgoliaUtils_request($this->c urlHandle, $this->hostsArray, "POST", "/1/indexes/" . $this->urlIndexName . "/clear");580 return AlgoliaUtils_request($this->context, "POST", "/1/indexes/" . $this->urlIndexName . "/clear"); 557 581 } 558 582 … … 609 633 */ 610 634 public function setSettings($settings) { 611 return AlgoliaUtils_request($this->c urlHandle, $this->hostsArray, "PUT", "/1/indexes/" . $this->urlIndexName . "/settings", array(), $settings);635 return AlgoliaUtils_request($this->context, "PUT", "/1/indexes/" . $this->urlIndexName . "/settings", array(), $settings); 612 636 } 613 637 … … 617 641 */ 618 642 public function listUserKeys() { 619 return AlgoliaUtils_request($this->c urlHandle, $this->hostsArray, "GET", "/1/indexes/" . $this->urlIndexName . "/keys");643 return AlgoliaUtils_request($this->context, "GET", "/1/indexes/" . $this->urlIndexName . "/keys"); 620 644 } 621 645 … … 625 649 */ 626 650 public function getUserKeyACL($key) { 627 return AlgoliaUtils_request($this->c urlHandle, $this->hostsArray, "GET", "/1/indexes/" . $this->urlIndexName . "/keys/" . $key);651 return AlgoliaUtils_request($this->context, "GET", "/1/indexes/" . $this->urlIndexName . "/keys/" . $key); 628 652 } 629 653 … … 633 657 */ 634 658 public function deleteUserKey($key) { 635 return AlgoliaUtils_request($this->c urlHandle, $this->hostsArray, "DELETE", "/1/indexes/" . $this->urlIndexName . "/keys/" . $key);659 return AlgoliaUtils_request($this->context, "DELETE", "/1/indexes/" . $this->urlIndexName . "/keys/" . $key); 636 660 } 637 661 … … 652 676 */ 653 677 public function addUserKey($acls, $validity = 0, $maxQueriesPerIPPerHour = 0, $maxHitsPerQuery = 0) { 654 return AlgoliaUtils_request($this->c urlHandle, $this->hostsArray, "POST", "/1/indexes/" . $this->urlIndexName . "/keys", array(),678 return AlgoliaUtils_request($this->context, "POST", "/1/indexes/" . $this->urlIndexName . "/keys", array(), 655 679 array("acl" => $acls, "validity" => $validity, "maxQueriesPerIPPerHour" => $maxQueriesPerIPPerHour, "maxHitsPerQuery" => $maxHitsPerQuery)); 656 680 } … … 661 685 */ 662 686 public function batch($requests) { 663 return AlgoliaUtils_request($this->c urlHandle, $this->hostsArray, "POST", "/1/indexes/" . $this->urlIndexName . "/batch", array(), $requests);687 return AlgoliaUtils_request($this->context, "POST", "/1/indexes/" . $this->urlIndexName . "/batch", array(), $requests); 664 688 } 665 689 … … 689 713 } 690 714 691 function AlgoliaUtils_request($c urlHandle, $hostsArray, $method, $path, $params = array(), $data = array()) {715 function AlgoliaUtils_request($context, $method, $path, $params = array(), $data = array()) { 692 716 $exception = null; 693 foreach ($ hostsArray as &$host) {717 foreach ($context->hostsArray as &$host) { 694 718 try { 695 $res = AlgoliaUtils_requestHost($c urlHandle, $method, $host, $path, $params, $data);719 $res = AlgoliaUtils_requestHost($context, $method, $host, $path, $params, $data); 696 720 if ($res !== null) 697 721 return $res; … … 708 732 } 709 733 710 function AlgoliaUtils_requestHost($c urlHandle, $method, $host, $path, $params, $data) {734 function AlgoliaUtils_requestHost($context, $method, $host, $path, $params, $data) { 711 735 $url = "https://" . $host . $path; 712 736 //echo $url; 713 737 if ($params != null && count($params) > 0) { 714 738 $params2 = array(); … … 721 745 } 722 746 $url .= "?" . http_build_query($params2); 723 } 724 747 748 } 749 //echo $url; 750 // initialize curl library 751 $curlHandle = curl_init(); 752 //curl_setopt($curlHandle, CURLOPT_VERBOSE, true); 753 if ($context->adminAPIKey == null) { 754 curl_setopt($curlHandle, CURLOPT_HTTPHEADER, array( 755 'X-Algolia-Application-Id: ' . $context->applicationID, 756 'X-Algolia-API-Key: ' . $context->apiKey, 757 'Content-type: application/json' 758 )); 759 } else { 760 curl_setopt($curlHandle, CURLOPT_HTTPHEADER, array( 761 'X-Algolia-Application-Id: ' . $context->applicationID, 762 'X-Algolia-API-Key: ' . $context->adminAPIKey, 763 'X-Forwarded-For: ' . $context->endUserIP, 764 'X-Forwarded-API-Key: ' . $context->rateLimitAPIKey, 765 'Content-type: application/json' 766 )); 767 } 768 curl_setopt($curlHandle, CURLOPT_USERAGENT, "Algolia for PHP 1.1.9"); 769 //Return the output instead of printing it 770 curl_setopt($curlHandle, CURLOPT_RETURNTRANSFER, true); 771 curl_setopt($curlHandle, CURLOPT_FAILONERROR, true); 772 curl_setopt($curlHandle, CURLOPT_ENCODING, ''); 773 curl_setopt($curlHandle, CURLOPT_SSL_VERIFYPEER, true); 774 curl_setopt($curlHandle, CURLOPT_SSL_VERIFYHOST, 2); 775 curl_setopt($curlHandle, CURLOPT_CAINFO, __DIR__ . '/resources/ca-bundle.crt'); 776 725 777 curl_setopt($curlHandle, CURLOPT_URL, $url); 726 778 curl_setopt($curlHandle, CURLOPT_CONNECTTIMEOUT, 30); 779 curl_setopt($curlHandle, CURLOPT_NOSIGNAL, 1); # The problem is that on (Li|U)nix, when libcurl uses the standard name resolver, a SIGALRM is raised during name resolution which libcurl thinks is the timeout alarm. 727 780 curl_setopt($curlHandle, CURLOPT_FAILONERROR, false); 728 781 … … 745 798 curl_setopt($curlHandle, CURLOPT_POST, true); 746 799 } 747 $response = curl_exec($curlHandle); 800 $mhandle = $context->getMHandle($curlHandle); 801 802 $response = NULL; 803 // Do all the processing. 804 $active = NULL; 805 806 $mrc = curl_multi_exec($mhandle, $active); 807 while ($mrc == CURLM_CALL_MULTI_PERFORM) { 808 usleep(100); 809 $mrc = curl_multi_exec($mhandle, $active); 810 } 811 while ($active && $mrc == CURLM_OK) { 812 $select = curl_multi_select($mhandle); 813 if ($select != -1 || $select != 0) { 814 do { 815 $mrc = curl_multi_exec($mhandle, $active); 816 } while ($mrc == CURLM_CALL_MULTI_PERFORM); 817 } elseif ($select == 0) { //Nothing to do stop 818 break; 819 } 820 usleep(100); 821 } 822 823 748 824 if ($response === false) { 749 825 throw new \Exception(curl_error($curlHandle)); … … 755 831 return null; 756 832 } 833 $response = curl_multi_getcontent($curlHandle); 757 834 $answer = json_decode($response, true); 835 $context->releaseMHandle($curlHandle); 836 curl_close($curlHandle); 758 837 759 838 if ($http_status == 400) { … … 783 862 $errorMsg = 'JSON parsing error: underflow or the modes mismatch'; 784 863 break; 785 case (defined( JSON_ERROR_UTF8) ? JSON_ERROR_UTF8 : -1): // PHP 5.3 less than 5.3.3 (Ubuntu 10.04 LTS)864 case (defined('JSON_ERROR_UTF8') ? JSON_ERROR_UTF8 : -1): // PHP 5.3 less than 5.3.3 (Ubuntu 10.04 LTS) 786 865 $errorMsg = 'JSON parsing error: malformed UTF-8 characters, possibly incorrectly encoded'; 787 866 break; … … 791 870 break; 792 871 } 793 if ($errorMsg !== null) 872 if ($errorMsg !== null) 794 873 throw new AlgoliaException($errorMsg); 795 874 -
maven-algolia/trunk/maven-algolia.php
r915533 r918102 5 5 Plugin URI: 6 6 Description: Fully customise WordPress search implementing algolia API 7 Version: 0. 17 Version: 0.2 8 8 Author: gtenaschuk, mustela 9 Author URI: http: www.sitemavens.com9 Author URI: http://www.sitemavens.com 10 10 Copyright: sitemavens.com 11 11 */ … … 24 24 $registry->setPluginDir( plugin_dir_path( __FILE__ ) ); 25 25 $registry->setPluginUrl( defined( 'DEV_ENV' ) && DEV_ENV ? WP_PLUGIN_URL . "/maven-algolia/" : plugin_dir_url( __FILE__ ) ); 26 $registry->setPluginVersion( "0. 1" );26 $registry->setPluginVersion( "0.2" ); 27 27 $registry->setPluginName( 'Maven Algolia' ); 28 28 $registry->setPluginShortName( 'mvnAlg' );
Note: See TracChangeset
for help on using the changeset viewer.