├── .github
├── ISSUE_TEMPLATE
│ └── Bug_report.yml
└── workflows
│ ├── do-not-edit-this-repository.yml
│ └── issue.yml
├── .gitignore
├── CHANGELOG.md
├── LICENSE
├── README.md
├── composer.json
├── composer.lock
├── lib
├── Algolia.php
├── Api
│ ├── AbtestingClient.php
│ ├── AnalyticsClient.php
│ ├── CompositionClient.php
│ ├── IngestionClient.php
│ ├── InsightsClient.php
│ ├── MonitoringClient.php
│ ├── PersonalizationClient.php
│ ├── QuerySuggestionsClient.php
│ ├── RecommendClient.php
│ └── SearchClient.php
├── ApiException.php
├── Cache
│ └── NullCacheDriver.php
├── Configuration
│ ├── AbtestingConfig.php
│ ├── AnalyticsConfig.php
│ ├── CompositionConfig.php
│ ├── ConfigWithRegion.php
│ ├── Configuration.php
│ ├── IngestionConfig.php
│ ├── InsightsConfig.php
│ ├── MonitoringConfig.php
│ ├── PersonalizationConfig.php
│ ├── QuerySuggestionsConfig.php
│ ├── RecommendConfig.php
│ └── SearchConfig.php
├── Exceptions
│ ├── AlgoliaException.php
│ ├── BadRequestException.php
│ ├── CannotWaitException.php
│ ├── ExceededRetriesException.php
│ ├── MissingObjectId.php
│ ├── NotFoundException.php
│ ├── ObjectNotFoundException.php
│ ├── RequestException.php
│ ├── RetriableException.php
│ ├── UnreachableException.php
│ └── ValidUntilNotFoundException.php
├── FormDataProcessor.php
├── Http
│ ├── CurlHttpClient.php
│ ├── GuzzleHttpClient.php
│ ├── HttpClientInterface.php
│ └── Psr7
│ │ ├── BufferStream.php
│ │ ├── PumpStream.php
│ │ ├── Request.php
│ │ ├── Response.php
│ │ ├── Stream.php
│ │ ├── Uri.php
│ │ ├── UriResolver.php
│ │ └── functions.php
├── Iterators
│ ├── AbstractAlgoliaIterator.php
│ ├── ObjectIterator.php
│ ├── RuleIterator.php
│ └── SynonymIterator.php
├── Log
│ └── DebugLogger.php
├── Model
│ ├── AbstractModel.php
│ ├── Abtesting
│ │ ├── ABTest.php
│ │ ├── ABTestConfiguration.php
│ │ ├── ABTestResponse.php
│ │ ├── AbTestsVariant.php
│ │ ├── AbTestsVariantSearchParams.php
│ │ ├── AddABTestsRequest.php
│ │ ├── AddABTestsVariant.php
│ │ ├── Currency.php
│ │ ├── EffectMetric.php
│ │ ├── EmptySearch.php
│ │ ├── EmptySearchFilter.php
│ │ ├── ErrorBase.php
│ │ ├── EstimateABTestRequest.php
│ │ ├── EstimateABTestResponse.php
│ │ ├── EstimateConfiguration.php
│ │ ├── FilterEffects.php
│ │ ├── ListABTestsResponse.php
│ │ ├── MinimumDetectableEffect.php
│ │ ├── Outliers.php
│ │ ├── OutliersFilter.php
│ │ ├── ScheduleABTestResponse.php
│ │ ├── ScheduleABTestsRequest.php
│ │ ├── Status.php
│ │ └── Variant.php
│ ├── Analytics
│ │ ├── ClickPosition.php
│ │ ├── CurrencyCode.php
│ │ ├── DailyAddToCartRates.php
│ │ ├── DailyAverageClicks.php
│ │ ├── DailyClickThroughRates.php
│ │ ├── DailyConversionRates.php
│ │ ├── DailyNoClickRates.php
│ │ ├── DailyNoResultsRates.php
│ │ ├── DailyPurchaseRates.php
│ │ ├── DailyRevenue.php
│ │ ├── DailySearches.php
│ │ ├── DailySearchesNoClicks.php
│ │ ├── DailySearchesNoResults.php
│ │ ├── DailyUsers.php
│ │ ├── Direction.php
│ │ ├── ErrorBase.php
│ │ ├── GetAddToCartRateResponse.php
│ │ ├── GetAverageClickPositionResponse.php
│ │ ├── GetClickPositionsResponse.php
│ │ ├── GetClickThroughRateResponse.php
│ │ ├── GetConversionRateResponse.php
│ │ ├── GetNoClickRateResponse.php
│ │ ├── GetNoResultsRateResponse.php
│ │ ├── GetPurchaseRateResponse.php
│ │ ├── GetRevenue.php
│ │ ├── GetSearchesCountResponse.php
│ │ ├── GetSearchesNoClicksResponse.php
│ │ ├── GetSearchesNoResultsResponse.php
│ │ ├── GetStatusResponse.php
│ │ ├── GetTopCountriesResponse.php
│ │ ├── GetTopFilterAttribute.php
│ │ ├── GetTopFilterAttributesResponse.php
│ │ ├── GetTopFilterForAttribute.php
│ │ ├── GetTopFilterForAttributeResponse.php
│ │ ├── GetTopFiltersNoResultsResponse.php
│ │ ├── GetTopFiltersNoResultsValue.php
│ │ ├── GetTopFiltersNoResultsValues.php
│ │ ├── GetTopHitsResponse.php
│ │ ├── GetTopSearchesResponse.php
│ │ ├── GetUsersCountResponse.php
│ │ ├── Operator.php
│ │ ├── OrderBy.php
│ │ ├── TopCountry.php
│ │ ├── TopHit.php
│ │ ├── TopHitWithAnalytics.php
│ │ ├── TopHitWithRevenueAnalytics.php
│ │ ├── TopHitsResponse.php
│ │ ├── TopHitsResponseWithAnalytics.php
│ │ ├── TopHitsResponseWithRevenueAnalytics.php
│ │ ├── TopSearch.php
│ │ ├── TopSearchWithAnalytics.php
│ │ ├── TopSearchWithRevenueAnalytics.php
│ │ ├── TopSearchesResponse.php
│ │ ├── TopSearchesResponseWithAnalytics.php
│ │ └── TopSearchesResponseWithRevenueAnalytics.php
│ ├── Composition
│ │ ├── AroundPrecision.php
│ │ ├── AroundRadius.php
│ │ ├── AroundRadiusAll.php
│ │ ├── Banner.php
│ │ ├── BannerImage.php
│ │ ├── BannerImageUrl.php
│ │ ├── BannerLink.php
│ │ ├── CompositionIdRankingInfo.php
│ │ ├── CompositionRunAppliedRules.php
│ │ ├── CompositionRunSearchResponse.php
│ │ ├── CompositionsSearchResponse.php
│ │ ├── ErrorBase.php
│ │ ├── Exhaustive.php
│ │ ├── FacetFilters.php
│ │ ├── FacetHits.php
│ │ ├── FacetOrdering.php
│ │ ├── FacetStats.php
│ │ ├── Facets.php
│ │ ├── HighlightResult.php
│ │ ├── HighlightResultOption.php
│ │ ├── Hit.php
│ │ ├── HitRankingInfo.php
│ │ ├── InsideBoundingBox.php
│ │ ├── MatchLevel.php
│ │ ├── MatchedGeoLocation.php
│ │ ├── NumericFilters.php
│ │ ├── OptionalFilters.php
│ │ ├── Params.php
│ │ ├── Personalization.php
│ │ ├── Range.php
│ │ ├── Redirect.php
│ │ ├── RedirectRuleIndexData.php
│ │ ├── RedirectRuleIndexMetadata.php
│ │ ├── RedirectURL.php
│ │ ├── RenderingContent.php
│ │ ├── RequestBody.php
│ │ ├── ResultsCompositionInfoResponse.php
│ │ ├── ResultsInjectedItemAppliedRulesInfoResponse.php
│ │ ├── ResultsInjectedItemInfoResponse.php
│ │ ├── SearchForFacetValuesParams.php
│ │ ├── SearchForFacetValuesRequest.php
│ │ ├── SearchForFacetValuesResponse.php
│ │ ├── SearchForFacetValuesResults.php
│ │ ├── SearchResponse.php
│ │ ├── SearchResultsItem.php
│ │ ├── SnippetResult.php
│ │ ├── SnippetResultOption.php
│ │ ├── SortRemainingBy.php
│ │ ├── SupportedLanguage.php
│ │ ├── Value.php
│ │ └── Widgets.php
│ ├── Ingestion
│ │ ├── Action.php
│ │ ├── ActionType.php
│ │ ├── AuthAPIKey.php
│ │ ├── AuthAPIKeyPartial.php
│ │ ├── AuthAlgolia.php
│ │ ├── AuthAlgoliaInsights.php
│ │ ├── AuthAlgoliaInsightsPartial.php
│ │ ├── AuthAlgoliaPartial.php
│ │ ├── AuthBasic.php
│ │ ├── AuthBasicPartial.php
│ │ ├── AuthGoogleServiceAccount.php
│ │ ├── AuthGoogleServiceAccountPartial.php
│ │ ├── AuthInput.php
│ │ ├── AuthInputPartial.php
│ │ ├── AuthOAuth.php
│ │ ├── AuthOAuthPartial.php
│ │ ├── Authentication.php
│ │ ├── AuthenticationCreate.php
│ │ ├── AuthenticationCreateResponse.php
│ │ ├── AuthenticationSearch.php
│ │ ├── AuthenticationSortKeys.php
│ │ ├── AuthenticationType.php
│ │ ├── AuthenticationUpdate.php
│ │ ├── AuthenticationUpdateResponse.php
│ │ ├── BigCommerceChannel.php
│ │ ├── BigCommerceMetafield.php
│ │ ├── BigQueryDataType.php
│ │ ├── CommercetoolsCustomFields.php
│ │ ├── DeleteResponse.php
│ │ ├── Destination.php
│ │ ├── DestinationCreate.php
│ │ ├── DestinationCreateResponse.php
│ │ ├── DestinationInput.php
│ │ ├── DestinationSearch.php
│ │ ├── DestinationSortKeys.php
│ │ ├── DestinationType.php
│ │ ├── DestinationUpdate.php
│ │ ├── DestinationUpdateResponse.php
│ │ ├── DockerStreams.php
│ │ ├── DockerStreamsInput.php
│ │ ├── DockerStreamsSyncMode.php
│ │ ├── EmailNotifications.php
│ │ ├── EntityType.php
│ │ ├── ErrorBase.php
│ │ ├── Event.php
│ │ ├── EventSortKeys.php
│ │ ├── EventStatus.php
│ │ ├── EventType.php
│ │ ├── ListAuthenticationsResponse.php
│ │ ├── ListDestinationsResponse.php
│ │ ├── ListEventsResponse.php
│ │ ├── ListSourcesResponse.php
│ │ ├── ListTasksResponse.php
│ │ ├── ListTasksResponseV1.php
│ │ ├── ListTransformationsResponse.php
│ │ ├── MappingFieldDirective.php
│ │ ├── MappingFormatSchema.php
│ │ ├── MappingInput.php
│ │ ├── MappingKitAction.php
│ │ ├── MappingTypeCSV.php
│ │ ├── MethodType.php
│ │ ├── Notifications.php
│ │ ├── OnDemandTrigger.php
│ │ ├── OnDemandTriggerInput.php
│ │ ├── OnDemandTriggerType.php
│ │ ├── OrderKeys.php
│ │ ├── Pagination.php
│ │ ├── Platform.php
│ │ ├── PlatformNone.php
│ │ ├── PlatformWithNone.php
│ │ ├── Policies.php
│ │ ├── PushTaskPayload.php
│ │ ├── PushTaskRecords.php
│ │ ├── RecordType.php
│ │ ├── Run.php
│ │ ├── RunListResponse.php
│ │ ├── RunOutcome.php
│ │ ├── RunProgress.php
│ │ ├── RunReasonCode.php
│ │ ├── RunResponse.php
│ │ ├── RunSortKeys.php
│ │ ├── RunSourcePayload.php
│ │ ├── RunSourceResponse.php
│ │ ├── RunStatus.php
│ │ ├── RunType.php
│ │ ├── ScheduleTrigger.php
│ │ ├── ScheduleTriggerInput.php
│ │ ├── ScheduleTriggerType.php
│ │ ├── ShopifyInput.php
│ │ ├── ShopifyMarket.php
│ │ ├── ShopifyMetafield.php
│ │ ├── Source.php
│ │ ├── SourceBigCommerce.php
│ │ ├── SourceBigQuery.php
│ │ ├── SourceCSV.php
│ │ ├── SourceCommercetools.php
│ │ ├── SourceCreate.php
│ │ ├── SourceCreateResponse.php
│ │ ├── SourceDocker.php
│ │ ├── SourceGA4BigQueryExport.php
│ │ ├── SourceInput.php
│ │ ├── SourceJSON.php
│ │ ├── SourceSearch.php
│ │ ├── SourceShopify.php
│ │ ├── SourceSortKeys.php
│ │ ├── SourceType.php
│ │ ├── SourceUpdate.php
│ │ ├── SourceUpdateCommercetools.php
│ │ ├── SourceUpdateDocker.php
│ │ ├── SourceUpdateInput.php
│ │ ├── SourceUpdateResponse.php
│ │ ├── SourceUpdateShopify.php
│ │ ├── StreamingInput.php
│ │ ├── StreamingTrigger.php
│ │ ├── StreamingTriggerType.php
│ │ ├── SubscriptionTrigger.php
│ │ ├── SubscriptionTriggerType.php
│ │ ├── Task.php
│ │ ├── TaskCreate.php
│ │ ├── TaskCreateResponse.php
│ │ ├── TaskCreateTrigger.php
│ │ ├── TaskCreateV1.php
│ │ ├── TaskInput.php
│ │ ├── TaskSearch.php
│ │ ├── TaskSortKeys.php
│ │ ├── TaskUpdate.php
│ │ ├── TaskUpdateResponse.php
│ │ ├── TaskUpdateV1.php
│ │ ├── TaskV1.php
│ │ ├── Transformation.php
│ │ ├── TransformationCode.php
│ │ ├── TransformationCreate.php
│ │ ├── TransformationCreateResponse.php
│ │ ├── TransformationError.php
│ │ ├── TransformationInput.php
│ │ ├── TransformationNoCode.php
│ │ ├── TransformationSearch.php
│ │ ├── TransformationSortKeys.php
│ │ ├── TransformationTry.php
│ │ ├── TransformationTryResponse.php
│ │ ├── TransformationType.php
│ │ ├── TransformationUpdateResponse.php
│ │ ├── Trigger.php
│ │ ├── TriggerType.php
│ │ ├── TriggerUpdateInput.php
│ │ ├── WatchResponse.php
│ │ └── Window.php
│ ├── Insights
│ │ ├── AddToCartEvent.php
│ │ ├── AddedToCartObjectIDs.php
│ │ ├── AddedToCartObjectIDsAfterSearch.php
│ │ ├── ClickEvent.php
│ │ ├── ClickedFilters.php
│ │ ├── ClickedObjectIDs.php
│ │ ├── ClickedObjectIDsAfterSearch.php
│ │ ├── ConversionEvent.php
│ │ ├── ConvertedFilters.php
│ │ ├── ConvertedObjectIDs.php
│ │ ├── ConvertedObjectIDsAfterSearch.php
│ │ ├── Discount.php
│ │ ├── ErrorBase.php
│ │ ├── EventsItems.php
│ │ ├── EventsResponse.php
│ │ ├── InsightsEvents.php
│ │ ├── ObjectData.php
│ │ ├── ObjectDataAfterSearch.php
│ │ ├── Price.php
│ │ ├── PurchaseEvent.php
│ │ ├── PurchasedObjectIDs.php
│ │ ├── PurchasedObjectIDsAfterSearch.php
│ │ ├── Value.php
│ │ ├── ViewEvent.php
│ │ ├── ViewedFilters.php
│ │ └── ViewedObjectIDs.php
│ ├── ModelInterface.php
│ ├── Monitoring
│ │ ├── ErrorBase.php
│ │ ├── Incident.php
│ │ ├── IncidentEntry.php
│ │ ├── IncidentsResponse.php
│ │ ├── IndexingMetric.php
│ │ ├── IndexingTimeResponse.php
│ │ ├── InfrastructureResponse.php
│ │ ├── InventoryResponse.php
│ │ ├── LatencyMetric.php
│ │ ├── LatencyResponse.php
│ │ ├── Metric.php
│ │ ├── Metrics.php
│ │ ├── Period.php
│ │ ├── ProbesMetric.php
│ │ ├── Region.php
│ │ ├── Server.php
│ │ ├── ServerStatus.php
│ │ ├── Status.php
│ │ ├── StatusResponse.php
│ │ ├── TimeEntry.php
│ │ └── Type.php
│ ├── Personalization
│ │ ├── DeleteUserProfileResponse.php
│ │ ├── ErrorBase.php
│ │ ├── EventType.php
│ │ ├── EventsScoring.php
│ │ ├── FacetsScoring.php
│ │ ├── GetUserTokenResponse.php
│ │ ├── PersonalizationStrategyParams.php
│ │ └── SetPersonalizationStrategyResponse.php
│ ├── QuerySuggestions
│ │ ├── BaseResponse.php
│ │ ├── ConfigStatus.php
│ │ ├── Configuration.php
│ │ ├── ConfigurationResponse.php
│ │ ├── ConfigurationWithIndex.php
│ │ ├── ErrorBase.php
│ │ ├── Facet.php
│ │ ├── Languages.php
│ │ ├── LogFile.php
│ │ ├── LogLevel.php
│ │ └── SourceIndex.php
│ ├── Recommend
│ │ ├── AdvancedSyntaxFeatures.php
│ │ ├── AlternativesAsExact.php
│ │ ├── AroundPrecision.php
│ │ ├── AroundRadius.php
│ │ ├── AroundRadiusAll.php
│ │ ├── AutoFacetFilter.php
│ │ ├── Banner.php
│ │ ├── BannerImage.php
│ │ ├── BannerImageUrl.php
│ │ ├── BannerLink.php
│ │ ├── BooleanString.php
│ │ ├── BoughtTogetherQuery.php
│ │ ├── Condition.php
│ │ ├── Consequence.php
│ │ ├── DeletedAtResponse.php
│ │ ├── Distinct.php
│ │ ├── ErrorBase.php
│ │ ├── ExactOnSingleWordQuery.php
│ │ ├── Exhaustive.php
│ │ ├── FacetFilters.php
│ │ ├── FacetOrdering.php
│ │ ├── FacetStats.php
│ │ ├── FallbackParams.php
│ │ ├── FbtModel.php
│ │ ├── GetRecommendTaskResponse.php
│ │ ├── GetRecommendationsParams.php
│ │ ├── GetRecommendationsResponse.php
│ │ ├── HideConsequenceObject.php
│ │ ├── HighlightResult.php
│ │ ├── HighlightResultOption.php
│ │ ├── IgnorePlurals.php
│ │ ├── IndexSettingsFacets.php
│ │ ├── InsideBoundingBox.php
│ │ ├── LookingSimilarModel.php
│ │ ├── LookingSimilarQuery.php
│ │ ├── MatchLevel.php
│ │ ├── MatchedGeoLocation.php
│ │ ├── NumericFilters.php
│ │ ├── OptionalFilters.php
│ │ ├── OptionalWords.php
│ │ ├── ParamsConsequence.php
│ │ ├── Personalization.php
│ │ ├── PromoteConsequenceObject.php
│ │ ├── QueryType.php
│ │ ├── Range.php
│ │ ├── RankingInfo.php
│ │ ├── ReRankingApplyFilter.php
│ │ ├── RecommendHit.php
│ │ ├── RecommendModels.php
│ │ ├── RecommendRule.php
│ │ ├── RecommendSearchParams.php
│ │ ├── RecommendUpdatedAtResponse.php
│ │ ├── RecommendationsHit.php
│ │ ├── RecommendationsRequest.php
│ │ ├── RecommendationsResults.php
│ │ ├── Redirect.php
│ │ ├── RedirectRuleIndexData.php
│ │ ├── RedirectRuleIndexMetadata.php
│ │ ├── RedirectURL.php
│ │ ├── RelatedModel.php
│ │ ├── RelatedQuery.php
│ │ ├── RemoveStopWords.php
│ │ ├── RemoveWordsIfNoResults.php
│ │ ├── RenderingContent.php
│ │ ├── RuleMetadata.php
│ │ ├── SearchRecommendRulesParams.php
│ │ ├── SearchRecommendRulesResponse.php
│ │ ├── SnippetResult.php
│ │ ├── SnippetResultOption.php
│ │ ├── SortRemainingBy.php
│ │ ├── SupportedLanguage.php
│ │ ├── TagFilters.php
│ │ ├── TaskStatus.php
│ │ ├── TimeRange.php
│ │ ├── TrendingFacetHit.php
│ │ ├── TrendingFacetsModel.php
│ │ ├── TrendingFacetsQuery.php
│ │ ├── TrendingItemsModel.php
│ │ ├── TrendingItemsQuery.php
│ │ ├── TypoTolerance.php
│ │ ├── TypoToleranceEnum.php
│ │ ├── Value.php
│ │ └── Widgets.php
│ └── Search
│ │ ├── Acl.php
│ │ ├── Action.php
│ │ ├── AddApiKeyResponse.php
│ │ ├── AdvancedSyntaxFeatures.php
│ │ ├── AlternativesAsExact.php
│ │ ├── Anchoring.php
│ │ ├── ApiKey.php
│ │ ├── ApiKeyOperation.php
│ │ ├── AroundPrecision.php
│ │ ├── AroundRadius.php
│ │ ├── AroundRadiusAll.php
│ │ ├── AssignUserIdParams.php
│ │ ├── AttributeToUpdate.php
│ │ ├── AutomaticFacetFilter.php
│ │ ├── AutomaticFacetFilters.php
│ │ ├── Banner.php
│ │ ├── BannerImage.php
│ │ ├── BannerImageUrl.php
│ │ ├── BannerLink.php
│ │ ├── BatchAssignUserIdsParams.php
│ │ ├── BatchDictionaryEntriesParams.php
│ │ ├── BatchDictionaryEntriesRequest.php
│ │ ├── BatchParams.php
│ │ ├── BatchRequest.php
│ │ ├── BatchResponse.php
│ │ ├── BatchWriteParams.php
│ │ ├── BooleanString.php
│ │ ├── BrowseParams.php
│ │ ├── BrowseParamsObject.php
│ │ ├── BrowseResponse.php
│ │ ├── BuiltInOperation.php
│ │ ├── BuiltInOperationType.php
│ │ ├── BuiltInOperationValue.php
│ │ ├── Condition.php
│ │ ├── Consequence.php
│ │ ├── ConsequenceHide.php
│ │ ├── ConsequenceParams.php
│ │ ├── ConsequenceQuery.php
│ │ ├── ConsequenceQueryObject.php
│ │ ├── CreatedAtResponse.php
│ │ ├── DeleteApiKeyResponse.php
│ │ ├── DeleteByParams.php
│ │ ├── DeleteSourceResponse.php
│ │ ├── DeletedAtResponse.php
│ │ ├── DictionaryAction.php
│ │ ├── DictionaryEntry.php
│ │ ├── DictionaryEntryState.php
│ │ ├── DictionaryEntryType.php
│ │ ├── DictionaryLanguage.php
│ │ ├── DictionarySettingsParams.php
│ │ ├── DictionaryType.php
│ │ ├── Distinct.php
│ │ ├── Edit.php
│ │ ├── EditType.php
│ │ ├── ErrorBase.php
│ │ ├── Event.php
│ │ ├── EventStatus.php
│ │ ├── EventType.php
│ │ ├── ExactOnSingleWordQuery.php
│ │ ├── Exhaustive.php
│ │ ├── FacetFilters.php
│ │ ├── FacetHits.php
│ │ ├── FacetOrdering.php
│ │ ├── FacetStats.php
│ │ ├── Facets.php
│ │ ├── FetchedIndex.php
│ │ ├── GetApiKeyResponse.php
│ │ ├── GetDictionarySettingsResponse.php
│ │ ├── GetLogsResponse.php
│ │ ├── GetObjectsParams.php
│ │ ├── GetObjectsRequest.php
│ │ ├── GetObjectsResponse.php
│ │ ├── GetTaskResponse.php
│ │ ├── GetTopUserIdsResponse.php
│ │ ├── HasPendingMappingsResponse.php
│ │ ├── HighlightResult.php
│ │ ├── HighlightResultOption.php
│ │ ├── Hit.php
│ │ ├── IgnorePlurals.php
│ │ ├── IndexSettings.php
│ │ ├── InsideBoundingBox.php
│ │ ├── Languages.php
│ │ ├── ListApiKeysResponse.php
│ │ ├── ListClustersResponse.php
│ │ ├── ListIndicesResponse.php
│ │ ├── ListUserIdsResponse.php
│ │ ├── Log.php
│ │ ├── LogQuery.php
│ │ ├── LogType.php
│ │ ├── MatchLevel.php
│ │ ├── MatchedGeoLocation.php
│ │ ├── Mode.php
│ │ ├── MultipleBatchRequest.php
│ │ ├── MultipleBatchResponse.php
│ │ ├── NumericFilters.php
│ │ ├── OperationIndexParams.php
│ │ ├── OperationType.php
│ │ ├── OptionalFilters.php
│ │ ├── OptionalWords.php
│ │ ├── Personalization.php
│ │ ├── Promote.php
│ │ ├── PromoteObjectID.php
│ │ ├── PromoteObjectIDs.php
│ │ ├── QueryType.php
│ │ ├── Range.php
│ │ ├── RankingInfo.php
│ │ ├── ReRankingApplyFilter.php
│ │ ├── Redirect.php
│ │ ├── RedirectRuleIndexData.php
│ │ ├── RedirectRuleIndexMetadata.php
│ │ ├── RedirectURL.php
│ │ ├── RemoveStopWords.php
│ │ ├── RemoveUserIdResponse.php
│ │ ├── RemoveWordsIfNoResults.php
│ │ ├── RenderingContent.php
│ │ ├── ReplaceAllObjectsResponse.php
│ │ ├── ReplaceSourceResponse.php
│ │ ├── Rule.php
│ │ ├── SaveObjectResponse.php
│ │ ├── SaveSynonymResponse.php
│ │ ├── ScopeType.php
│ │ ├── SearchDictionaryEntriesParams.php
│ │ ├── SearchDictionaryEntriesResponse.php
│ │ ├── SearchForFacetValuesRequest.php
│ │ ├── SearchForFacetValuesResponse.php
│ │ ├── SearchForFacets.php
│ │ ├── SearchForHits.php
│ │ ├── SearchMethodParams.php
│ │ ├── SearchParams.php
│ │ ├── SearchParamsObject.php
│ │ ├── SearchParamsString.php
│ │ ├── SearchQuery.php
│ │ ├── SearchResponse.php
│ │ ├── SearchResponses.php
│ │ ├── SearchResult.php
│ │ ├── SearchRulesParams.php
│ │ ├── SearchRulesResponse.php
│ │ ├── SearchStrategy.php
│ │ ├── SearchSynonymsParams.php
│ │ ├── SearchSynonymsResponse.php
│ │ ├── SearchTypeDefault.php
│ │ ├── SearchTypeFacet.php
│ │ ├── SearchUserIdsParams.php
│ │ ├── SearchUserIdsResponse.php
│ │ ├── SecuredApiKeyRestrictions.php
│ │ ├── SemanticSearch.php
│ │ ├── SettingsResponse.php
│ │ ├── SnippetResult.php
│ │ ├── SnippetResultOption.php
│ │ ├── SortRemainingBy.php
│ │ ├── Source.php
│ │ ├── StandardEntries.php
│ │ ├── SupportedLanguage.php
│ │ ├── SynonymHit.php
│ │ ├── SynonymType.php
│ │ ├── TagFilters.php
│ │ ├── TaskStatus.php
│ │ ├── TimeRange.php
│ │ ├── TypoTolerance.php
│ │ ├── TypoToleranceEnum.php
│ │ ├── UpdateApiKeyResponse.php
│ │ ├── UpdatedAtResponse.php
│ │ ├── UpdatedAtWithObjectIdResponse.php
│ │ ├── UserHighlightResult.php
│ │ ├── UserHit.php
│ │ ├── UserId.php
│ │ ├── Value.php
│ │ ├── WatchResponse.php
│ │ └── Widgets.php
├── ObjectSerializer.php
├── RequestOptions
│ ├── RequestOptions.php
│ └── RequestOptionsFactory.php
├── RetryStrategy
│ ├── ApiWrapper.php
│ ├── ApiWrapperInterface.php
│ ├── ClusterHosts.php
│ ├── Host.php
│ └── HostCollection.php
└── Support
│ ├── AlgoliaAgent.php
│ └── Helpers.php
├── phpstan.neon
└── phpunit.xml.dist
/.github/ISSUE_TEMPLATE/Bug_report.yml:
--------------------------------------------------------------------------------
1 | name: Bug Report
2 | description: File a bug report.
3 | title: '[bug]: '
4 | labels: ['bug', 'triage']
5 | body:
6 | - type: markdown
7 | attributes:
8 | value: |
9 | ## Please help us help you!
10 |
11 | > [!IMPORTANT]
12 | > This repository is fully generated and all pull request will be rejected.
13 | > If you wish to contribute, please refer to the [contribution guidelines](https://github.com/algolia/api-clients-automation/blob/main/CONTRIBUTING.md) on the `api-clients-automation` repository.
14 |
15 | Before filing your issue, ask yourself:
16 | - Is there an issue already opened for this bug?
17 | - Can I reproduce it?
18 |
19 | If you are not sure about the origin of the issue, or if it impacts your customer experience, please contact [our support team](https://alg.li/support).
20 | - type: textarea
21 | attributes:
22 | label: Description
23 | description: A clear and concise description of what the bug is.
24 | validations:
25 | required: true
26 | - type: dropdown
27 | id: client
28 | attributes:
29 | label: Client
30 | description: Which API are you targeting?
31 | options:
32 | - All
33 | - AB testing
34 | - Analytics
35 | - Ingestion
36 | - Insights
37 | - Monitoring
38 | - Personalization
39 | - Query-Suggestions
40 | - Recommend
41 | - Search
42 | - Crawler
43 | validations:
44 | required: true
45 | - type: input
46 | id: version
47 | attributes:
48 | label: Version
49 | description: The version of the client you are using.
50 | validations:
51 | required: true
52 | - type: textarea
53 | id: logs
54 | attributes:
55 | label: Relevant log output
56 | description: Please copy and paste any relevant log output. This will be automatically formatted into code, so no need for backticks.
57 | render: shell
58 |
--------------------------------------------------------------------------------
/.github/workflows/do-not-edit-this-repository.yml:
--------------------------------------------------------------------------------
1 | name: Do not edit files in this repository
2 |
3 | on:
4 | pull_request_target:
5 | types:
6 | - opened
7 | - synchronize
8 | - reopen
9 | branches:
10 | - 'main'
11 |
12 | jobs:
13 | auto_close_pr:
14 | name: Close PR
15 | runs-on: ubuntu-latest
16 | steps:
17 | - uses: actions/checkout@v4
18 |
19 | - name: Close PR
20 | env:
21 | GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
22 | PR_NUMBER: ${{ github.event.pull_request.number }}
23 | run: |
24 | gh pr close "${PR_NUMBER}" -d -c "Thanks for contributing to our API clients! Sorry to close your PR, but this repository is fully generated, you can port your changes to [the API Clients Automation repository](https://github.com/algolia/api-clients-automation). If you need some guidance, feel free to [open an issue](https://github.com/algolia/api-clients-automation/issues) or [read our contribution guide](https://api-clients-automation.netlify.app/docs/introduction)."
25 |
--------------------------------------------------------------------------------
/.github/workflows/issue.yml:
--------------------------------------------------------------------------------
1 | name: 'Issue sync with Jira'
2 | on:
3 | issues:
4 | types: [opened]
5 |
6 | permissions:
7 | issues: write
8 | contents: read
9 |
10 | jobs:
11 | sync:
12 | runs-on: ubuntu-latest
13 | steps:
14 | - name: Create ticket
15 | uses: actions/github-script@v7
16 | with:
17 | script: |
18 | const action = context.payload.action;
19 | if (action !== 'opened') {
20 | return;
21 | }
22 | const title = context.payload.issue.title;
23 | const body = context.payload.issue.body;
24 |
25 | const res = await fetch('https://algolia.atlassian.net/rest/api/2/issue', {
26 | method: 'POST',
27 | headers: {
28 | 'Accept': 'application/json',
29 | 'Content-Type': 'application/json',
30 | 'Authorization': `Basic ${{ secrets.JIRA_TOKEN }}`
31 | },
32 | body: JSON.stringify({
33 | fields: {
34 | description: `Issue created by ${context.actor} at ${context.payload.issue.html_url} \n\n${body}`,
35 | issuetype: {
36 | id: '10001'
37 | },
38 | parent: {
39 | key: 'DI-3523'
40 | },
41 | project: {
42 | id: '10118'
43 | },
44 | components: [
45 | {
46 | id: '10872'
47 | }
48 | ],
49 | summary: `[GH-ISSUE] ${title}`
50 | },
51 | update: {}
52 | })
53 | });
54 |
55 | if (!res.ok) {
56 | throw new Error(`Failed to create ticket: ${res.statusText} (${res.status}) - ${await res.text()}`);
57 | }
58 |
59 | const data = await res.json();
60 | console.log(`Created ticket: ${data.key}`);
61 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # ref: https://github.com/github/gitignore/blob/master/Composer.gitignore
2 |
3 | composer.phar
4 | /vendor/
5 |
6 | # Commit your application's lock file https://getcomposer.org/doc/01-basic-usage.md#commit-your-composer-lock-file-to-version-control
7 | # You may choose to ignore a library lock file http://getcomposer.org/doc/02-libraries.md#lock-file
8 | # composer.lock
9 |
10 | # php-cs-fixer cache
11 | .php_cs.cache
12 | .php-cs-fixer.cache
13 |
14 | # PHPUnit cache
15 | .phpunit.result.cache
16 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2013-Present Algolia
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
The perfect starting point to integrate Algolia within your PHP project
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 | Documentation •
18 | Laravel •
19 | Symfony •
20 | Community Forum •
21 | Stack Overflow •
22 | Report a bug •
23 | FAQ •
24 | Support
25 |
26 |
27 | ## ✨ Features
28 |
29 | - Thin & minimal low-level HTTP client to interact with Algolia's API
30 | - Supports php `^8.0`.
31 |
32 | ## 💡 Getting Started
33 |
34 | First, install Algolia PHP API Client via the [composer](https://getcomposer.org/) package manager:
35 |
36 | ```bash
37 | composer require algolia/algoliasearch-client-php "^4.0"
38 | ```
39 |
40 | You can now import the Algolia API client in your project and play with it.
41 |
42 | ```php
43 | use Algolia\AlgoliaSearch\Api\SearchClient;
44 |
45 | $client = SearchClient::create('', '');
46 |
47 | // Add a new record to your Algolia index
48 | $response = $client->saveObject(
49 | '',
50 | ['objectID' => 'id',
51 | 'test' => 'val',
52 | ],
53 | );
54 |
55 | // play with the response
56 | var_dump($response);
57 |
58 | // Poll the task status to know when it has been indexed
59 | $client->waitForTask('', $response['taskID']);
60 |
61 | // Fetch search results, with typo tolerance
62 | $response = $client->search(
63 | ['requests' => [
64 | ['indexName' => '',
65 | 'query' => '',
66 | 'hitsPerPage' => 50,
67 | ],
68 | ],
69 | ],
70 | );
71 |
72 | // play with the response
73 | var_dump($response);
74 | ```
75 |
76 | For full documentation, visit the **[Algolia PHP API Client](https://www.algolia.com/doc/libraries/php/)**.
77 |
78 | ## ❓ Troubleshooting
79 |
80 | Encountering an issue? Before reaching out to support, we recommend heading to our [FAQ](https://www.algolia.com/doc/api-client/troubleshooting/faq/php/) where you will find answers for the most common issues and gotchas with the client. You can also open [a GitHub issue](https://github.com/algolia/api-clients-automation/issues/new?assignees=&labels=&projects=&template=Bug_report.md)
81 |
82 | ## Contributing
83 |
84 | This repository hosts the code of the generated Algolia API client for PHP, if you'd like to contribute, head over to the [main repository](https://github.com/algolia/api-clients-automation). You can also find contributing guides on [our documentation website](https://api-clients-automation.netlify.app/docs/introduction).
85 |
86 | ## 📄 License
87 |
88 | The Algolia PHP API Client is an open-sourced software licensed under the [MIT license](LICENSE).
89 |
--------------------------------------------------------------------------------
/composer.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "algolia/algoliasearch-client-php",
3 | "version": "4.21.0",
4 | "description": "API powering the features of Algolia.",
5 | "keywords": ["algolia", "search", "api", "client", "php"],
6 | "type": "library",
7 | "homepage": "https://github.com/algolia/algoliasearch-client-php",
8 | "license": "MIT",
9 | "authors": [
10 | {
11 | "name": "Algolia Team",
12 | "homepage": "https://alg.li/support"
13 | }
14 | ],
15 | "require": {
16 | "php": ">=8.1 !=8.3.0",
17 | "ext-curl": "*",
18 | "ext-json": "*",
19 | "ext-mbstring": "*",
20 | "guzzlehttp/psr7": "^2.0",
21 | "psr/http-message": "^1.1 || ^2.0",
22 | "psr/log": "^1.0 || ^2.0 || ^3.0",
23 | "psr/simple-cache": "^1.0 || ^2.0 || ^3.0"
24 | },
25 | "require-dev": {
26 | "friendsofphp/php-cs-fixer": "^2.0 || ^3.5.0",
27 | "phpunit/phpunit": "^11.0",
28 | "vlucas/phpdotenv": "^5.4",
29 | "phpstan/phpstan": "^1.12"
30 | },
31 | "autoload": {
32 | "psr-4": { "Algolia\\AlgoliaSearch\\" : "lib/" },
33 | "files": [
34 | "lib/Http/Psr7/functions.php"
35 | ]
36 | },
37 | "suggest": {
38 | "guzzlehttp/guzzle": "If you prefer to use Guzzle HTTP client instead of the Http Client implementation provided by the package"
39 | },
40 | "minimum-stability": "dev",
41 | "prefer-stable": true
42 | }
43 |
--------------------------------------------------------------------------------
/lib/Algolia.php:
--------------------------------------------------------------------------------
1 | responseHeaders = $responseHeaders;
45 | $this->responseBody = $responseBody;
46 | }
47 |
48 | /**
49 | * Gets the HTTP response header.
50 | *
51 | * @return null|string[] HTTP response header
52 | */
53 | public function getResponseHeaders()
54 | {
55 | return $this->responseHeaders;
56 | }
57 |
58 | /**
59 | * Gets the HTTP body of the server response either as Json or string.
60 | *
61 | * @return null|\stdClass|string HTTP body of the server response either as \stdClass or string
62 | */
63 | public function getResponseBody()
64 | {
65 | return $this->responseBody;
66 | }
67 |
68 | /**
69 | * Sets the deserialized response object (during deserialization).
70 | *
71 | * @param mixed $obj Deserialized response object
72 | */
73 | public function setResponseObject($obj)
74 | {
75 | $this->responseObject = $obj;
76 | }
77 |
78 | /**
79 | * Gets the deserialized response object (during deserialization).
80 | *
81 | * @return mixed the deserialized response object
82 | */
83 | public function getResponseObject()
84 | {
85 | return $this->responseObject;
86 | }
87 | }
88 |
--------------------------------------------------------------------------------
/lib/Cache/NullCacheDriver.php:
--------------------------------------------------------------------------------
1 | '',
33 | 'apiKey' => '',
34 | 'hosts' => null,
35 | 'hasFullHosts' => false,
36 | 'readTimeout' => 5,
37 | 'writeTimeout' => 30,
38 | 'connectTimeout' => 2,
39 | 'defaultHeaders' => [],
40 | ];
41 | }
42 | }
43 |
--------------------------------------------------------------------------------
/lib/Configuration/AnalyticsConfig.php:
--------------------------------------------------------------------------------
1 | '',
33 | 'apiKey' => '',
34 | 'hosts' => null,
35 | 'hasFullHosts' => false,
36 | 'readTimeout' => 5,
37 | 'writeTimeout' => 30,
38 | 'connectTimeout' => 2,
39 | 'defaultHeaders' => [],
40 | ];
41 | }
42 | }
43 |
--------------------------------------------------------------------------------
/lib/Configuration/CompositionConfig.php:
--------------------------------------------------------------------------------
1 | '',
15 | 'apiKey' => '',
16 | 'hosts' => null,
17 | 'hasFullHosts' => false,
18 | 'readTimeout' => 5,
19 | 'writeTimeout' => 30,
20 | 'connectTimeout' => 2,
21 | 'defaultHeaders' => [],
22 | ];
23 | }
24 | }
25 |
--------------------------------------------------------------------------------
/lib/Configuration/ConfigWithRegion.php:
--------------------------------------------------------------------------------
1 | $appId,
11 | 'apiKey' => $apiKey,
12 | 'region' => $region,
13 | ];
14 |
15 | return new static($config);
16 | }
17 |
18 | public function getRegion()
19 | {
20 | return $this->config['region'];
21 | }
22 | }
23 |
--------------------------------------------------------------------------------
/lib/Configuration/IngestionConfig.php:
--------------------------------------------------------------------------------
1 | '',
34 | 'apiKey' => '',
35 | 'hosts' => null,
36 | 'hasFullHosts' => false,
37 | 'readTimeout' => 25,
38 | 'writeTimeout' => 25,
39 | 'connectTimeout' => 25,
40 | 'defaultHeaders' => [],
41 | ];
42 | }
43 | }
44 |
--------------------------------------------------------------------------------
/lib/Configuration/InsightsConfig.php:
--------------------------------------------------------------------------------
1 | '',
33 | 'apiKey' => '',
34 | 'hosts' => null,
35 | 'hasFullHosts' => false,
36 | 'readTimeout' => 5,
37 | 'writeTimeout' => 30,
38 | 'connectTimeout' => 2,
39 | 'defaultHeaders' => [],
40 | ];
41 | }
42 | }
43 |
--------------------------------------------------------------------------------
/lib/Configuration/MonitoringConfig.php:
--------------------------------------------------------------------------------
1 | '',
15 | 'apiKey' => '',
16 | 'hosts' => null,
17 | 'hasFullHosts' => false,
18 | 'readTimeout' => 5,
19 | 'writeTimeout' => 30,
20 | 'connectTimeout' => 2,
21 | 'defaultHeaders' => [],
22 | ];
23 | }
24 | }
25 |
--------------------------------------------------------------------------------
/lib/Configuration/PersonalizationConfig.php:
--------------------------------------------------------------------------------
1 | '',
34 | 'apiKey' => '',
35 | 'hosts' => null,
36 | 'hasFullHosts' => false,
37 | 'readTimeout' => 5,
38 | 'writeTimeout' => 30,
39 | 'connectTimeout' => 2,
40 | 'defaultHeaders' => [],
41 | ];
42 | }
43 | }
44 |
--------------------------------------------------------------------------------
/lib/Configuration/QuerySuggestionsConfig.php:
--------------------------------------------------------------------------------
1 | '',
34 | 'apiKey' => '',
35 | 'hosts' => null,
36 | 'hasFullHosts' => false,
37 | 'readTimeout' => 5,
38 | 'writeTimeout' => 30,
39 | 'connectTimeout' => 2,
40 | 'defaultHeaders' => [],
41 | ];
42 | }
43 | }
44 |
--------------------------------------------------------------------------------
/lib/Configuration/RecommendConfig.php:
--------------------------------------------------------------------------------
1 | '',
15 | 'apiKey' => '',
16 | 'hosts' => null,
17 | 'hasFullHosts' => false,
18 | 'readTimeout' => 5,
19 | 'writeTimeout' => 30,
20 | 'connectTimeout' => 2,
21 | 'defaultHeaders' => [],
22 | ];
23 | }
24 | }
25 |
--------------------------------------------------------------------------------
/lib/Configuration/SearchConfig.php:
--------------------------------------------------------------------------------
1 | $appId,
18 | 'apiKey' => $apiKey,
19 | ];
20 |
21 | return new static($config);
22 | }
23 |
24 | public function getWaitTaskTimeBeforeRetry()
25 | {
26 | return $this->config['waitTaskTimeBeforeRetry'];
27 | }
28 |
29 | /**
30 | * Sets the max retries value used in the Search helpers (e.g. replaceAllobjects).
31 | *
32 | * @param number $maxRetries the user agent of the api client
33 | *
34 | * @return $this
35 | */
36 | public function setMaxRetries($maxRetries)
37 | {
38 | $this->config['defaultMaxRetries'] = $maxRetries;
39 |
40 | return $this;
41 | }
42 |
43 | public function getDefaultMaxRetries()
44 | {
45 | return $this->config['defaultMaxRetries'];
46 | }
47 |
48 | /**
49 | * Sets the region of the current algolia application to the configuration, this is required to be called if you wish to leverage the transformation pipeline (via the *WithTransformation methods).
50 | *
51 | * @param string $region the user agent of the api client
52 | *
53 | * @return $this
54 | */
55 | public function setTransformationRegion($region)
56 | {
57 | $this->config['region'] = $region;
58 |
59 | return $this;
60 | }
61 |
62 | public function getTransformationRegion()
63 | {
64 | return $this->config['region'];
65 | }
66 |
67 | public function getDefaultConfiguration()
68 | {
69 | return [
70 | 'appId' => '',
71 | 'apiKey' => '',
72 | 'hosts' => null,
73 | 'hasFullHosts' => false,
74 | 'readTimeout' => 5,
75 | 'writeTimeout' => 30,
76 | 'connectTimeout' => 2,
77 | 'defaultHeaders' => [],
78 | 'region' => null,
79 | 'waitTaskTimeBeforeRetry' => $this->defaultWaitTaskTimeBeforeRetry,
80 | 'defaultMaxRetries' => $this->defaultMaxRetries,
81 | 'defaultForwardToReplicas' => null,
82 | 'batchSize' => 1000,
83 | ];
84 | }
85 | }
86 |
--------------------------------------------------------------------------------
/lib/Exceptions/AlgoliaException.php:
--------------------------------------------------------------------------------
1 | request = $request;
14 |
15 | return $this;
16 | }
17 |
18 | public function getRequest()
19 | {
20 | return $this->request;
21 | }
22 | }
23 |
--------------------------------------------------------------------------------
/lib/Exceptions/RetriableException.php:
--------------------------------------------------------------------------------
1 | client = $client ?: self::buildClient();
20 | }
21 |
22 | public function sendRequest(
23 | RequestInterface $request,
24 | $timeout,
25 | $connectTimeout
26 | ) {
27 | try {
28 | $response = $this->client->send($request, [
29 | 'timeout' => $timeout,
30 | 'connect_timeout' => $connectTimeout,
31 | ]);
32 | } catch (RequestException $e) {
33 | if ($e->hasResponse()) {
34 | return $e->getResponse();
35 | }
36 |
37 | return new Response(0, [], null, '1.1', $e->getMessage());
38 | } catch (ConnectException $e) {
39 | return new Response(0, [], null, '1.1', $e->getMessage());
40 | }
41 |
42 | return $response;
43 | }
44 |
45 | private static function buildClient(array $config = [])
46 | {
47 | $handlerStack = new HandlerStack(\GuzzleHttp\choose_handler());
48 | $handlerStack->push(Middleware::prepareBody(), 'prepare_body');
49 | $config = array_merge(['handler' => $handlerStack], $config);
50 |
51 | return new GuzzleClient($config);
52 | }
53 | }
54 |
--------------------------------------------------------------------------------
/lib/Http/HttpClientInterface.php:
--------------------------------------------------------------------------------
1 | hwm = $hwm;
33 | }
34 |
35 | public function __toString(): string
36 | {
37 | return $this->getContents();
38 | }
39 |
40 | public function getContents(): string
41 | {
42 | $buffer = $this->buffer;
43 | $this->buffer = '';
44 |
45 | return $buffer;
46 | }
47 |
48 | public function close(): void
49 | {
50 | $this->buffer = '';
51 | }
52 |
53 | public function detach(): void
54 | {
55 | $this->close();
56 | }
57 |
58 | public function getSize(): int
59 | {
60 | return mb_strlen($this->buffer);
61 | }
62 |
63 | public function isReadable(): bool
64 | {
65 | return true;
66 | }
67 |
68 | public function isWritable(): bool
69 | {
70 | return true;
71 | }
72 |
73 | public function isSeekable(): bool
74 | {
75 | return false;
76 | }
77 |
78 | public function rewind(): void
79 | {
80 | $this->seek(0);
81 | }
82 |
83 | public function seek($offset, $whence = SEEK_SET): void
84 | {
85 | throw new \RuntimeException('Cannot seek a BufferStream');
86 | }
87 |
88 | public function eof(): bool
89 | {
90 | return 0 === mb_strlen($this->buffer);
91 | }
92 |
93 | public function tell(): int
94 | {
95 | throw new \RuntimeException('Cannot determine the position of a BufferStream');
96 | }
97 |
98 | /**
99 | * Reads data from the buffer.
100 | *
101 | * @param mixed $length
102 | */
103 | public function read($length): string
104 | {
105 | $currentLength = mb_strlen($this->buffer);
106 |
107 | if ($length >= $currentLength) {
108 | // No need to slice the buffer because we don't have enough data.
109 | $result = $this->buffer;
110 | $this->buffer = '';
111 | } else {
112 | // Slice up the result to provide a subset of the buffer.
113 | $result = mb_substr($this->buffer, 0, $length);
114 | $this->buffer = mb_substr($this->buffer, $length);
115 | }
116 |
117 | return $result;
118 | }
119 |
120 | /**
121 | * Writes data to the buffer.
122 | *
123 | * @param mixed $string
124 | */
125 | public function write($string): int
126 | {
127 | $this->buffer .= $string;
128 |
129 | // TODO: What should happen here?
130 | if (mb_strlen($this->buffer) >= $this->hwm) {
131 | return false;
132 | }
133 |
134 | return mb_strlen($string);
135 | }
136 |
137 | public function getMetadata($key = null)
138 | {
139 | if ('hwm' === $key) {
140 | return $this->hwm;
141 | }
142 |
143 | return $key ? null : [];
144 | }
145 | }
146 |
--------------------------------------------------------------------------------
/lib/Http/Psr7/PumpStream.php:
--------------------------------------------------------------------------------
1 | source = $source;
49 | $this->size = isset($options['size']) ? $options['size'] : null;
50 | $this->metadata = isset($options['metadata'])
51 | ? $options['metadata']
52 | : [];
53 | $this->buffer = new BufferStream();
54 | }
55 |
56 | public function __toString(): string
57 | {
58 | try {
59 | return copy_to_string($this);
60 | } catch (\Exception $e) {
61 | return '';
62 | }
63 | }
64 |
65 | public function close(): void
66 | {
67 | $this->detach();
68 | }
69 |
70 | public function detach(): void
71 | {
72 | $this->tellPos = false;
73 | $this->source = null;
74 | }
75 |
76 | public function getSize(): ?int
77 | {
78 | return $this->size;
79 | }
80 |
81 | public function tell(): int
82 | {
83 | return $this->tellPos;
84 | }
85 |
86 | public function eof(): bool
87 | {
88 | return !$this->source;
89 | }
90 |
91 | public function isSeekable(): bool
92 | {
93 | return false;
94 | }
95 |
96 | public function rewind(): void
97 | {
98 | $this->seek(0);
99 | }
100 |
101 | public function seek($offset, $whence = SEEK_SET): void
102 | {
103 | throw new \RuntimeException('Cannot seek a PumpStream');
104 | }
105 |
106 | public function isWritable(): bool
107 | {
108 | return false;
109 | }
110 |
111 | public function write($string): int
112 | {
113 | throw new \RuntimeException('Cannot write to a PumpStream');
114 | }
115 |
116 | public function isReadable(): bool
117 | {
118 | return true;
119 | }
120 |
121 | public function read($length): string
122 | {
123 | $data = $this->buffer->read($length);
124 | $readLen = mb_strlen($data);
125 | $this->tellPos += $readLen;
126 | $remaining = $length - $readLen;
127 |
128 | if ($remaining) {
129 | $this->pump($remaining);
130 | $data .= $this->buffer->read($remaining);
131 | $this->tellPos += mb_strlen($data) - $readLen;
132 | }
133 |
134 | return $data;
135 | }
136 |
137 | public function getContents(): string
138 | {
139 | $result = '';
140 | while (!$this->eof()) {
141 | $result .= $this->read(1000000);
142 | }
143 |
144 | return $result;
145 | }
146 |
147 | public function getMetadata($key = null)
148 | {
149 | if (!$key) {
150 | return $this->metadata;
151 | }
152 |
153 | return isset($this->metadata[$key]) ? $this->metadata[$key] : null;
154 | }
155 |
156 | private function pump($length)
157 | {
158 | if ($this->source) {
159 | do {
160 | $data = call_user_func($this->source, $length);
161 | if (false === $data || null === $data) {
162 | $this->source = null;
163 |
164 | return;
165 | }
166 | $this->buffer->write($data);
167 | $length -= mb_strlen($data);
168 | } while ($length > 0);
169 | }
170 | }
171 | }
172 |
--------------------------------------------------------------------------------
/lib/Http/Psr7/functions.php:
--------------------------------------------------------------------------------
1 | valid()) {
35 | return false;
36 | }
37 | $result = $resource->current();
38 | $resource->next();
39 |
40 | return $result;
41 | }, $options);
42 | } elseif (method_exists($resource, '__toString')) {
43 | return stream_for((string) $resource, $options);
44 | }
45 |
46 | break;
47 |
48 | case 'NULL':
49 | return new Stream(fopen('php://temp', 'r+'), $options);
50 | }
51 | if (is_callable($resource)) {
52 | return new PumpStream($resource, $options);
53 | }
54 |
55 | throw new \InvalidArgumentException('Invalid resource type: '.gettype($resource));
56 | }
57 |
58 | /**
59 | * @internal
60 | *
61 | * @param mixed $maxLen
62 | */
63 | function copy_to_string(StreamInterface $stream, $maxLen = -1)
64 | {
65 | $buffer = '';
66 | if (-1 === $maxLen) {
67 | while (!$stream->eof()) {
68 | $buf = $stream->read(1048576);
69 | // Using a loose equality here to match on '' and false.
70 | if (null === $buf) {
71 | break;
72 | }
73 | $buffer .= $buf;
74 | }
75 |
76 | return $buffer;
77 | }
78 | $len = 0;
79 | while (!$stream->eof() && $len < $maxLen) {
80 | $buf = $stream->read($maxLen - $len);
81 | // Using a loose equality here to match on '' and false.
82 | if (null === $buf) {
83 | break;
84 | }
85 | $buffer .= $buf;
86 | $len = mb_strlen($buffer);
87 | }
88 |
89 | return $buffer;
90 | }
91 |
--------------------------------------------------------------------------------
/lib/Iterators/AbstractAlgoliaIterator.php:
--------------------------------------------------------------------------------
1 | indexName = $indexName;
48 | $this->searchClient = $searchClient;
49 | $this->requestOptions = $requestOptions + [
50 | 'hitsPerPage' => 1000,
51 | ];
52 |
53 | $this->fetchNextPage();
54 | }
55 |
56 | /**
57 | * Return the current element.
58 | *
59 | * @return array
60 | */
61 | #[\ReturnTypeWillChange]
62 | public function current()
63 | {
64 | $hit = $this->response['hits'][$this->batchKey];
65 |
66 | return $this->formatHit($hit);
67 | }
68 |
69 | /**
70 | * Move forward to next element.
71 | */
72 | #[\ReturnTypeWillChange]
73 | public function next()
74 | {
75 | ++$this->key;
76 | ++$this->batchKey;
77 | if ($this->valid()) {
78 | return;
79 | }
80 |
81 | $this->fetchNextPage();
82 | }
83 |
84 | /**
85 | * Return the key of the current element.
86 | *
87 | * @return int
88 | */
89 | #[\ReturnTypeWillChange]
90 | public function key()
91 | {
92 | return $this->key;
93 | }
94 |
95 | /**
96 | * Checks if current position is valid. If the current position
97 | * is not valid, we call Algolia' API to load more results
98 | * until it's the last page.
99 | *
100 | * @return bool the return value will be casted to boolean and then evaluated.
101 | * Returns true on success or false on failure
102 | */
103 | #[\ReturnTypeWillChange]
104 | public function valid()
105 | {
106 | return isset($this->response['hits'][$this->batchKey]);
107 | }
108 |
109 | /**
110 | * Rewind the Iterator to the first element.
111 | */
112 | #[\ReturnTypeWillChange]
113 | public function rewind()
114 | {
115 | if (0 !== $this->key) {
116 | $this->key = 0;
117 | $this->batchKey = 0;
118 | $this->page = 0;
119 | $this->response = null;
120 | $this->fetchNextPage();
121 | }
122 | }
123 |
124 | /**
125 | * Call Algolia' API to get new result batch.
126 | */
127 | abstract protected function fetchNextPage();
128 |
129 | /**
130 | * Sometimes the Iterator is using search internally, this method
131 | * is used to clean the results, like remove the highlight.
132 | *
133 | * @return array formatted synonym array
134 | */
135 | abstract protected function formatHit(array $hit);
136 | }
137 |
--------------------------------------------------------------------------------
/lib/Iterators/ObjectIterator.php:
--------------------------------------------------------------------------------
1 | response['cursor'])
10 | ? $this->response['cursor']
11 | : null;
12 | }
13 |
14 | /**
15 | * Exporting objects (records) doesn't use the search function but the
16 | * browse method, no client-side formatting is required.
17 | *
18 | * @return array the exact same $hit
19 | */
20 | protected function formatHit(array $hit)
21 | {
22 | return $hit;
23 | }
24 |
25 | protected function fetchNextPage()
26 | {
27 | if (is_array($this->response) && !isset($this->response['cursor'])) {
28 | return;
29 | }
30 |
31 | $cursor = [];
32 | if (isset($this->response['cursor'])) {
33 | $cursor['cursor'] = $this->response['cursor'];
34 | }
35 |
36 | $this->response = $this->searchClient->browse(
37 | $this->indexName,
38 | array_merge($this->requestOptions, $cursor)
39 | );
40 |
41 | $this->batchKey = 0;
42 | }
43 | }
44 |
--------------------------------------------------------------------------------
/lib/Iterators/RuleIterator.php:
--------------------------------------------------------------------------------
1 | response)
18 | && $this->key >= count($this->response['hits'])
19 | ) {
20 | return;
21 | }
22 |
23 | $this->response = $this->searchClient->searchRules(
24 | $this->indexName,
25 | array_merge($this->requestOptions, ['page' => $this->page])
26 | );
27 |
28 | $this->batchKey = 0;
29 | ++$this->page;
30 | }
31 | }
32 |
--------------------------------------------------------------------------------
/lib/Iterators/SynonymIterator.php:
--------------------------------------------------------------------------------
1 | response)
18 | && $this->key >= count($this->response['hits'])
19 | ) {
20 | return;
21 | }
22 |
23 | $this->response = $this->searchClient->searchSynonyms(
24 | $this->indexName,
25 | array_merge($this->requestOptions, ['page' => $this->page])
26 | );
27 |
28 | $this->batchKey = 0;
29 | ++$this->page;
30 | }
31 | }
32 |
--------------------------------------------------------------------------------
/lib/Log/DebugLogger.php:
--------------------------------------------------------------------------------
1 | $level,
43 | 'message' => $message,
44 | 'context' => $context,
45 | ];
46 |
47 | if (function_exists('dump')) {
48 | dump($logMessage);
49 | } else {
50 | var_dump($logMessage);
51 | }
52 | }
53 | }
54 | }
55 |
--------------------------------------------------------------------------------
/lib/Model/AbstractModel.php:
--------------------------------------------------------------------------------
1 | 50`, `>` is the operator.
13 | */
14 | class Operator
15 | {
16 | /**
17 | * Possible values of this enum.
18 | */
19 | public const COLON = ':';
20 |
21 | public const LESS_THAN = '<';
22 |
23 | public const LESS_THAN_OR_EQUAL_TO = '<=';
24 |
25 | public const EQUAL = '=';
26 |
27 | public const NOT_EQUAL = '!=';
28 |
29 | public const GREATER_THAN = '>';
30 |
31 | public const GREATER_THAN_OR_EQUAL_TO = '>=';
32 |
33 | /**
34 | * Gets allowable values of the enum.
35 | *
36 | * @return string[]
37 | */
38 | public static function getAllowableEnumValues()
39 | {
40 | return [
41 | self::COLON,
42 | self::LESS_THAN,
43 | self::LESS_THAN_OR_EQUAL_TO,
44 | self::EQUAL,
45 | self::NOT_EQUAL,
46 | self::GREATER_THAN,
47 | self::GREATER_THAN_OR_EQUAL_TO,
48 | ];
49 | }
50 | }
51 |
--------------------------------------------------------------------------------
/lib/Model/Analytics/OrderBy.php:
--------------------------------------------------------------------------------
1 | listInvalidProperties());
140 | }
141 |
142 | /**
143 | * Returns true if offset exists. False otherwise.
144 | *
145 | * @param int $offset Offset
146 | */
147 | public function offsetExists($offset): bool
148 | {
149 | return isset($this->container[$offset]);
150 | }
151 |
152 | /**
153 | * Gets offset.
154 | *
155 | * @param int $offset Offset
156 | *
157 | * @return null|mixed
158 | */
159 | public function offsetGet($offset): mixed
160 | {
161 | return $this->container[$offset] ?? null;
162 | }
163 |
164 | /**
165 | * Sets value based on offset.
166 | *
167 | * @param null|int $offset Offset
168 | * @param mixed $value Value to be set
169 | */
170 | public function offsetSet($offset, $value): void
171 | {
172 | if (is_null($offset)) {
173 | $this->container[] = $value;
174 | } else {
175 | $this->container[$offset] = $value;
176 | }
177 | }
178 |
179 | /**
180 | * Unsets offset.
181 | *
182 | * @param int $offset Offset
183 | */
184 | public function offsetUnset($offset): void
185 | {
186 | unset($this->container[$offset]);
187 | }
188 | }
189 |
--------------------------------------------------------------------------------
/lib/Model/Composition/MatchLevel.php:
--------------------------------------------------------------------------------
1 | listInvalidProperties());
140 | }
141 |
142 | /**
143 | * Returns true if offset exists. False otherwise.
144 | *
145 | * @param int $offset Offset
146 | */
147 | public function offsetExists($offset): bool
148 | {
149 | return isset($this->container[$offset]);
150 | }
151 |
152 | /**
153 | * Gets offset.
154 | *
155 | * @param int $offset Offset
156 | *
157 | * @return null|mixed
158 | */
159 | public function offsetGet($offset): mixed
160 | {
161 | return $this->container[$offset] ?? null;
162 | }
163 |
164 | /**
165 | * Sets value based on offset.
166 | *
167 | * @param null|int $offset Offset
168 | * @param mixed $value Value to be set
169 | */
170 | public function offsetSet($offset, $value): void
171 | {
172 | if (is_null($offset)) {
173 | $this->container[] = $value;
174 | } else {
175 | $this->container[$offset] = $value;
176 | }
177 | }
178 |
179 | /**
180 | * Unsets offset.
181 | *
182 | * @param int $offset Offset
183 | */
184 | public function offsetUnset($offset): void
185 | {
186 | unset($this->container[$offset]);
187 | }
188 | }
189 |
--------------------------------------------------------------------------------
/lib/Model/Ingestion/RecordType.php:
--------------------------------------------------------------------------------
1 | listInvalidProperties());
140 | }
141 |
142 | /**
143 | * Returns true if offset exists. False otherwise.
144 | *
145 | * @param int $offset Offset
146 | */
147 | public function offsetExists($offset): bool
148 | {
149 | return isset($this->container[$offset]);
150 | }
151 |
152 | /**
153 | * Gets offset.
154 | *
155 | * @param int $offset Offset
156 | *
157 | * @return null|mixed
158 | */
159 | public function offsetGet($offset): mixed
160 | {
161 | return $this->container[$offset] ?? null;
162 | }
163 |
164 | /**
165 | * Sets value based on offset.
166 | *
167 | * @param null|int $offset Offset
168 | * @param mixed $value Value to be set
169 | */
170 | public function offsetSet($offset, $value): void
171 | {
172 | if (is_null($offset)) {
173 | $this->container[] = $value;
174 | } else {
175 | $this->container[$offset] = $value;
176 | }
177 | }
178 |
179 | /**
180 | * Unsets offset.
181 | *
182 | * @param int $offset Offset
183 | */
184 | public function offsetUnset($offset): void
185 | {
186 | unset($this->container[$offset]);
187 | }
188 | }
189 |
--------------------------------------------------------------------------------
/lib/Model/Recommend/LookingSimilarModel.php:
--------------------------------------------------------------------------------
1 | listInvalidProperties());
140 | }
141 |
142 | /**
143 | * Returns true if offset exists. False otherwise.
144 | *
145 | * @param int $offset Offset
146 | */
147 | public function offsetExists($offset): bool
148 | {
149 | return isset($this->container[$offset]);
150 | }
151 |
152 | /**
153 | * Gets offset.
154 | *
155 | * @param int $offset Offset
156 | *
157 | * @return null|mixed
158 | */
159 | public function offsetGet($offset): mixed
160 | {
161 | return $this->container[$offset] ?? null;
162 | }
163 |
164 | /**
165 | * Sets value based on offset.
166 | *
167 | * @param null|int $offset Offset
168 | * @param mixed $value Value to be set
169 | */
170 | public function offsetSet($offset, $value): void
171 | {
172 | if (is_null($offset)) {
173 | $this->container[] = $value;
174 | } else {
175 | $this->container[$offset] = $value;
176 | }
177 | }
178 |
179 | /**
180 | * Unsets offset.
181 | *
182 | * @param int $offset Offset
183 | */
184 | public function offsetUnset($offset): void
185 | {
186 | unset($this->container[$offset]);
187 | }
188 | }
189 |
--------------------------------------------------------------------------------
/lib/Model/Search/DictionaryAction.php:
--------------------------------------------------------------------------------
1 | listInvalidProperties());
140 | }
141 |
142 | /**
143 | * Returns true if offset exists. False otherwise.
144 | *
145 | * @param int $offset Offset
146 | */
147 | public function offsetExists($offset): bool
148 | {
149 | return isset($this->container[$offset]);
150 | }
151 |
152 | /**
153 | * Gets offset.
154 | *
155 | * @param int $offset Offset
156 | *
157 | * @return null|mixed
158 | */
159 | public function offsetGet($offset): mixed
160 | {
161 | return $this->container[$offset] ?? null;
162 | }
163 |
164 | /**
165 | * Sets value based on offset.
166 | *
167 | * @param null|int $offset Offset
168 | * @param mixed $value Value to be set
169 | */
170 | public function offsetSet($offset, $value): void
171 | {
172 | if (is_null($offset)) {
173 | $this->container[] = $value;
174 | } else {
175 | $this->container[$offset] = $value;
176 | }
177 | }
178 |
179 | /**
180 | * Unsets offset.
181 | *
182 | * @param int $offset Offset
183 | */
184 | public function offsetUnset($offset): void
185 | {
186 | unset($this->container[$offset]);
187 | }
188 | }
189 |
--------------------------------------------------------------------------------
/lib/Model/Search/LogType.php:
--------------------------------------------------------------------------------
1 | config = $config;
15 | }
16 |
17 | /**
18 | * @param array|RequestOptions $options
19 | *
20 | * @return RequestOptions
21 | */
22 | public function create($options)
23 | {
24 | if (is_array($options)) {
25 | $options = $this->normalize($options);
26 |
27 | $options = new RequestOptions($options);
28 | } elseif ($options instanceof RequestOptions) {
29 | $options = $this->create($options);
30 | } else {
31 | throw new \InvalidArgumentException('RequestOptions can only be created from array or from RequestOptions object');
32 | }
33 |
34 | return $options->addDefaultHeaders($this->config->getDefaultHeaders());
35 | }
36 |
37 | public function createBodyLess($options)
38 | {
39 | $options = $this->create($options);
40 |
41 | return $options->addQueryParameters($options->getBody())->setBody([]);
42 | }
43 |
44 | private function normalize($options)
45 | {
46 | $normalized = [
47 | 'headers' => [
48 | 'x-algolia-application-id' => $this->config->getAppId(),
49 | 'x-algolia-api-key' => $this->config->getAlgoliaApiKey(),
50 | 'User-Agent' => null !== $this->config->getAlgoliaAgent()
51 | ? $this->config->getAlgoliaAgent()
52 | : AlgoliaAgent::get($this->config->getClientName()),
53 | 'Content-Type' => 'application/json',
54 | ],
55 | 'queryParameters' => [],
56 | 'body' => [],
57 | 'readTimeout' => $this->config->getReadTimeout(),
58 | 'writeTimeout' => $this->config->getWriteTimeout(),
59 | 'connectTimeout' => $this->config->getConnectTimeout(),
60 | ];
61 | foreach ($options as $optionName => $value) {
62 | if (is_array($value) && 'headers' === $optionName) {
63 | $headersToLowerCase = [];
64 | foreach ($value as $key => $v) {
65 | $headersToLowerCase[mb_strtolower($key)] = $v;
66 | }
67 |
68 | $normalized[$optionName] = array_merge(
69 | $normalized[$optionName],
70 | $headersToLowerCase
71 | );
72 | } else {
73 | $normalized[$optionName] = $value;
74 | }
75 | }
76 |
77 | return $normalized;
78 | }
79 | }
80 |
--------------------------------------------------------------------------------
/lib/RetryStrategy/ApiWrapperInterface.php:
--------------------------------------------------------------------------------
1 | read = $read;
25 | $this->write = $write;
26 | }
27 |
28 | public static function create($read, $write = null)
29 | {
30 | if (null === $write) {
31 | $write = $read;
32 | }
33 |
34 | if (is_string($read)) {
35 | $read = [$read => 0];
36 | }
37 |
38 | if (is_string($write)) {
39 | $write = [$write => 0];
40 | }
41 |
42 | if (array_values($read) === $read) {
43 | $read = array_fill_keys($read, 0);
44 | }
45 |
46 | if (array_values($write) === $write) {
47 | $write = array_fill_keys($write, 0);
48 | }
49 |
50 | return new self(
51 | HostCollection::create($read),
52 | HostCollection::create($write)
53 | );
54 | }
55 |
56 | public static function createFromAppId($applicationId)
57 | {
58 | $read = $write = [
59 | $applicationId.'-1.algolianet.com' => 0,
60 | $applicationId.'-2.algolianet.com' => 0,
61 | $applicationId.'-3.algolianet.com' => 0,
62 | ];
63 |
64 | $read[$applicationId.'-dsn.algolia.net'] = 10;
65 | $write[$applicationId.'.algolia.net'] = 10;
66 |
67 | return self::create($read, $write)->shuffle();
68 | }
69 |
70 | public static function createFromCache($cacheKey)
71 | {
72 | if (!Algolia::isCacheEnabled()) {
73 | return false;
74 | }
75 |
76 | if (!Algolia::getCache()->has($cacheKey)) {
77 | return false;
78 | }
79 |
80 | return @unserialize(Algolia::getCache()->get($cacheKey));
81 | }
82 |
83 | public function read()
84 | {
85 | return $this->getUrls('read');
86 | }
87 |
88 | public function write()
89 | {
90 | return $this->getUrls('write');
91 | }
92 |
93 | public function failed($host)
94 | {
95 | $this->read->markAsDown($host);
96 | $this->write->markAsDown($host);
97 |
98 | $this->updateCache();
99 |
100 | return $this;
101 | }
102 |
103 | public function reset()
104 | {
105 | $this->read->reset();
106 | $this->write->reset();
107 |
108 | return $this;
109 | }
110 |
111 | public function shuffle()
112 | {
113 | $this->read->shuffle();
114 | $this->write->shuffle();
115 |
116 | return $this;
117 | }
118 |
119 | /**
120 | * Sets the cache key to save the state of the ClusterHosts.
121 | *
122 | * @param string $cacheKey
123 | *
124 | * @return $this
125 | */
126 | public function setCacheKey($cacheKey)
127 | {
128 | $this->cacheKey = $cacheKey;
129 |
130 | return $this;
131 | }
132 |
133 | private function getUrls($type)
134 | {
135 | $urls = $this->{$type}->getUrls();
136 | $lashHashName = 'last'.ucfirst($type).'Hash';
137 |
138 | if (Algolia::isCacheEnabled()) {
139 | $hash = sha1(implode('-', $urls));
140 | if ($hash !== $this->{$lashHashName}) {
141 | $this->updateCache();
142 | }
143 | $this->{$lashHashName} = $hash;
144 | }
145 |
146 | return $urls;
147 | }
148 |
149 | private function updateCache()
150 | {
151 | if (null !== $this->cacheKey && Algolia::isCacheEnabled()) {
152 | Algolia::getCache()->set($this->cacheKey, serialize($this));
153 | }
154 | }
155 | }
156 |
--------------------------------------------------------------------------------
/lib/RetryStrategy/Host.php:
--------------------------------------------------------------------------------
1 | url = $url;
22 | $this->priority = $priority;
23 | }
24 |
25 | public function getUrl()
26 | {
27 | return $this->url;
28 | }
29 |
30 | public function getPriority()
31 | {
32 | return $this->priority;
33 | }
34 |
35 | public function isUp()
36 | {
37 | if (!$this->up) {
38 | $this->resetIfExpired();
39 | }
40 |
41 | return $this->up;
42 | }
43 |
44 | public function markAsDown()
45 | {
46 | $this->up = false;
47 | $this->lastCheck = time();
48 | }
49 |
50 | public function reset()
51 | {
52 | $this->up = true;
53 | $this->lastCheck = null;
54 | }
55 |
56 | private function resetIfExpired()
57 | {
58 | $expired = $this->lastCheck + self::TTL < time();
59 |
60 | if ($expired) {
61 | $this->reset();
62 | }
63 | }
64 | }
65 |
--------------------------------------------------------------------------------
/lib/RetryStrategy/HostCollection.php:
--------------------------------------------------------------------------------
1 | hosts = $hosts;
15 | }
16 |
17 | public static function create(array $urlsWithPriority)
18 | {
19 | $hosts = [];
20 | foreach ($urlsWithPriority as $url => $priority) {
21 | $hosts[] = new Host($url, $priority);
22 | }
23 |
24 | return new self($hosts);
25 | }
26 |
27 | public function get()
28 | {
29 | // We pass the result through array_values because sometimes
30 | // we need to make sure you can access the first element
31 | // via $result[0]
32 | return array_values(
33 | array_filter($this->hosts, function (Host $host) {
34 | return $host->isUp();
35 | })
36 | );
37 | }
38 |
39 | public function getUrls()
40 | {
41 | return array_map(function (Host $host) {
42 | return $host->getUrl();
43 | }, $this->get());
44 | }
45 |
46 | public function markAsDown($hostKey)
47 | {
48 | array_map(function (Host $host) use ($hostKey) {
49 | if ($host->getUrl() === $hostKey) {
50 | $host->markAsDown();
51 | }
52 | }, $this->hosts);
53 | }
54 |
55 | public function shuffle()
56 | {
57 | if (shuffle($this->hosts)) {
58 | $this->sort();
59 | }
60 |
61 | return $this;
62 | }
63 |
64 | public function reset()
65 | {
66 | foreach ($this->hosts as $host) {
67 | $host->reset();
68 | }
69 |
70 | return $this;
71 | }
72 |
73 | private function sort()
74 | {
75 | usort($this->hosts, function (Host $a, Host $b) {
76 | $prioA = $a->getPriority();
77 | $prioB = $b->getPriority();
78 | if ($prioA === $prioB) {
79 | return 0;
80 | }
81 |
82 | return $prioA > $prioB ? -1 : 1;
83 | });
84 | }
85 | }
86 |
--------------------------------------------------------------------------------
/lib/Support/AlgoliaAgent.php:
--------------------------------------------------------------------------------
1 | $version) {
38 | $ua[] = $segment.' ('.$version.')';
39 | }
40 |
41 | return implode('; ', $ua);
42 | }
43 |
44 | private static function getDefaultSegments($clientName)
45 | {
46 | $segments = [];
47 |
48 | $segments['Algolia for PHP'] = Algolia::VERSION;
49 | $segments[$clientName] = Algolia::VERSION;
50 | $segments['PHP'] = rtrim(
51 | str_replace(PHP_EXTRA_VERSION, '', PHP_VERSION),
52 | '-'
53 | );
54 | if (defined('HHVM_VERSION')) {
55 | $segments['HHVM'] = HHVM_VERSION;
56 | }
57 | if (interface_exists('\GuzzleHttp\ClientInterface')) {
58 | if (defined('\GuzzleHttp\ClientInterface::VERSION')) {
59 | $segments['Guzzle'] = ClientInterface::VERSION;
60 | } else {
61 | $segments['Guzzle'] =
62 | ClientInterface::MAJOR_VERSION;
63 | }
64 | }
65 |
66 | return $segments;
67 | }
68 | }
69 |
--------------------------------------------------------------------------------
/phpstan.neon:
--------------------------------------------------------------------------------
1 | parameters:
2 | excludePaths:
3 | - vendor/*
4 | level: max
5 |
--------------------------------------------------------------------------------
/phpunit.xml.dist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | ../../tests/output/php/src/
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------