| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967 |
- <?php
- namespace Webkul\BagistoApi\Providers;
- use ApiPlatform\GraphQl\Resolver\Factory\ResolverFactoryInterface;
- use ApiPlatform\GraphQl\Resolver\QueryCollectionResolverInterface;
- use ApiPlatform\GraphQl\Resolver\QueryItemResolverInterface;
- use ApiPlatform\GraphQl\Type\Definition\IterableType;
- use ApiPlatform\Laravel\Eloquent\State\PersistProcessor;
- use ApiPlatform\Metadata\IdentifiersExtractorInterface;
- use ApiPlatform\Metadata\IriConverterInterface;
- use ApiPlatform\OpenApi\Factory\OpenApiFactoryInterface;
- use ApiPlatform\State\Pagination\Pagination;
- use ApiPlatform\State\ProcessorInterface;
- use ApiPlatform\State\ProviderInterface;
- use Illuminate\Support\ServiceProvider;
- use Webkul\BagistoApi\Console\Commands\GenerateStorefrontKey;
- use Webkul\BagistoApi\Facades\CartTokenFacade;
- use Webkul\BagistoApi\Http\Controllers\AdminGraphQLPlaygroundController;
- use Webkul\BagistoApi\Http\Controllers\GraphQLPlaygroundController;
- use Webkul\BagistoApi\Http\Middleware\VerifyStorefrontKey;
- use Webkul\BagistoApi\Metadata\CustomIdentifiersExtractor;
- use Webkul\BagistoApi\OpenApi\SplitOpenApiFactory;
- use Webkul\BagistoApi\Repositories\GuestCartTokensRepository;
- use Webkul\BagistoApi\Resolver\BaseQueryItemResolver;
- use Webkul\BagistoApi\Resolver\CategoryCollectionResolver;
- use Webkul\BagistoApi\Resolver\CustomerQueryResolver;
- use Webkul\BagistoApi\Resolver\Factory\ProductRelationResolverFactory;
- use Webkul\BagistoApi\Resolver\ProductCollectionResolver;
- use Webkul\BagistoApi\Resolver\SingleProductBagistoApiResolver;
- use Webkul\BagistoApi\Resolver\PageByUrlKeyResolver;
- use Webkul\BagistoApi\Routing\CustomIriConverter;
- use Webkul\BagistoApi\Serializer\TokenHeaderDenormalizer;
- use Webkul\BagistoApi\Services\CartTokenService;
- use Webkul\BagistoApi\Services\PaymentService;
- use Webkul\BagistoApi\Services\StorefrontKeyService;
- use Webkul\BagistoApi\Services\TokenHeaderService;
- use Webkul\BagistoApi\State\PaymentCallbackProcessor;
- use Webkul\BagistoApi\State\PaymentInitiateProcessor;
- use Webkul\BagistoApi\State\PaymentReplayProcessor;
- use Webkul\BagistoApi\State\SaveCheckoutCartProcessor;
- use Webkul\BagistoApi\State\BookingSlotProvider;
- use Webkul\BagistoApi\State\PageProvider;
- use Webkul\BagistoApi\State\AttributeCollectionProvider;
- use Webkul\BagistoApi\State\AttributeOptionCollectionProvider;
- use Webkul\BagistoApi\State\AttributeOptionQueryProvider;
- use Webkul\BagistoApi\State\RepayOrderPaymentMethodsProvider;
- use Webkul\BagistoApi\State\AttributeValueProcessor;
- use Webkul\BagistoApi\State\AuthenticatedCustomerProvider;
- use Webkul\BagistoApi\State\BundleOptionProductsProvider;
- use Webkul\BagistoApi\State\CartTokenMutationProvider;
- use Webkul\BagistoApi\State\CartTokenProcessor;
- use Webkul\BagistoApi\State\CategoryTreeProvider;
- use Webkul\BagistoApi\State\ChannelProvider;
- use Webkul\BagistoApi\State\CheckoutAddressProvider;
- use Webkul\BagistoApi\State\CheckoutProcessor;
- use Webkul\BagistoApi\State\CompareItemProcessor;
- use Webkul\BagistoApi\State\CountryStateCollectionProvider;
- use Webkul\BagistoApi\State\CountryStateQueryProvider;
- use Webkul\BagistoApi\State\CustomerAddressProvider;
- use Webkul\BagistoApi\State\CustomerAddressTokenProcessor;
- use Webkul\BagistoApi\State\CustomerProcessor;
- use Webkul\BagistoApi\State\CustomerProfileProcessor;
- use Webkul\BagistoApi\State\DefaultChannelProvider;
- use Webkul\BagistoApi\State\DownloadableLinksProvider;
- use Webkul\BagistoApi\State\DownloadableProductProcessor;
- use Webkul\BagistoApi\State\DownloadableSamplesProvider;
- use Webkul\BagistoApi\State\FilterableAttributesProvider;
- use Webkul\BagistoApi\State\ForgotPasswordProcessor;
- use Webkul\BagistoApi\State\GetCheckoutAddressCollectionProvider;
- use Webkul\BagistoApi\State\GroupedProductsProvider;
- use Webkul\BagistoApi\State\LoginProcessor;
- use Webkul\BagistoApi\State\LogoutProcessor;
- use Webkul\BagistoApi\State\PaymentMethodsProvider;
- use Webkul\BagistoApi\State\Processor\NewsletterSubscriptionProcessor;
- use Webkul\BagistoApi\State\Processor\ContactUsProcessor;
- use Webkul\BagistoApi\State\ProductBagistoApiProvider;
- use Webkul\BagistoApi\State\ProductGraphQLProvider;
- use Webkul\BagistoApi\State\ProductCustomerGroupPriceProcessor;
- use Webkul\BagistoApi\State\ProductCustomerGroupPriceProvider;
- use Webkul\BagistoApi\State\ProductDetailProvider;
- use Webkul\BagistoApi\State\ProductProcessor;
- use Webkul\BagistoApi\State\ProductRelationProvider;
- use Webkul\BagistoApi\State\ProductRestProvider;
- use Webkul\BagistoApi\State\ProductReviewProcessor;
- use Webkul\BagistoApi\State\ProductReviewProvider;
- use Webkul\BagistoApi\State\ShippingRatesProvider;
- use Webkul\BagistoApi\State\VerifyTokenProcessor;
- use Webkul\BagistoApi\State\CompareItemProvider;
- use Webkul\BagistoApi\State\CustomerDownloadableProductProvider;
- use Webkul\BagistoApi\State\CustomerInvoiceProvider;
- use Webkul\BagistoApi\State\CustomerOrderProvider;
- use Webkul\BagistoApi\State\CustomerOrderShipmentItemProvider;
- use Webkul\BagistoApi\State\CustomerOrderShipmentProvider;
- use Webkul\BagistoApi\State\CustomerReviewProvider;
- use Webkul\BagistoApi\State\WishlistItemProvider;
- use Webkul\BagistoApi\State\WishlistProcessor;
- use Webkul\BagistoApi\State\WishlistProvider;
- use Webkul\BagistoApi\State\MoveWishlistToCartProcessor;
- use Webkul\BagistoApi\State\DeleteAllWishlistsProcessor;
- use Webkul\BagistoApi\State\CancelOrderProcessor;
- use Webkul\BagistoApi\State\ReorderProcessor;
- use Webkul\BagistoApi\State\DeleteAllCompareItemsProcessor;
- use Longyi\ImageUpload\Services\ImageUploadService;
- use ApiPlatform\GraphQl\Serializer\SerializerContextBuilder as GraphQlSerializerContextBuilder;
- use Symfony\Component\Serializer\NameConverter\NameConverterInterface;
- use Webkul\BagistoApi\GraphQl\Serializer\FixedSerializerContextBuilder;
- use Webkul\BagistoApi\State\ProductImageProvider;
- class BagistoApiServiceProvider extends ServiceProvider
- {
- /**
- * Register the service provider bindings.
- */
- public function register(): void
- {
- $this->mergeConfigFrom(__DIR__.'/../../config/bagistoapi.php', 'bagistoapi');
- // Force the API-aware response-cache profile. Spatie's default profile caches
- // every successful GET and hashes by path only, so paginated API responses
- // (?page=2, ?itemsPerPage=5) collapse onto one cache entry.
- config(['responsecache.cache_profile' => \Webkul\BagistoApi\CacheProfiles\ApiAwareResponseCache::class]);
- $this->app->singleton(IterableType::class);
- $this->app->tag(IterableType::class, 'api_platform.graphql.type');
- // $this->overrideApiPlatformLinksHandler();
- $this->registerSnakeCaseLinksHandlerFix();
- $this->app->singleton(ProductImageProvider::class, function ($app) {
- return new ProductImageProvider(
- $app->make(Pagination::class)
- );
- });
- $this->app->singleton(StorefrontKeyService::class, function ($app) {
- return new StorefrontKeyService;
- });
- $this->ensureCorsExposedHeaders(['X-Total-Count', 'X-Page', 'X-Per-Page', 'X-Total-Pages']);
- $this->app->extend(OpenApiFactoryInterface::class, function ($openApiFactory) {
- return new SplitOpenApiFactory($openApiFactory);
- });
- $this->app->singleton(TokenHeaderDenormalizer::class);
- $this->forcePersistentMetadataCache();
- $this->app->singleton('token-header-service', function ($app) {
- return new TokenHeaderService;
- });
- $this->app->alias('token-header-service', 'Webkul\BagistoApi\Services\TokenHeaderService');
- $this->app->singleton('cart-token-service', function ($app) {
- return new CartTokenService(
- $app->make('Webkul\Checkout\Repositories\CartRepository'),
- $app->make('Webkul\BagistoApi\Repositories\GuestCartTokensRepository'),
- $app->make('Webkul\Customer\Repositories\CustomerRepository')
- );
- });
- $this->app->alias('cart-token-service', CartTokenFacade::class);
- $this->app->singleton('Webkul\BagistoApi\Repositories\GuestCartTokensRepository', function ($app) {
- return new GuestCartTokensRepository($app);
- });
- $this->app->tag(ProductProcessor::class, ProcessorInterface::class);
- $this->app->tag(AttributeValueProcessor::class, ProcessorInterface::class);
- $this->app->tag(ProductCustomerGroupPriceProcessor::class, ProcessorInterface::class);
- $this->app->tag(CustomerProcessor::class, ProcessorInterface::class);
- $this->app->tag(LoginProcessor::class, ProcessorInterface::class);
- $this->app->tag(VerifyTokenProcessor::class, ProcessorInterface::class);
- $this->app->tag(LogoutProcessor::class, ProcessorInterface::class);
- $this->app->tag(ForgotPasswordProcessor::class, ProcessorInterface::class);
- $this->app->tag(CustomerProfileProcessor::class, ProcessorInterface::class);
- $this->app->tag(CustomerAddressTokenProcessor::class, ProcessorInterface::class);
- $this->app->tag(CartTokenProcessor::class, ProcessorInterface::class);
- $this->app->tag(CheckoutProcessor::class, ProcessorInterface::class);
- $this->app->tag(PaymentInitiateProcessor::class, ProcessorInterface::class);
- $this->app->tag(PaymentCallbackProcessor::class, ProcessorInterface::class);
- $this->app->tag(PaymentReplayProcessor::class, ProcessorInterface::class);
- $this->app->tag(ProductReviewProcessor::class, ProcessorInterface::class);
- $this->app->tag(CompareItemProcessor::class, ProcessorInterface::class);
- $this->app->tag(DownloadableProductProcessor::class, ProcessorInterface::class);
- $this->app->tag(NewsletterSubscriptionProcessor::class, ProcessorInterface::class);
- $this->app->tag(WishlistProcessor::class, ProcessorInterface::class);
- $this->app->tag(\Webkul\BagistoApi\State\GdprRequestProcessor::class, ProcessorInterface::class);
- $this->app->tag(MoveWishlistToCartProcessor::class, ProcessorInterface::class);
- $this->app->tag(DeleteAllWishlistsProcessor::class, ProcessorInterface::class);
- $this->app->tag(DeleteAllCompareItemsProcessor::class, ProcessorInterface::class);
- $this->app->tag(CancelOrderProcessor::class, ProcessorInterface::class);
- $this->app->tag(ReorderProcessor::class, ProcessorInterface::class);
- $this->app->tag(ContactUsProcessor::class, ProcessorInterface::class);
- $this->app->tag(SaveCheckoutCartProcessor::class, ProcessorInterface::class);
- $this->app->tag(TokenHeaderDenormalizer::class, 'serializer.normalizer');
- $this->app->extend('api_platform_normalizer_list', function (\SplPriorityQueue $list, $app) {
- $list->insert(
- $app->make(\Webkul\BagistoApi\Serializer\PaginationHeaderNormalizer::class),
- 1000
- );
- return $list;
- });
- $this->app->singleton(ProductCustomerGroupPriceProcessor::class, function ($app) {
- return new ProductCustomerGroupPriceProcessor(
- $app->make(PersistProcessor::class)
- );
- });
- $this->app->singleton(CustomerProcessor::class, function ($app) {
- return new CustomerProcessor(
- $app->make('Webkul\Customer\Repositories\CustomerRepository'),
- $app->make('Webkul\BagistoApi\Validators\CustomerValidator')
- );
- });
- $this->app->singleton(LoginProcessor::class, function ($app) {
- return new LoginProcessor(
- $app->make('Webkul\BagistoApi\Validators\LoginValidator')
- );
- });
- $this->app->singleton(CustomerProfileProcessor::class, function ($app) {
- return new CustomerProfileProcessor(
- $app->make('Webkul\BagistoApi\Validators\CustomerValidator')
- );
- });
- $this->app->singleton(CartTokenProcessor::class, function ($app) {
- return new CartTokenProcessor(
- $app->make('Webkul\Checkout\Repositories\CartRepository'),
- $app->make('Webkul\BagistoApi\Repositories\GuestCartTokensRepository')
- );
- });
- $this->app->singleton(PaymentService::class, function ($app) {
- return new PaymentService(
- $app->make('Webkul\Sales\Repositories\OrderRepository'),
- $app->make('Webkul\Checkout\Repositories\CartRepository'),
- $app->make('cart-token-service'),
- $app->make('Webkul\Sales\Repositories\InvoiceRepository'),
- $app->make('Webkul\Sales\Repositories\OrderTransactionRepository'),
- $app->make('Webkul\BagistoApi\Repositories\PaymentAttemptRepository'),
- );
- });
- $this->app->singleton(SaveCheckoutCartProcessor::class, function ($app) {
- return new SaveCheckoutCartProcessor(
- $app->make('Webkul\CartRule\Repositories\CartRuleCouponRepository'),
- );
- });
- $this->app->singleton(CheckoutProcessor::class, function ($app) {
- return new CheckoutProcessor(
- $app->make('Webkul\Customer\Repositories\CustomerRepository'),
- $app->make('Webkul\Sales\Repositories\OrderRepository'),
- $app->make('Webkul\Checkout\Repositories\CartRepository'),
- $app->make(PaymentService::class),
- );
- });
- $this->app->singleton(PaymentInitiateProcessor::class, function ($app) {
- return new PaymentInitiateProcessor(
- $app->make(PaymentService::class),
- );
- });
- $this->app->singleton(PaymentCallbackProcessor::class, function ($app) {
- return new PaymentCallbackProcessor(
- $app->make(PaymentService::class),
- );
- });
- $this->app->singleton(PaymentReplayProcessor::class, function ($app) {
- return new PaymentReplayProcessor(
- $app->make(PaymentService::class),
- );
- });
- $this->app->singleton(ProductReviewProcessor::class, function ($app) {
- return new ProductReviewProcessor(
- $app->make(PersistProcessor::class),
- $app->make(ImageUploadService::class)
- );
- });
- $this->app->singleton(CompareItemProcessor::class, function ($app) {
- return new CompareItemProcessor(
- $app->make(PersistProcessor::class)
- );
- });
- $this->app->singleton(WishlistProcessor::class, function ($app) {
- return new WishlistProcessor(
- $app->make(PersistProcessor::class)
- );
- });
- $this->app->singleton(MoveWishlistToCartProcessor::class, function ($app) {
- return new MoveWishlistToCartProcessor(
- $app->make(PersistProcessor::class)
- );
- });
- $this->app->singleton(DeleteAllWishlistsProcessor::class, function ($app) {
- return new DeleteAllWishlistsProcessor(
- $app->make(PersistProcessor::class)
- );
- });
- $this->app->singleton(DeleteAllCompareItemsProcessor::class, function ($app) {
- return new DeleteAllCompareItemsProcessor(
- $app->make(PersistProcessor::class)
- );
- });
- $this->app->singleton(CancelOrderProcessor::class, function ($app) {
- return new CancelOrderProcessor(
- $app->make(PersistProcessor::class),
- $app->make('Webkul\Sales\Repositories\OrderRepository'),
- $app->make(PaymentService::class),
- );
- });
- $this->app->singleton(ReorderProcessor::class, function ($app) {
- return new ReorderProcessor(
- $app->make(PersistProcessor::class)
- );
- });
- $this->app->singleton(LogoutProcessor::class, function ($app) {
- return new LogoutProcessor();
- });
- $this->app->tag(CheckoutAddressProvider::class, ProviderInterface::class);
- $this->app->tag(CustomerAddressProvider::class, ProviderInterface::class);
- $this->app->tag(GetCheckoutAddressCollectionProvider::class, ProviderInterface::class);
- $this->app->tag(PaymentMethodsProvider::class, ProviderInterface::class);
- $this->app->tag(RepayOrderPaymentMethodsProvider::class, ProviderInterface::class);
- $this->app->tag(ShippingRatesProvider::class, ProviderInterface::class);
- $this->app->tag(AuthenticatedCustomerProvider::class, ProviderInterface::class);
- $this->app->tag(\Webkul\BagistoApi\State\CustomerProfileCollectionProvider::class, ProviderInterface::class);
- $this->app->tag(CartTokenMutationProvider::class, ProviderInterface::class);
- $this->app->tag(ChannelProvider::class, ProviderInterface::class);
- $this->app->tag(DefaultChannelProvider::class, ProviderInterface::class);
- $this->app->tag(ProductBagistoApiProvider::class, ProviderInterface::class);
- $this->app->tag(ProductGraphQLProvider::class, ProviderInterface::class);
- $this->app->tag(ProductRestProvider::class, ProviderInterface::class);
- $this->app->tag(ProductDetailProvider::class, ProviderInterface::class);
- $this->app->tag(ProductImageProvider::class, ProviderInterface::class);
- $this->app->tag(ProductCustomerGroupPriceProvider::class, ProviderInterface::class);
- $this->app->tag(ProductRelationProvider::class, ProviderInterface::class);
- $this->app->tag(BundleOptionProductsProvider::class, ProviderInterface::class);
- $this->app->tag(GroupedProductsProvider::class, ProviderInterface::class);
- $this->app->tag(DownloadableLinksProvider::class, ProviderInterface::class);
- $this->app->tag(DownloadableSamplesProvider::class, ProviderInterface::class);
- $this->app->tag(ProductReviewProvider::class, ProviderInterface::class);
- $this->app->tag(FilterableAttributesProvider::class, ProviderInterface::class);
- $this->app->tag(AttributeCollectionProvider::class, ProviderInterface::class);
- $this->app->tag(AttributeOptionCollectionProvider::class, ProviderInterface::class);
- $this->app->tag(AttributeOptionQueryProvider::class, ProviderInterface::class);
- $this->app->tag(CountryStateCollectionProvider::class, ProviderInterface::class);
- $this->app->tag(CountryStateQueryProvider::class, ProviderInterface::class);
- $this->app->tag(CategoryTreeProvider::class, ProviderInterface::class);
- $this->app->tag(\Webkul\BagistoApi\State\CategoryRestProvider::class, ProviderInterface::class);
- $this->app->tag(BookingSlotProvider::class, ProviderInterface::class);
- $this->app->tag(\Webkul\BagistoApi\State\BookingProductDetailProvider::class, ProviderInterface::class);
- $this->app->tag(PageProvider::class, ProviderInterface::class);
- $this->app->tag(\Webkul\BagistoApi\State\CursorAwareCollectionProvider::class, ProviderInterface::class);
- $this->app->tag(WishlistProvider::class, ProviderInterface::class);
- $this->app->tag(WishlistItemProvider::class, ProviderInterface::class);
- $this->app->tag(\Webkul\BagistoApi\State\GdprRequestProvider::class, ProviderInterface::class);
- $this->app->tag(\Webkul\BagistoApi\State\GdprRequestItemProvider::class, ProviderInterface::class);
- $this->app->tag(CompareItemProvider::class, ProviderInterface::class);
- $this->app->tag(CustomerReviewProvider::class, ProviderInterface::class);
- $this->app->tag(CustomerOrderProvider::class, ProviderInterface::class);
- $this->app->tag(CustomerDownloadableProductProvider::class, ProviderInterface::class);
- $this->app->tag(CustomerInvoiceProvider::class, ProviderInterface::class);
- $this->app->tag(CustomerOrderShipmentProvider::class, ProviderInterface::class);
- $this->app->tag(CustomerOrderShipmentItemProvider::class, ProviderInterface::class);
- $this->app->singleton(GetCheckoutAddressCollectionProvider::class, function ($app) {
- return new GetCheckoutAddressCollectionProvider(
- $app->make('ApiPlatform\State\Pagination\Pagination')
- );
- });
- $this->app->singleton(WishlistProvider::class, function ($app) {
- return new WishlistProvider(
- $app->make(Pagination::class)
- );
- });
- $this->app->singleton(\Webkul\BagistoApi\State\GdprRequestProvider::class, function ($app) {
- return new \Webkul\BagistoApi\State\GdprRequestProvider(
- $app->make(Pagination::class)
- );
- });
- $this->app->singleton(CompareItemProvider::class, function ($app) {
- return new CompareItemProvider(
- $app->make(Pagination::class)
- );
- });
- $this->app->singleton(CustomerReviewProvider::class, function ($app) {
- return new CustomerReviewProvider(
- $app->make(Pagination::class)
- );
- });
- $this->app->singleton(CustomerOrderProvider::class, function ($app) {
- return new CustomerOrderProvider(
- $app->make(Pagination::class)
- );
- });
- $this->app->singleton(CustomerDownloadableProductProvider::class, function ($app) {
- return new CustomerDownloadableProductProvider(
- $app->make(Pagination::class)
- );
- });
- $this->app->singleton(CustomerInvoiceProvider::class, function ($app) {
- return new CustomerInvoiceProvider(
- $app->make(Pagination::class)
- );
- });
- $this->app->singleton(CustomerOrderShipmentProvider::class, function ($app) {
- return new CustomerOrderShipmentProvider(
- $app->make(Pagination::class)
- );
- });
- $this->app->singleton(CustomerOrderShipmentItemProvider::class, function ($app) {
- return new CustomerOrderShipmentItemProvider(
- $app->make(Pagination::class)
- );
- });
- $this->app->singleton(CustomerAddressProvider::class, function ($app) {
- return new CustomerAddressProvider(
- $app->make(Pagination::class)
- );
- });
- $this->app->singleton(ProductBagistoApiProvider::class, function ($app) {
- return new ProductBagistoApiProvider(
- $app->make(Pagination::class)
- );
- });
- $this->app->singleton(ProductGraphQLProvider::class, function ($app) {
- return new ProductGraphQLProvider(
- $app->make(Pagination::class),
- $app->make(\Webkul\Product\Repositories\ElasticSearchRepository::class)
- );
- });
- $this->app->singleton(\Webkul\BagistoApi\State\ProductRelationFlagResolver::class);
- $this->app->singleton(ProductRelationProvider::class, function ($app) {
- return new ProductRelationProvider(
- $app->make(Pagination::class)
- );
- });
- $this->app->singleton(ProductReviewProvider::class, function ($app) {
- return new ProductReviewProvider(
- $app->make(Pagination::class)
- );
- });
- $this->app->singleton(GroupedProductsProvider::class, function ($app) {
- return new GroupedProductsProvider(
- $app->make(Pagination::class)
- );
- });
- $this->app->singleton(DownloadableLinksProvider::class, function ($app) {
- return new DownloadableLinksProvider(
- $app->make(Pagination::class)
- );
- });
- $this->app->singleton(DownloadableSamplesProvider::class, function ($app) {
- return new DownloadableSamplesProvider(
- $app->make(Pagination::class)
- );
- });
- $this->app->singleton(FilterableAttributesProvider::class, function ($app) {
- return new FilterableAttributesProvider(
- $app->make(\ApiPlatform\State\Pagination\Pagination::class)
- );
- });
- $this->app->singleton(AttributeCollectionProvider::class, function ($app) {
- return new AttributeCollectionProvider(
- $app->make(Pagination::class)
- );
- });
- $this->app->singleton(AttributeOptionCollectionProvider::class, function ($app) {
- return new AttributeOptionCollectionProvider(
- $app->make(Pagination::class)
- );
- });
- $this->app->singleton(CountryStateCollectionProvider::class, function ($app) {
- return new CountryStateCollectionProvider(
- $app->make(Pagination::class)
- );
- });
- $this->app->singleton(ProductCollectionResolver::class);
- $this->app->tag(SingleProductBagistoApiResolver::class, QueryItemResolverInterface::class);
- $this->app->tag(CategoryCollectionResolver::class, QueryCollectionResolverInterface::class);
- $this->app->tag(BaseQueryItemResolver::class, QueryItemResolverInterface::class);
- $this->app->tag(\Webkul\BagistoApi\Resolver\WishlistQueryResolver::class, QueryItemResolverInterface::class);
- $this->app->tag(\Webkul\BagistoApi\Resolver\GdprRequestQueryResolver::class, QueryItemResolverInterface::class);
- $this->app->tag(CustomerQueryResolver::class, QueryItemResolverInterface::class);
- $this->app->tag(PageByUrlKeyResolver::class, QueryCollectionResolverInterface::class);
- $this->app->extend(ResolverFactoryInterface::class, function ($resolverFactory, $app) {
- return new ProductRelationResolverFactory(
- $resolverFactory,
- $app->make(ProductRelationProvider::class)
- );
- });
- $this->app->extend(IdentifiersExtractorInterface::class, function ($extractor) {
- return new CustomIdentifiersExtractor($extractor);
- });
- $this->app->extend(IriConverterInterface::class, function ($converter, $app) {
- return new CustomIriConverter(
- $converter,
- $app->make(\ApiPlatform\Metadata\Resource\Factory\ResourceMetadataCollectionFactoryInterface::class)
- );
- });
- $this->app->extend(GraphQlSerializerContextBuilder::class, function ($builder, $app) {
- return new FixedSerializerContextBuilder(
- $builder,
- $app->make(NameConverterInterface::class)
- );
- });
- }
- /**
- * Replace ApiPlatform's default CollectionProvider/ItemProvider so that
- * sub-collection relations (GraphQL) use our CamelCaseAwareLinksHandler.
- *
- * ApiPlatform's own LinksHandler compares GraphQL camelCase fieldnames
- * (e.g. "flexibleVariants") with snake_case Link::fromProperty (e.g.
- * "flexible_variants"); the mismatch causes sub-collection queries to
- * skip the parent-id WHERE clause and return every row in the child
- * table. Our handler normalizes both sides before comparing and
- * re-resolves the relation by method name.
- */
- /**
- * Replace ApiPlatform's CollectionProvider/ItemProvider so the inner
- * LinksHandler is our camelCase-aware variant.
- *
- * ApiPlatform ships its bindings via ApiPlatformDeferredProvider (a
- * DeferrableProvider whose register() only runs when the binding is
- * first resolved — i.e. after every other ServiceProvider::register()).
- * We use Container::extend() so our decorator runs *after* ApiPlatform
- * has built the original singleton. extend() also remembers our closure
- * for bindings that don't exist yet, so registration order is safe.
- *
- * The provider's $linksHandler is a readonly promoted property and
- * therefore cannot be replaced via Reflection on PHP 8.1+. Instead we
- * rebuild the singleton with the same dependencies.
- */
- protected function overrideApiPlatformLinksHandler(): void
- {
- $buildHandler = fn ($app) => new \Webkul\BagistoApi\State\CamelCaseAwareLinksHandler(
- $app,
- $app->make(\ApiPlatform\Metadata\Resource\Factory\ResourceMetadataCollectionFactoryInterface::class)
- );
- $this->app->extend(
- \ApiPlatform\Laravel\Eloquent\State\CollectionProvider::class,
- function ($original, $app) use ($buildHandler) {
- if (! $original instanceof \ApiPlatform\Laravel\Eloquent\State\CollectionProvider) {
- return $original;
- }
- $ref = new \ReflectionObject($original);
- $queryExtensions = $this->readPrivate($ref, $original, 'queryExtensions');
- $handleLinksLoc = $this->readPrivate($ref, $original, 'handleLinksLocator');
- return new \ApiPlatform\Laravel\Eloquent\State\CollectionProvider(
- $app->make(\ApiPlatform\State\Pagination\Pagination::class),
- $buildHandler($app),
- $queryExtensions ?? [],
- $handleLinksLoc
- );
- }
- );
- $this->app->extend(
- \ApiPlatform\Laravel\Eloquent\State\ItemProvider::class,
- function ($original, $app) use ($buildHandler) {
- if (! $original instanceof \ApiPlatform\Laravel\Eloquent\State\ItemProvider) {
- return $original;
- }
- $ref = new \ReflectionObject($original);
- $handleLinksLoc = $this->readPrivate($ref, $original, 'handleLinksLocator');
- $queryExtensions = $this->readPrivate($ref, $original, 'queryExtensions');
- return new \ApiPlatform\Laravel\Eloquent\State\ItemProvider(
- $buildHandler($app),
- $handleLinksLoc,
- $queryExtensions ?? []
- );
- }
- );
- }
- private function readPrivate(\ReflectionObject $ref, object $instance, string $propertyName): mixed
- {
- if (! $ref->hasProperty($propertyName)) {
- return null;
- }
- $prop = $ref->getProperty($propertyName);
- $prop->setAccessible(true);
- return $prop->getValue($instance);
- }
- /**
- * Keep API Platform's resource-metadata caches on a PERSISTENT store even when
- * APP_DEBUG=true.
- *
- * api-platform/laravel's ApiPlatformProvider::register() (≈ lines 271-323) binds
- * PropertyMetadataFactoryInterface and PropertyNameCollectionFactoryInterface with the
- * cache store hardcoded to 'array' whenever app.debug is true. The 'array' store is
- * in-memory and dropped after each request, so the OpenAPI doc routes (/api/shop,
- * /api/admin) rebuild metadata for every resource on every hit and exceed PHP's
- * max_execution_time (>30s). Real single-resource endpoints are unaffected.
- *
- * We re-bind both factories identically to vendor but force the configured persistent
- * store (api-platform.cache, default 'file') regardless of app.debug — restoring the
- * 2.3.8 behaviour where debug mode did not disable metadata caching. The package's
- * NullableToOnePropertyMetadataFactory extender (registered above) still applies on top.
- *
- * NOTE: this mirrors the vendor decorator chain. If api-platform/laravel changes the
- * inner factories, re-sync this method against ApiPlatformProvider::register().
- */
- protected function forcePersistentMetadataCache(): void
- {
- $store = config('api-platform.cache', 'file');
- $this->app->singleton(
- \ApiPlatform\Metadata\Property\Factory\PropertyMetadataFactoryInterface::class,
- function ($app) use ($store) {
- $nameConverter = config('api-platform.name_converter', \Symfony\Component\Serializer\NameConverter\SnakeCaseToCamelCaseNameConverter::class);
- if ($nameConverter && class_exists($nameConverter)) {
- $nameConverter = new \ApiPlatform\Laravel\Eloquent\Serializer\EloquentNameConverter($app->make($nameConverter));
- }
- return new \ApiPlatform\Laravel\Metadata\CachePropertyMetadataFactory(
- new \ApiPlatform\JsonSchema\Metadata\Property\Factory\SchemaPropertyMetadataFactory(
- $app->make(\ApiPlatform\Metadata\ResourceClassResolverInterface::class),
- new \ApiPlatform\Metadata\Property\Factory\SerializerPropertyMetadataFactory(
- $app->make(\ApiPlatform\Serializer\Mapping\Factory\ClassMetadataFactory::class),
- new \ApiPlatform\Metadata\Property\Factory\PropertyInfoPropertyMetadataFactory(
- $app->make(\Symfony\Component\PropertyInfo\PropertyInfoExtractorInterface::class),
- new \ApiPlatform\Metadata\Property\Factory\AttributePropertyMetadataFactory(
- new \ApiPlatform\Laravel\Eloquent\Metadata\Factory\Property\EloquentAttributePropertyMetadataFactory(
- new \ApiPlatform\Laravel\Eloquent\Metadata\Factory\Property\EloquentPropertyMetadataFactory(
- $app->make(\ApiPlatform\Laravel\Eloquent\Metadata\ModelMetadata::class),
- ),
- ),
- $nameConverter
- ),
- $app->make(\ApiPlatform\Metadata\ResourceClassResolverInterface::class)
- ),
- )
- ),
- $store
- );
- }
- );
- $this->app->singleton(
- \ApiPlatform\Metadata\Property\Factory\PropertyNameCollectionFactoryInterface::class,
- function ($app) use ($store) {
- $nameConverter = config('api-platform.name_converter', \Symfony\Component\Serializer\NameConverter\SnakeCaseToCamelCaseNameConverter::class);
- if ($nameConverter && class_exists($nameConverter)) {
- $nameConverter = new \ApiPlatform\Laravel\Eloquent\Serializer\EloquentNameConverter($app->make($nameConverter));
- }
- return new \ApiPlatform\Laravel\Metadata\CachePropertyNameCollectionMetadataFactory(
- new \ApiPlatform\Metadata\Property\Factory\ClassLevelAttributePropertyNameCollectionFactory(
- new \ApiPlatform\Metadata\Property\Factory\ConcernsPropertyNameCollectionMetadataFactory(
- new \ApiPlatform\Laravel\Eloquent\Metadata\Factory\Property\EloquentPropertyNameCollectionMetadataFactory(
- $app->make(\ApiPlatform\Laravel\Eloquent\Metadata\ModelMetadata::class),
- new \ApiPlatform\Metadata\Property\Factory\PropertyInfoPropertyNameCollectionFactory($app->make(\Symfony\Component\PropertyInfo\PropertyInfoExtractorInterface::class)),
- $app->make(\ApiPlatform\Metadata\ResourceClassResolverInterface::class)
- )
- ),
- $nameConverter
- ),
- $store
- );
- }
- );
- }
- /**
- * Bootstrap services.
- */
- public function boot(): void
- {
- $this->loadTranslationsFrom(__DIR__.'/../Resources/lang', 'bagistoapi');
- $this->loadMigrationsFrom(__DIR__.'/../Database/Migrations');
- $this->loadViewsFrom(__DIR__.'/../Resources/views', 'webkul');
- if ($this->isRunningAsVendorPackage()) {
- $this->publishes([
- __DIR__.'/../config/api-platform-vendor.php' => config_path('api-platform.php'),
- ], 'bagistoapi-config');
- } else {
- $this->publishes([
- __DIR__.'/../config/api-platform.php' => config_path('api-platform.php'),
- ], 'bagistoapi-config');
- }
- $this->publishes([
- __DIR__.'/../config/graphql-auth.php' => config_path('graphql-auth.php'),
- __DIR__.'/../config/storefront.php' => config_path('storefront.php'),
- __DIR__.'/../config/bagistoapi.php' => config_path('bagistoapi.php'),
- ], 'bagistoapi-config');
- $this->publishes([
- __DIR__.'/../resources/views' => resource_path('views/vendor/webkul'),
- ], 'bagistoapi-views');
- $this->publishes([
- __DIR__.'/../Resources/assets' => public_path('themes/admin/default/assets'),
- ], 'bagistoapi-assets');
- $this->runInstallationIfNeeded();
- $this->registerApiResources();
- $this->registerApiDocumentationRoutes();
- $this->registerMiddlewareAliases();
- $this->registerGlobalMiddleware();
- $this->registerServiceProviders();
- if ($this->app->runningInConsole()) {
- $this->registerCommands();
- }
- }
- /**
- * Register API documentation routes.
- */
- protected function registerApiDocumentationRoutes(): void
- {
- \Illuminate\Support\Facades\Route::get('/api', \Webkul\BagistoApi\Http\Controllers\ApiEntrypointController::class)
- ->name('bagistoapi.docs-index');
- \Illuminate\Support\Facades\Route::get('/api/shop', [
- \Webkul\BagistoApi\Http\Controllers\SwaggerUIController::class, 'shopApi',
- ])->name('bagistoapi.shop-docs')->where('_format', '^(?!json|xml|csv)');
- \Illuminate\Support\Facades\Route::get('/api/admin', [
- \Webkul\BagistoApi\Http\Controllers\SwaggerUIController::class, 'adminApi',
- ])->name('bagistoapi.admin-docs')->where('_format', '^(?!json|xml|csv)');
- \Illuminate\Support\Facades\Route::get('/api/shop/docs', [
- \Webkul\BagistoApi\Http\Controllers\SwaggerUIController::class, 'shopApiDocs',
- ])->name('bagistoapi.shop-api-spec');
- \Illuminate\Support\Facades\Route::get('/api/admin/docs', [
- \Webkul\BagistoApi\Http\Controllers\SwaggerUIController::class, 'adminApiDocs',
- ])->name('bagistoapi.admin-api-spec');
- \Illuminate\Support\Facades\Route::get('/api/graphiql', GraphQLPlaygroundController::class)
- ->name('bagistoapi.graphql-playground');
- \Illuminate\Support\Facades\Route::get('/api/graphql', GraphQLPlaygroundController::class)
- ->name('bagistoapi.api-graphql-playground');
- \Illuminate\Support\Facades\Route::get('/admin/graphiql', AdminGraphQLPlaygroundController::class)
- ->name('bagistoapi.admin-graphql-playground');
- \Illuminate\Support\Facades\Route::get('/api/shop/customer-invoices/{id}/pdf', \Webkul\BagistoApi\Http\Controllers\InvoicePdfController::class)
- ->where('id', '[0-9]+')
- ->middleware(['Webkul\BagistoApi\Http\Middleware\VerifyStorefrontKey'])
- ->name('bagistoapi.customer-invoice-pdf');
- \Illuminate\Support\Facades\Route::get('/api/downloadable/download-sample/{type}/{id}', \Webkul\BagistoApi\Http\Controllers\DownloadSampleController::class)
- ->where('type', 'link|sample')
- ->where('id', '[0-9]+')
- ->name('bagistoapi.download-sample');
- \Illuminate\Support\Facades\Route::get('/api/shop/customer-downloadable-products/{id}/download', \Webkul\BagistoApi\Http\Controllers\DownloadablePurchasedController::class)
- ->where('id', '[0-9]+')
- ->middleware(['Webkul\BagistoApi\Http\Middleware\VerifyStorefrontKey'])
- ->name('bagistoapi.customer-downloadable-product-download');
- }
- /**
- * Register API resources.
- */
- protected function registerApiResources(): void
- {
- if ($this->app->bound('api_platform.metadata_factory')) {
- }
- }
- /**
- * Run installation if needed.
- */
- protected function runInstallationIfNeeded(): void
- {
- if (file_exists(config_path('api-platform.php'))) {
- return;
- }
- if (! $this->app->runningInConsole() || ! $this->isComposerOperation()) {
- return;
- }
- try {
- $this->app['artisan']->call('bagisto-api-platform:install', ['--quiet' => true]);
- } catch (\Exception) {
- // Installation can be run manually if needed
- }
- }
- /**
- * Determine if running via Composer.
- */
- protected function isComposerOperation(): bool
- {
- $composerMemory = getenv('COMPOSER_MEMORY_LIMIT');
- $composerAuth = getenv('COMPOSER_AUTH');
- return ! empty($composerMemory) || ! empty($composerAuth) || defined('COMPOSER_BINARY_PATH');
- }
- /**
- * Register middleware aliases.
- */
- protected function registerMiddlewareAliases(): void
- {
- $this->app['router']->aliasMiddleware('storefront.key', VerifyStorefrontKey::class);
- $this->app['router']->aliasMiddleware('api.locale-channel', \Webkul\BagistoApi\Http\Middleware\SetLocaleChannel::class);
- $this->app['router']->aliasMiddleware('api.rate-limit', \Webkul\BagistoApi\Http\Middleware\RateLimitApi::class);
- $this->app['router']->aliasMiddleware('api.security-headers', \Webkul\BagistoApi\Http\Middleware\SecurityHeaders::class);
- $this->app['router']->aliasMiddleware('api.log-requests', \Webkul\BagistoApi\Http\Middleware\LogApiRequests::class);
- }
- /**
- * Register global middleware that runs on every HTTP request.
- * EnsureJsonContentType lets bodyless POST endpoints (e.g., delete-all-*)
- * work without clients needing to send a Content-Type header.
- */
- protected function registerGlobalMiddleware(): void
- {
- $kernel = $this->app->make(\Illuminate\Contracts\Http\Kernel::class);
- $kernel->prependMiddleware(\Webkul\BagistoApi\Http\Middleware\EnsureJsonContentType::class);
- }
- /**
- * Make our X-* pagination headers visible to JS clients via CORS without
- * requiring users to edit config/cors.php.
- */
- private function ensureCorsExposedHeaders(array $headers): void
- {
- $existing = config('cors.exposed_headers', []);
- $merged = array_values(array_unique(array_merge($existing, $headers)));
- if ($merged !== $existing) {
- config(['cors.exposed_headers' => $merged]);
- }
- }
- /**
- * Register service providers.
- */
- protected function registerServiceProviders(): void
- {
- $this->app->register(ApiPlatformExceptionHandlerServiceProvider::class);
- $this->app->register(DatabaseQueryLoggingProvider::class);
- $this->app->register(ExceptionHandlerServiceProvider::class);
- }
- /**
- * Register console commands.
- */
- protected function registerCommands(): void
- {
- $this->commands([
- \Webkul\BagistoApi\Console\Commands\InstallApiPlatformCommand::class,
- \Webkul\BagistoApi\Console\Commands\ClearApiPlatformCacheCommand::class,
- GenerateStorefrontKey::class,
- \Webkul\BagistoApi\Console\Commands\ApiKeyManagementCommand::class,
- \Webkul\BagistoApi\Console\Commands\ApiKeyMaintenanceCommand::class,
- ]);
- }
- /**
- * Override API Platform's ItemProvider and CollectionProvider to wrap the
- * LinksHandler with SnakeCaseLinksHandler, fixing the camelCase/snake_case
- * mismatch between GraphQL field names and Eloquent relationship names.
- */
- protected function registerSnakeCaseLinksHandlerFix(): void
- {
- $this->app->extend(
- \ApiPlatform\Laravel\Eloquent\State\ItemProvider::class,
- function ($original, $app) {
- $linksHandler = new \Webkul\BagistoApi\State\SnakeCaseLinksHandler(
- new \ApiPlatform\Laravel\Eloquent\State\LinksHandler(
- $app,
- $app->make(\ApiPlatform\Metadata\Resource\Factory\ResourceMetadataCollectionFactoryInterface::class)
- )
- );
- $tagged = iterator_to_array($app->tagged(\ApiPlatform\Laravel\Eloquent\State\LinksHandlerInterface::class));
- return new \ApiPlatform\Laravel\Eloquent\State\ItemProvider(
- $linksHandler,
- new \ApiPlatform\Laravel\ServiceLocator($tagged),
- $app->tagged(\ApiPlatform\Laravel\Eloquent\Extension\QueryExtensionInterface::class)
- );
- }
- );
- $this->app->extend(
- \ApiPlatform\Laravel\Eloquent\State\CollectionProvider::class,
- function ($original, $app) {
- $linksHandler = new \Webkul\BagistoApi\State\SnakeCaseLinksHandler(
- new \ApiPlatform\Laravel\Eloquent\State\LinksHandler(
- $app,
- $app->make(\ApiPlatform\Metadata\Resource\Factory\ResourceMetadataCollectionFactoryInterface::class)
- )
- );
- $tagged = iterator_to_array($app->tagged(\ApiPlatform\Laravel\Eloquent\State\LinksHandlerInterface::class));
- return new \ApiPlatform\Laravel\Eloquent\State\CollectionProvider(
- $app->make(\ApiPlatform\State\Pagination\Pagination::class),
- $linksHandler,
- $app->tagged(\ApiPlatform\Laravel\Eloquent\State\QueryExtensionInterface::class),
- new \ApiPlatform\Laravel\ServiceLocator($tagged)
- );
- }
- );
- }
- /**
- * Check if the package is running as a vendor package.
- */
- protected function isRunningAsVendorPackage(): bool
- {
- return str_contains(__DIR__, 'vendor');
- }
- }
|