BagistoApiServiceProvider.php 45 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967
  1. <?php
  2. namespace Webkul\BagistoApi\Providers;
  3. use ApiPlatform\GraphQl\Resolver\Factory\ResolverFactoryInterface;
  4. use ApiPlatform\GraphQl\Resolver\QueryCollectionResolverInterface;
  5. use ApiPlatform\GraphQl\Resolver\QueryItemResolverInterface;
  6. use ApiPlatform\GraphQl\Type\Definition\IterableType;
  7. use ApiPlatform\Laravel\Eloquent\State\PersistProcessor;
  8. use ApiPlatform\Metadata\IdentifiersExtractorInterface;
  9. use ApiPlatform\Metadata\IriConverterInterface;
  10. use ApiPlatform\OpenApi\Factory\OpenApiFactoryInterface;
  11. use ApiPlatform\State\Pagination\Pagination;
  12. use ApiPlatform\State\ProcessorInterface;
  13. use ApiPlatform\State\ProviderInterface;
  14. use Illuminate\Support\ServiceProvider;
  15. use Webkul\BagistoApi\Console\Commands\GenerateStorefrontKey;
  16. use Webkul\BagistoApi\Facades\CartTokenFacade;
  17. use Webkul\BagistoApi\Http\Controllers\AdminGraphQLPlaygroundController;
  18. use Webkul\BagistoApi\Http\Controllers\GraphQLPlaygroundController;
  19. use Webkul\BagistoApi\Http\Middleware\VerifyStorefrontKey;
  20. use Webkul\BagistoApi\Metadata\CustomIdentifiersExtractor;
  21. use Webkul\BagistoApi\OpenApi\SplitOpenApiFactory;
  22. use Webkul\BagistoApi\Repositories\GuestCartTokensRepository;
  23. use Webkul\BagistoApi\Resolver\BaseQueryItemResolver;
  24. use Webkul\BagistoApi\Resolver\CategoryCollectionResolver;
  25. use Webkul\BagistoApi\Resolver\CustomerQueryResolver;
  26. use Webkul\BagistoApi\Resolver\Factory\ProductRelationResolverFactory;
  27. use Webkul\BagistoApi\Resolver\ProductCollectionResolver;
  28. use Webkul\BagistoApi\Resolver\SingleProductBagistoApiResolver;
  29. use Webkul\BagistoApi\Resolver\PageByUrlKeyResolver;
  30. use Webkul\BagistoApi\Routing\CustomIriConverter;
  31. use Webkul\BagistoApi\Serializer\TokenHeaderDenormalizer;
  32. use Webkul\BagistoApi\Services\CartTokenService;
  33. use Webkul\BagistoApi\Services\PaymentService;
  34. use Webkul\BagistoApi\Services\StorefrontKeyService;
  35. use Webkul\BagistoApi\Services\TokenHeaderService;
  36. use Webkul\BagistoApi\State\PaymentCallbackProcessor;
  37. use Webkul\BagistoApi\State\PaymentInitiateProcessor;
  38. use Webkul\BagistoApi\State\PaymentReplayProcessor;
  39. use Webkul\BagistoApi\State\SaveCheckoutCartProcessor;
  40. use Webkul\BagistoApi\State\BookingSlotProvider;
  41. use Webkul\BagistoApi\State\PageProvider;
  42. use Webkul\BagistoApi\State\AttributeCollectionProvider;
  43. use Webkul\BagistoApi\State\AttributeOptionCollectionProvider;
  44. use Webkul\BagistoApi\State\AttributeOptionQueryProvider;
  45. use Webkul\BagistoApi\State\RepayOrderPaymentMethodsProvider;
  46. use Webkul\BagistoApi\State\AttributeValueProcessor;
  47. use Webkul\BagistoApi\State\AuthenticatedCustomerProvider;
  48. use Webkul\BagistoApi\State\BundleOptionProductsProvider;
  49. use Webkul\BagistoApi\State\CartTokenMutationProvider;
  50. use Webkul\BagistoApi\State\CartTokenProcessor;
  51. use Webkul\BagistoApi\State\CategoryTreeProvider;
  52. use Webkul\BagistoApi\State\ChannelProvider;
  53. use Webkul\BagistoApi\State\CheckoutAddressProvider;
  54. use Webkul\BagistoApi\State\CheckoutProcessor;
  55. use Webkul\BagistoApi\State\CompareItemProcessor;
  56. use Webkul\BagistoApi\State\CountryStateCollectionProvider;
  57. use Webkul\BagistoApi\State\CountryStateQueryProvider;
  58. use Webkul\BagistoApi\State\CustomerAddressProvider;
  59. use Webkul\BagistoApi\State\CustomerAddressTokenProcessor;
  60. use Webkul\BagistoApi\State\CustomerProcessor;
  61. use Webkul\BagistoApi\State\CustomerProfileProcessor;
  62. use Webkul\BagistoApi\State\DefaultChannelProvider;
  63. use Webkul\BagistoApi\State\DownloadableLinksProvider;
  64. use Webkul\BagistoApi\State\DownloadableProductProcessor;
  65. use Webkul\BagistoApi\State\DownloadableSamplesProvider;
  66. use Webkul\BagistoApi\State\FilterableAttributesProvider;
  67. use Webkul\BagistoApi\State\ForgotPasswordProcessor;
  68. use Webkul\BagistoApi\State\GetCheckoutAddressCollectionProvider;
  69. use Webkul\BagistoApi\State\GroupedProductsProvider;
  70. use Webkul\BagistoApi\State\LoginProcessor;
  71. use Webkul\BagistoApi\State\LogoutProcessor;
  72. use Webkul\BagistoApi\State\PaymentMethodsProvider;
  73. use Webkul\BagistoApi\State\Processor\NewsletterSubscriptionProcessor;
  74. use Webkul\BagistoApi\State\Processor\ContactUsProcessor;
  75. use Webkul\BagistoApi\State\ProductBagistoApiProvider;
  76. use Webkul\BagistoApi\State\ProductGraphQLProvider;
  77. use Webkul\BagistoApi\State\ProductCustomerGroupPriceProcessor;
  78. use Webkul\BagistoApi\State\ProductCustomerGroupPriceProvider;
  79. use Webkul\BagistoApi\State\ProductDetailProvider;
  80. use Webkul\BagistoApi\State\ProductProcessor;
  81. use Webkul\BagistoApi\State\ProductRelationProvider;
  82. use Webkul\BagistoApi\State\ProductRestProvider;
  83. use Webkul\BagistoApi\State\ProductReviewProcessor;
  84. use Webkul\BagistoApi\State\ProductReviewProvider;
  85. use Webkul\BagistoApi\State\ShippingRatesProvider;
  86. use Webkul\BagistoApi\State\VerifyTokenProcessor;
  87. use Webkul\BagistoApi\State\CompareItemProvider;
  88. use Webkul\BagistoApi\State\CustomerDownloadableProductProvider;
  89. use Webkul\BagistoApi\State\CustomerInvoiceProvider;
  90. use Webkul\BagistoApi\State\CustomerOrderProvider;
  91. use Webkul\BagistoApi\State\CustomerOrderShipmentItemProvider;
  92. use Webkul\BagistoApi\State\CustomerOrderShipmentProvider;
  93. use Webkul\BagistoApi\State\CustomerReviewProvider;
  94. use Webkul\BagistoApi\State\WishlistItemProvider;
  95. use Webkul\BagistoApi\State\WishlistProcessor;
  96. use Webkul\BagistoApi\State\WishlistProvider;
  97. use Webkul\BagistoApi\State\MoveWishlistToCartProcessor;
  98. use Webkul\BagistoApi\State\DeleteAllWishlistsProcessor;
  99. use Webkul\BagistoApi\State\CancelOrderProcessor;
  100. use Webkul\BagistoApi\State\ReorderProcessor;
  101. use Webkul\BagistoApi\State\DeleteAllCompareItemsProcessor;
  102. use Longyi\ImageUpload\Services\ImageUploadService;
  103. use ApiPlatform\GraphQl\Serializer\SerializerContextBuilder as GraphQlSerializerContextBuilder;
  104. use Symfony\Component\Serializer\NameConverter\NameConverterInterface;
  105. use Webkul\BagistoApi\GraphQl\Serializer\FixedSerializerContextBuilder;
  106. use Webkul\BagistoApi\State\ProductImageProvider;
  107. class BagistoApiServiceProvider extends ServiceProvider
  108. {
  109. /**
  110. * Register the service provider bindings.
  111. */
  112. public function register(): void
  113. {
  114. $this->mergeConfigFrom(__DIR__.'/../../config/bagistoapi.php', 'bagistoapi');
  115. // Force the API-aware response-cache profile. Spatie's default profile caches
  116. // every successful GET and hashes by path only, so paginated API responses
  117. // (?page=2, ?itemsPerPage=5) collapse onto one cache entry.
  118. config(['responsecache.cache_profile' => \Webkul\BagistoApi\CacheProfiles\ApiAwareResponseCache::class]);
  119. $this->app->singleton(IterableType::class);
  120. $this->app->tag(IterableType::class, 'api_platform.graphql.type');
  121. // $this->overrideApiPlatformLinksHandler();
  122. $this->registerSnakeCaseLinksHandlerFix();
  123. $this->app->singleton(ProductImageProvider::class, function ($app) {
  124. return new ProductImageProvider(
  125. $app->make(Pagination::class)
  126. );
  127. });
  128. $this->app->singleton(StorefrontKeyService::class, function ($app) {
  129. return new StorefrontKeyService;
  130. });
  131. $this->ensureCorsExposedHeaders(['X-Total-Count', 'X-Page', 'X-Per-Page', 'X-Total-Pages']);
  132. $this->app->extend(OpenApiFactoryInterface::class, function ($openApiFactory) {
  133. return new SplitOpenApiFactory($openApiFactory);
  134. });
  135. $this->app->singleton(TokenHeaderDenormalizer::class);
  136. $this->forcePersistentMetadataCache();
  137. $this->app->singleton('token-header-service', function ($app) {
  138. return new TokenHeaderService;
  139. });
  140. $this->app->alias('token-header-service', 'Webkul\BagistoApi\Services\TokenHeaderService');
  141. $this->app->singleton('cart-token-service', function ($app) {
  142. return new CartTokenService(
  143. $app->make('Webkul\Checkout\Repositories\CartRepository'),
  144. $app->make('Webkul\BagistoApi\Repositories\GuestCartTokensRepository'),
  145. $app->make('Webkul\Customer\Repositories\CustomerRepository')
  146. );
  147. });
  148. $this->app->alias('cart-token-service', CartTokenFacade::class);
  149. $this->app->singleton('Webkul\BagistoApi\Repositories\GuestCartTokensRepository', function ($app) {
  150. return new GuestCartTokensRepository($app);
  151. });
  152. $this->app->tag(ProductProcessor::class, ProcessorInterface::class);
  153. $this->app->tag(AttributeValueProcessor::class, ProcessorInterface::class);
  154. $this->app->tag(ProductCustomerGroupPriceProcessor::class, ProcessorInterface::class);
  155. $this->app->tag(CustomerProcessor::class, ProcessorInterface::class);
  156. $this->app->tag(LoginProcessor::class, ProcessorInterface::class);
  157. $this->app->tag(VerifyTokenProcessor::class, ProcessorInterface::class);
  158. $this->app->tag(LogoutProcessor::class, ProcessorInterface::class);
  159. $this->app->tag(ForgotPasswordProcessor::class, ProcessorInterface::class);
  160. $this->app->tag(CustomerProfileProcessor::class, ProcessorInterface::class);
  161. $this->app->tag(CustomerAddressTokenProcessor::class, ProcessorInterface::class);
  162. $this->app->tag(CartTokenProcessor::class, ProcessorInterface::class);
  163. $this->app->tag(CheckoutProcessor::class, ProcessorInterface::class);
  164. $this->app->tag(PaymentInitiateProcessor::class, ProcessorInterface::class);
  165. $this->app->tag(PaymentCallbackProcessor::class, ProcessorInterface::class);
  166. $this->app->tag(PaymentReplayProcessor::class, ProcessorInterface::class);
  167. $this->app->tag(ProductReviewProcessor::class, ProcessorInterface::class);
  168. $this->app->tag(CompareItemProcessor::class, ProcessorInterface::class);
  169. $this->app->tag(DownloadableProductProcessor::class, ProcessorInterface::class);
  170. $this->app->tag(NewsletterSubscriptionProcessor::class, ProcessorInterface::class);
  171. $this->app->tag(WishlistProcessor::class, ProcessorInterface::class);
  172. $this->app->tag(\Webkul\BagistoApi\State\GdprRequestProcessor::class, ProcessorInterface::class);
  173. $this->app->tag(MoveWishlistToCartProcessor::class, ProcessorInterface::class);
  174. $this->app->tag(DeleteAllWishlistsProcessor::class, ProcessorInterface::class);
  175. $this->app->tag(DeleteAllCompareItemsProcessor::class, ProcessorInterface::class);
  176. $this->app->tag(CancelOrderProcessor::class, ProcessorInterface::class);
  177. $this->app->tag(ReorderProcessor::class, ProcessorInterface::class);
  178. $this->app->tag(ContactUsProcessor::class, ProcessorInterface::class);
  179. $this->app->tag(SaveCheckoutCartProcessor::class, ProcessorInterface::class);
  180. $this->app->tag(TokenHeaderDenormalizer::class, 'serializer.normalizer');
  181. $this->app->extend('api_platform_normalizer_list', function (\SplPriorityQueue $list, $app) {
  182. $list->insert(
  183. $app->make(\Webkul\BagistoApi\Serializer\PaginationHeaderNormalizer::class),
  184. 1000
  185. );
  186. return $list;
  187. });
  188. $this->app->singleton(ProductCustomerGroupPriceProcessor::class, function ($app) {
  189. return new ProductCustomerGroupPriceProcessor(
  190. $app->make(PersistProcessor::class)
  191. );
  192. });
  193. $this->app->singleton(CustomerProcessor::class, function ($app) {
  194. return new CustomerProcessor(
  195. $app->make('Webkul\Customer\Repositories\CustomerRepository'),
  196. $app->make('Webkul\BagistoApi\Validators\CustomerValidator')
  197. );
  198. });
  199. $this->app->singleton(LoginProcessor::class, function ($app) {
  200. return new LoginProcessor(
  201. $app->make('Webkul\BagistoApi\Validators\LoginValidator')
  202. );
  203. });
  204. $this->app->singleton(CustomerProfileProcessor::class, function ($app) {
  205. return new CustomerProfileProcessor(
  206. $app->make('Webkul\BagistoApi\Validators\CustomerValidator')
  207. );
  208. });
  209. $this->app->singleton(CartTokenProcessor::class, function ($app) {
  210. return new CartTokenProcessor(
  211. $app->make('Webkul\Checkout\Repositories\CartRepository'),
  212. $app->make('Webkul\BagistoApi\Repositories\GuestCartTokensRepository')
  213. );
  214. });
  215. $this->app->singleton(PaymentService::class, function ($app) {
  216. return new PaymentService(
  217. $app->make('Webkul\Sales\Repositories\OrderRepository'),
  218. $app->make('Webkul\Checkout\Repositories\CartRepository'),
  219. $app->make('cart-token-service'),
  220. $app->make('Webkul\Sales\Repositories\InvoiceRepository'),
  221. $app->make('Webkul\Sales\Repositories\OrderTransactionRepository'),
  222. $app->make('Webkul\BagistoApi\Repositories\PaymentAttemptRepository'),
  223. );
  224. });
  225. $this->app->singleton(SaveCheckoutCartProcessor::class, function ($app) {
  226. return new SaveCheckoutCartProcessor(
  227. $app->make('Webkul\CartRule\Repositories\CartRuleCouponRepository'),
  228. );
  229. });
  230. $this->app->singleton(CheckoutProcessor::class, function ($app) {
  231. return new CheckoutProcessor(
  232. $app->make('Webkul\Customer\Repositories\CustomerRepository'),
  233. $app->make('Webkul\Sales\Repositories\OrderRepository'),
  234. $app->make('Webkul\Checkout\Repositories\CartRepository'),
  235. $app->make(PaymentService::class),
  236. );
  237. });
  238. $this->app->singleton(PaymentInitiateProcessor::class, function ($app) {
  239. return new PaymentInitiateProcessor(
  240. $app->make(PaymentService::class),
  241. );
  242. });
  243. $this->app->singleton(PaymentCallbackProcessor::class, function ($app) {
  244. return new PaymentCallbackProcessor(
  245. $app->make(PaymentService::class),
  246. );
  247. });
  248. $this->app->singleton(PaymentReplayProcessor::class, function ($app) {
  249. return new PaymentReplayProcessor(
  250. $app->make(PaymentService::class),
  251. );
  252. });
  253. $this->app->singleton(ProductReviewProcessor::class, function ($app) {
  254. return new ProductReviewProcessor(
  255. $app->make(PersistProcessor::class),
  256. $app->make(ImageUploadService::class)
  257. );
  258. });
  259. $this->app->singleton(CompareItemProcessor::class, function ($app) {
  260. return new CompareItemProcessor(
  261. $app->make(PersistProcessor::class)
  262. );
  263. });
  264. $this->app->singleton(WishlistProcessor::class, function ($app) {
  265. return new WishlistProcessor(
  266. $app->make(PersistProcessor::class)
  267. );
  268. });
  269. $this->app->singleton(MoveWishlistToCartProcessor::class, function ($app) {
  270. return new MoveWishlistToCartProcessor(
  271. $app->make(PersistProcessor::class)
  272. );
  273. });
  274. $this->app->singleton(DeleteAllWishlistsProcessor::class, function ($app) {
  275. return new DeleteAllWishlistsProcessor(
  276. $app->make(PersistProcessor::class)
  277. );
  278. });
  279. $this->app->singleton(DeleteAllCompareItemsProcessor::class, function ($app) {
  280. return new DeleteAllCompareItemsProcessor(
  281. $app->make(PersistProcessor::class)
  282. );
  283. });
  284. $this->app->singleton(CancelOrderProcessor::class, function ($app) {
  285. return new CancelOrderProcessor(
  286. $app->make(PersistProcessor::class),
  287. $app->make('Webkul\Sales\Repositories\OrderRepository'),
  288. $app->make(PaymentService::class),
  289. );
  290. });
  291. $this->app->singleton(ReorderProcessor::class, function ($app) {
  292. return new ReorderProcessor(
  293. $app->make(PersistProcessor::class)
  294. );
  295. });
  296. $this->app->singleton(LogoutProcessor::class, function ($app) {
  297. return new LogoutProcessor();
  298. });
  299. $this->app->tag(CheckoutAddressProvider::class, ProviderInterface::class);
  300. $this->app->tag(CustomerAddressProvider::class, ProviderInterface::class);
  301. $this->app->tag(GetCheckoutAddressCollectionProvider::class, ProviderInterface::class);
  302. $this->app->tag(PaymentMethodsProvider::class, ProviderInterface::class);
  303. $this->app->tag(RepayOrderPaymentMethodsProvider::class, ProviderInterface::class);
  304. $this->app->tag(ShippingRatesProvider::class, ProviderInterface::class);
  305. $this->app->tag(AuthenticatedCustomerProvider::class, ProviderInterface::class);
  306. $this->app->tag(\Webkul\BagistoApi\State\CustomerProfileCollectionProvider::class, ProviderInterface::class);
  307. $this->app->tag(CartTokenMutationProvider::class, ProviderInterface::class);
  308. $this->app->tag(ChannelProvider::class, ProviderInterface::class);
  309. $this->app->tag(DefaultChannelProvider::class, ProviderInterface::class);
  310. $this->app->tag(ProductBagistoApiProvider::class, ProviderInterface::class);
  311. $this->app->tag(ProductGraphQLProvider::class, ProviderInterface::class);
  312. $this->app->tag(ProductRestProvider::class, ProviderInterface::class);
  313. $this->app->tag(ProductDetailProvider::class, ProviderInterface::class);
  314. $this->app->tag(ProductImageProvider::class, ProviderInterface::class);
  315. $this->app->tag(ProductCustomerGroupPriceProvider::class, ProviderInterface::class);
  316. $this->app->tag(ProductRelationProvider::class, ProviderInterface::class);
  317. $this->app->tag(BundleOptionProductsProvider::class, ProviderInterface::class);
  318. $this->app->tag(GroupedProductsProvider::class, ProviderInterface::class);
  319. $this->app->tag(DownloadableLinksProvider::class, ProviderInterface::class);
  320. $this->app->tag(DownloadableSamplesProvider::class, ProviderInterface::class);
  321. $this->app->tag(ProductReviewProvider::class, ProviderInterface::class);
  322. $this->app->tag(FilterableAttributesProvider::class, ProviderInterface::class);
  323. $this->app->tag(AttributeCollectionProvider::class, ProviderInterface::class);
  324. $this->app->tag(AttributeOptionCollectionProvider::class, ProviderInterface::class);
  325. $this->app->tag(AttributeOptionQueryProvider::class, ProviderInterface::class);
  326. $this->app->tag(CountryStateCollectionProvider::class, ProviderInterface::class);
  327. $this->app->tag(CountryStateQueryProvider::class, ProviderInterface::class);
  328. $this->app->tag(CategoryTreeProvider::class, ProviderInterface::class);
  329. $this->app->tag(\Webkul\BagistoApi\State\CategoryRestProvider::class, ProviderInterface::class);
  330. $this->app->tag(BookingSlotProvider::class, ProviderInterface::class);
  331. $this->app->tag(\Webkul\BagistoApi\State\BookingProductDetailProvider::class, ProviderInterface::class);
  332. $this->app->tag(PageProvider::class, ProviderInterface::class);
  333. $this->app->tag(\Webkul\BagistoApi\State\CursorAwareCollectionProvider::class, ProviderInterface::class);
  334. $this->app->tag(WishlistProvider::class, ProviderInterface::class);
  335. $this->app->tag(WishlistItemProvider::class, ProviderInterface::class);
  336. $this->app->tag(\Webkul\BagistoApi\State\GdprRequestProvider::class, ProviderInterface::class);
  337. $this->app->tag(\Webkul\BagistoApi\State\GdprRequestItemProvider::class, ProviderInterface::class);
  338. $this->app->tag(CompareItemProvider::class, ProviderInterface::class);
  339. $this->app->tag(CustomerReviewProvider::class, ProviderInterface::class);
  340. $this->app->tag(CustomerOrderProvider::class, ProviderInterface::class);
  341. $this->app->tag(CustomerDownloadableProductProvider::class, ProviderInterface::class);
  342. $this->app->tag(CustomerInvoiceProvider::class, ProviderInterface::class);
  343. $this->app->tag(CustomerOrderShipmentProvider::class, ProviderInterface::class);
  344. $this->app->tag(CustomerOrderShipmentItemProvider::class, ProviderInterface::class);
  345. $this->app->singleton(GetCheckoutAddressCollectionProvider::class, function ($app) {
  346. return new GetCheckoutAddressCollectionProvider(
  347. $app->make('ApiPlatform\State\Pagination\Pagination')
  348. );
  349. });
  350. $this->app->singleton(WishlistProvider::class, function ($app) {
  351. return new WishlistProvider(
  352. $app->make(Pagination::class)
  353. );
  354. });
  355. $this->app->singleton(\Webkul\BagistoApi\State\GdprRequestProvider::class, function ($app) {
  356. return new \Webkul\BagistoApi\State\GdprRequestProvider(
  357. $app->make(Pagination::class)
  358. );
  359. });
  360. $this->app->singleton(CompareItemProvider::class, function ($app) {
  361. return new CompareItemProvider(
  362. $app->make(Pagination::class)
  363. );
  364. });
  365. $this->app->singleton(CustomerReviewProvider::class, function ($app) {
  366. return new CustomerReviewProvider(
  367. $app->make(Pagination::class)
  368. );
  369. });
  370. $this->app->singleton(CustomerOrderProvider::class, function ($app) {
  371. return new CustomerOrderProvider(
  372. $app->make(Pagination::class)
  373. );
  374. });
  375. $this->app->singleton(CustomerDownloadableProductProvider::class, function ($app) {
  376. return new CustomerDownloadableProductProvider(
  377. $app->make(Pagination::class)
  378. );
  379. });
  380. $this->app->singleton(CustomerInvoiceProvider::class, function ($app) {
  381. return new CustomerInvoiceProvider(
  382. $app->make(Pagination::class)
  383. );
  384. });
  385. $this->app->singleton(CustomerOrderShipmentProvider::class, function ($app) {
  386. return new CustomerOrderShipmentProvider(
  387. $app->make(Pagination::class)
  388. );
  389. });
  390. $this->app->singleton(CustomerOrderShipmentItemProvider::class, function ($app) {
  391. return new CustomerOrderShipmentItemProvider(
  392. $app->make(Pagination::class)
  393. );
  394. });
  395. $this->app->singleton(CustomerAddressProvider::class, function ($app) {
  396. return new CustomerAddressProvider(
  397. $app->make(Pagination::class)
  398. );
  399. });
  400. $this->app->singleton(ProductBagistoApiProvider::class, function ($app) {
  401. return new ProductBagistoApiProvider(
  402. $app->make(Pagination::class)
  403. );
  404. });
  405. $this->app->singleton(ProductGraphQLProvider::class, function ($app) {
  406. return new ProductGraphQLProvider(
  407. $app->make(Pagination::class),
  408. $app->make(\Webkul\Product\Repositories\ElasticSearchRepository::class)
  409. );
  410. });
  411. $this->app->singleton(\Webkul\BagistoApi\State\ProductRelationFlagResolver::class);
  412. $this->app->singleton(ProductRelationProvider::class, function ($app) {
  413. return new ProductRelationProvider(
  414. $app->make(Pagination::class)
  415. );
  416. });
  417. $this->app->singleton(ProductReviewProvider::class, function ($app) {
  418. return new ProductReviewProvider(
  419. $app->make(Pagination::class)
  420. );
  421. });
  422. $this->app->singleton(GroupedProductsProvider::class, function ($app) {
  423. return new GroupedProductsProvider(
  424. $app->make(Pagination::class)
  425. );
  426. });
  427. $this->app->singleton(DownloadableLinksProvider::class, function ($app) {
  428. return new DownloadableLinksProvider(
  429. $app->make(Pagination::class)
  430. );
  431. });
  432. $this->app->singleton(DownloadableSamplesProvider::class, function ($app) {
  433. return new DownloadableSamplesProvider(
  434. $app->make(Pagination::class)
  435. );
  436. });
  437. $this->app->singleton(FilterableAttributesProvider::class, function ($app) {
  438. return new FilterableAttributesProvider(
  439. $app->make(\ApiPlatform\State\Pagination\Pagination::class)
  440. );
  441. });
  442. $this->app->singleton(AttributeCollectionProvider::class, function ($app) {
  443. return new AttributeCollectionProvider(
  444. $app->make(Pagination::class)
  445. );
  446. });
  447. $this->app->singleton(AttributeOptionCollectionProvider::class, function ($app) {
  448. return new AttributeOptionCollectionProvider(
  449. $app->make(Pagination::class)
  450. );
  451. });
  452. $this->app->singleton(CountryStateCollectionProvider::class, function ($app) {
  453. return new CountryStateCollectionProvider(
  454. $app->make(Pagination::class)
  455. );
  456. });
  457. $this->app->singleton(ProductCollectionResolver::class);
  458. $this->app->tag(SingleProductBagistoApiResolver::class, QueryItemResolverInterface::class);
  459. $this->app->tag(CategoryCollectionResolver::class, QueryCollectionResolverInterface::class);
  460. $this->app->tag(BaseQueryItemResolver::class, QueryItemResolverInterface::class);
  461. $this->app->tag(\Webkul\BagistoApi\Resolver\WishlistQueryResolver::class, QueryItemResolverInterface::class);
  462. $this->app->tag(\Webkul\BagistoApi\Resolver\GdprRequestQueryResolver::class, QueryItemResolverInterface::class);
  463. $this->app->tag(CustomerQueryResolver::class, QueryItemResolverInterface::class);
  464. $this->app->tag(PageByUrlKeyResolver::class, QueryCollectionResolverInterface::class);
  465. $this->app->extend(ResolverFactoryInterface::class, function ($resolverFactory, $app) {
  466. return new ProductRelationResolverFactory(
  467. $resolverFactory,
  468. $app->make(ProductRelationProvider::class)
  469. );
  470. });
  471. $this->app->extend(IdentifiersExtractorInterface::class, function ($extractor) {
  472. return new CustomIdentifiersExtractor($extractor);
  473. });
  474. $this->app->extend(IriConverterInterface::class, function ($converter, $app) {
  475. return new CustomIriConverter(
  476. $converter,
  477. $app->make(\ApiPlatform\Metadata\Resource\Factory\ResourceMetadataCollectionFactoryInterface::class)
  478. );
  479. });
  480. $this->app->extend(GraphQlSerializerContextBuilder::class, function ($builder, $app) {
  481. return new FixedSerializerContextBuilder(
  482. $builder,
  483. $app->make(NameConverterInterface::class)
  484. );
  485. });
  486. }
  487. /**
  488. * Replace ApiPlatform's default CollectionProvider/ItemProvider so that
  489. * sub-collection relations (GraphQL) use our CamelCaseAwareLinksHandler.
  490. *
  491. * ApiPlatform's own LinksHandler compares GraphQL camelCase fieldnames
  492. * (e.g. "flexibleVariants") with snake_case Link::fromProperty (e.g.
  493. * "flexible_variants"); the mismatch causes sub-collection queries to
  494. * skip the parent-id WHERE clause and return every row in the child
  495. * table. Our handler normalizes both sides before comparing and
  496. * re-resolves the relation by method name.
  497. */
  498. /**
  499. * Replace ApiPlatform's CollectionProvider/ItemProvider so the inner
  500. * LinksHandler is our camelCase-aware variant.
  501. *
  502. * ApiPlatform ships its bindings via ApiPlatformDeferredProvider (a
  503. * DeferrableProvider whose register() only runs when the binding is
  504. * first resolved — i.e. after every other ServiceProvider::register()).
  505. * We use Container::extend() so our decorator runs *after* ApiPlatform
  506. * has built the original singleton. extend() also remembers our closure
  507. * for bindings that don't exist yet, so registration order is safe.
  508. *
  509. * The provider's $linksHandler is a readonly promoted property and
  510. * therefore cannot be replaced via Reflection on PHP 8.1+. Instead we
  511. * rebuild the singleton with the same dependencies.
  512. */
  513. protected function overrideApiPlatformLinksHandler(): void
  514. {
  515. $buildHandler = fn ($app) => new \Webkul\BagistoApi\State\CamelCaseAwareLinksHandler(
  516. $app,
  517. $app->make(\ApiPlatform\Metadata\Resource\Factory\ResourceMetadataCollectionFactoryInterface::class)
  518. );
  519. $this->app->extend(
  520. \ApiPlatform\Laravel\Eloquent\State\CollectionProvider::class,
  521. function ($original, $app) use ($buildHandler) {
  522. if (! $original instanceof \ApiPlatform\Laravel\Eloquent\State\CollectionProvider) {
  523. return $original;
  524. }
  525. $ref = new \ReflectionObject($original);
  526. $queryExtensions = $this->readPrivate($ref, $original, 'queryExtensions');
  527. $handleLinksLoc = $this->readPrivate($ref, $original, 'handleLinksLocator');
  528. return new \ApiPlatform\Laravel\Eloquent\State\CollectionProvider(
  529. $app->make(\ApiPlatform\State\Pagination\Pagination::class),
  530. $buildHandler($app),
  531. $queryExtensions ?? [],
  532. $handleLinksLoc
  533. );
  534. }
  535. );
  536. $this->app->extend(
  537. \ApiPlatform\Laravel\Eloquent\State\ItemProvider::class,
  538. function ($original, $app) use ($buildHandler) {
  539. if (! $original instanceof \ApiPlatform\Laravel\Eloquent\State\ItemProvider) {
  540. return $original;
  541. }
  542. $ref = new \ReflectionObject($original);
  543. $handleLinksLoc = $this->readPrivate($ref, $original, 'handleLinksLocator');
  544. $queryExtensions = $this->readPrivate($ref, $original, 'queryExtensions');
  545. return new \ApiPlatform\Laravel\Eloquent\State\ItemProvider(
  546. $buildHandler($app),
  547. $handleLinksLoc,
  548. $queryExtensions ?? []
  549. );
  550. }
  551. );
  552. }
  553. private function readPrivate(\ReflectionObject $ref, object $instance, string $propertyName): mixed
  554. {
  555. if (! $ref->hasProperty($propertyName)) {
  556. return null;
  557. }
  558. $prop = $ref->getProperty($propertyName);
  559. $prop->setAccessible(true);
  560. return $prop->getValue($instance);
  561. }
  562. /**
  563. * Keep API Platform's resource-metadata caches on a PERSISTENT store even when
  564. * APP_DEBUG=true.
  565. *
  566. * api-platform/laravel's ApiPlatformProvider::register() (≈ lines 271-323) binds
  567. * PropertyMetadataFactoryInterface and PropertyNameCollectionFactoryInterface with the
  568. * cache store hardcoded to 'array' whenever app.debug is true. The 'array' store is
  569. * in-memory and dropped after each request, so the OpenAPI doc routes (/api/shop,
  570. * /api/admin) rebuild metadata for every resource on every hit and exceed PHP's
  571. * max_execution_time (>30s). Real single-resource endpoints are unaffected.
  572. *
  573. * We re-bind both factories identically to vendor but force the configured persistent
  574. * store (api-platform.cache, default 'file') regardless of app.debug — restoring the
  575. * 2.3.8 behaviour where debug mode did not disable metadata caching. The package's
  576. * NullableToOnePropertyMetadataFactory extender (registered above) still applies on top.
  577. *
  578. * NOTE: this mirrors the vendor decorator chain. If api-platform/laravel changes the
  579. * inner factories, re-sync this method against ApiPlatformProvider::register().
  580. */
  581. protected function forcePersistentMetadataCache(): void
  582. {
  583. $store = config('api-platform.cache', 'file');
  584. $this->app->singleton(
  585. \ApiPlatform\Metadata\Property\Factory\PropertyMetadataFactoryInterface::class,
  586. function ($app) use ($store) {
  587. $nameConverter = config('api-platform.name_converter', \Symfony\Component\Serializer\NameConverter\SnakeCaseToCamelCaseNameConverter::class);
  588. if ($nameConverter && class_exists($nameConverter)) {
  589. $nameConverter = new \ApiPlatform\Laravel\Eloquent\Serializer\EloquentNameConverter($app->make($nameConverter));
  590. }
  591. return new \ApiPlatform\Laravel\Metadata\CachePropertyMetadataFactory(
  592. new \ApiPlatform\JsonSchema\Metadata\Property\Factory\SchemaPropertyMetadataFactory(
  593. $app->make(\ApiPlatform\Metadata\ResourceClassResolverInterface::class),
  594. new \ApiPlatform\Metadata\Property\Factory\SerializerPropertyMetadataFactory(
  595. $app->make(\ApiPlatform\Serializer\Mapping\Factory\ClassMetadataFactory::class),
  596. new \ApiPlatform\Metadata\Property\Factory\PropertyInfoPropertyMetadataFactory(
  597. $app->make(\Symfony\Component\PropertyInfo\PropertyInfoExtractorInterface::class),
  598. new \ApiPlatform\Metadata\Property\Factory\AttributePropertyMetadataFactory(
  599. new \ApiPlatform\Laravel\Eloquent\Metadata\Factory\Property\EloquentAttributePropertyMetadataFactory(
  600. new \ApiPlatform\Laravel\Eloquent\Metadata\Factory\Property\EloquentPropertyMetadataFactory(
  601. $app->make(\ApiPlatform\Laravel\Eloquent\Metadata\ModelMetadata::class),
  602. ),
  603. ),
  604. $nameConverter
  605. ),
  606. $app->make(\ApiPlatform\Metadata\ResourceClassResolverInterface::class)
  607. ),
  608. )
  609. ),
  610. $store
  611. );
  612. }
  613. );
  614. $this->app->singleton(
  615. \ApiPlatform\Metadata\Property\Factory\PropertyNameCollectionFactoryInterface::class,
  616. function ($app) use ($store) {
  617. $nameConverter = config('api-platform.name_converter', \Symfony\Component\Serializer\NameConverter\SnakeCaseToCamelCaseNameConverter::class);
  618. if ($nameConverter && class_exists($nameConverter)) {
  619. $nameConverter = new \ApiPlatform\Laravel\Eloquent\Serializer\EloquentNameConverter($app->make($nameConverter));
  620. }
  621. return new \ApiPlatform\Laravel\Metadata\CachePropertyNameCollectionMetadataFactory(
  622. new \ApiPlatform\Metadata\Property\Factory\ClassLevelAttributePropertyNameCollectionFactory(
  623. new \ApiPlatform\Metadata\Property\Factory\ConcernsPropertyNameCollectionMetadataFactory(
  624. new \ApiPlatform\Laravel\Eloquent\Metadata\Factory\Property\EloquentPropertyNameCollectionMetadataFactory(
  625. $app->make(\ApiPlatform\Laravel\Eloquent\Metadata\ModelMetadata::class),
  626. new \ApiPlatform\Metadata\Property\Factory\PropertyInfoPropertyNameCollectionFactory($app->make(\Symfony\Component\PropertyInfo\PropertyInfoExtractorInterface::class)),
  627. $app->make(\ApiPlatform\Metadata\ResourceClassResolverInterface::class)
  628. )
  629. ),
  630. $nameConverter
  631. ),
  632. $store
  633. );
  634. }
  635. );
  636. }
  637. /**
  638. * Bootstrap services.
  639. */
  640. public function boot(): void
  641. {
  642. $this->loadTranslationsFrom(__DIR__.'/../Resources/lang', 'bagistoapi');
  643. $this->loadMigrationsFrom(__DIR__.'/../Database/Migrations');
  644. $this->loadViewsFrom(__DIR__.'/../Resources/views', 'webkul');
  645. if ($this->isRunningAsVendorPackage()) {
  646. $this->publishes([
  647. __DIR__.'/../config/api-platform-vendor.php' => config_path('api-platform.php'),
  648. ], 'bagistoapi-config');
  649. } else {
  650. $this->publishes([
  651. __DIR__.'/../config/api-platform.php' => config_path('api-platform.php'),
  652. ], 'bagistoapi-config');
  653. }
  654. $this->publishes([
  655. __DIR__.'/../config/graphql-auth.php' => config_path('graphql-auth.php'),
  656. __DIR__.'/../config/storefront.php' => config_path('storefront.php'),
  657. __DIR__.'/../config/bagistoapi.php' => config_path('bagistoapi.php'),
  658. ], 'bagistoapi-config');
  659. $this->publishes([
  660. __DIR__.'/../resources/views' => resource_path('views/vendor/webkul'),
  661. ], 'bagistoapi-views');
  662. $this->publishes([
  663. __DIR__.'/../Resources/assets' => public_path('themes/admin/default/assets'),
  664. ], 'bagistoapi-assets');
  665. $this->runInstallationIfNeeded();
  666. $this->registerApiResources();
  667. $this->registerApiDocumentationRoutes();
  668. $this->registerMiddlewareAliases();
  669. $this->registerGlobalMiddleware();
  670. $this->registerServiceProviders();
  671. if ($this->app->runningInConsole()) {
  672. $this->registerCommands();
  673. }
  674. }
  675. /**
  676. * Register API documentation routes.
  677. */
  678. protected function registerApiDocumentationRoutes(): void
  679. {
  680. \Illuminate\Support\Facades\Route::get('/api', \Webkul\BagistoApi\Http\Controllers\ApiEntrypointController::class)
  681. ->name('bagistoapi.docs-index');
  682. \Illuminate\Support\Facades\Route::get('/api/shop', [
  683. \Webkul\BagistoApi\Http\Controllers\SwaggerUIController::class, 'shopApi',
  684. ])->name('bagistoapi.shop-docs')->where('_format', '^(?!json|xml|csv)');
  685. \Illuminate\Support\Facades\Route::get('/api/admin', [
  686. \Webkul\BagistoApi\Http\Controllers\SwaggerUIController::class, 'adminApi',
  687. ])->name('bagistoapi.admin-docs')->where('_format', '^(?!json|xml|csv)');
  688. \Illuminate\Support\Facades\Route::get('/api/shop/docs', [
  689. \Webkul\BagistoApi\Http\Controllers\SwaggerUIController::class, 'shopApiDocs',
  690. ])->name('bagistoapi.shop-api-spec');
  691. \Illuminate\Support\Facades\Route::get('/api/admin/docs', [
  692. \Webkul\BagistoApi\Http\Controllers\SwaggerUIController::class, 'adminApiDocs',
  693. ])->name('bagistoapi.admin-api-spec');
  694. \Illuminate\Support\Facades\Route::get('/api/graphiql', GraphQLPlaygroundController::class)
  695. ->name('bagistoapi.graphql-playground');
  696. \Illuminate\Support\Facades\Route::get('/api/graphql', GraphQLPlaygroundController::class)
  697. ->name('bagistoapi.api-graphql-playground');
  698. \Illuminate\Support\Facades\Route::get('/admin/graphiql', AdminGraphQLPlaygroundController::class)
  699. ->name('bagistoapi.admin-graphql-playground');
  700. \Illuminate\Support\Facades\Route::get('/api/shop/customer-invoices/{id}/pdf', \Webkul\BagistoApi\Http\Controllers\InvoicePdfController::class)
  701. ->where('id', '[0-9]+')
  702. ->middleware(['Webkul\BagistoApi\Http\Middleware\VerifyStorefrontKey'])
  703. ->name('bagistoapi.customer-invoice-pdf');
  704. \Illuminate\Support\Facades\Route::get('/api/downloadable/download-sample/{type}/{id}', \Webkul\BagistoApi\Http\Controllers\DownloadSampleController::class)
  705. ->where('type', 'link|sample')
  706. ->where('id', '[0-9]+')
  707. ->name('bagistoapi.download-sample');
  708. \Illuminate\Support\Facades\Route::get('/api/shop/customer-downloadable-products/{id}/download', \Webkul\BagistoApi\Http\Controllers\DownloadablePurchasedController::class)
  709. ->where('id', '[0-9]+')
  710. ->middleware(['Webkul\BagistoApi\Http\Middleware\VerifyStorefrontKey'])
  711. ->name('bagistoapi.customer-downloadable-product-download');
  712. }
  713. /**
  714. * Register API resources.
  715. */
  716. protected function registerApiResources(): void
  717. {
  718. if ($this->app->bound('api_platform.metadata_factory')) {
  719. }
  720. }
  721. /**
  722. * Run installation if needed.
  723. */
  724. protected function runInstallationIfNeeded(): void
  725. {
  726. if (file_exists(config_path('api-platform.php'))) {
  727. return;
  728. }
  729. if (! $this->app->runningInConsole() || ! $this->isComposerOperation()) {
  730. return;
  731. }
  732. try {
  733. $this->app['artisan']->call('bagisto-api-platform:install', ['--quiet' => true]);
  734. } catch (\Exception) {
  735. // Installation can be run manually if needed
  736. }
  737. }
  738. /**
  739. * Determine if running via Composer.
  740. */
  741. protected function isComposerOperation(): bool
  742. {
  743. $composerMemory = getenv('COMPOSER_MEMORY_LIMIT');
  744. $composerAuth = getenv('COMPOSER_AUTH');
  745. return ! empty($composerMemory) || ! empty($composerAuth) || defined('COMPOSER_BINARY_PATH');
  746. }
  747. /**
  748. * Register middleware aliases.
  749. */
  750. protected function registerMiddlewareAliases(): void
  751. {
  752. $this->app['router']->aliasMiddleware('storefront.key', VerifyStorefrontKey::class);
  753. $this->app['router']->aliasMiddleware('api.locale-channel', \Webkul\BagistoApi\Http\Middleware\SetLocaleChannel::class);
  754. $this->app['router']->aliasMiddleware('api.rate-limit', \Webkul\BagistoApi\Http\Middleware\RateLimitApi::class);
  755. $this->app['router']->aliasMiddleware('api.security-headers', \Webkul\BagistoApi\Http\Middleware\SecurityHeaders::class);
  756. $this->app['router']->aliasMiddleware('api.log-requests', \Webkul\BagistoApi\Http\Middleware\LogApiRequests::class);
  757. }
  758. /**
  759. * Register global middleware that runs on every HTTP request.
  760. * EnsureJsonContentType lets bodyless POST endpoints (e.g., delete-all-*)
  761. * work without clients needing to send a Content-Type header.
  762. */
  763. protected function registerGlobalMiddleware(): void
  764. {
  765. $kernel = $this->app->make(\Illuminate\Contracts\Http\Kernel::class);
  766. $kernel->prependMiddleware(\Webkul\BagistoApi\Http\Middleware\EnsureJsonContentType::class);
  767. }
  768. /**
  769. * Make our X-* pagination headers visible to JS clients via CORS without
  770. * requiring users to edit config/cors.php.
  771. */
  772. private function ensureCorsExposedHeaders(array $headers): void
  773. {
  774. $existing = config('cors.exposed_headers', []);
  775. $merged = array_values(array_unique(array_merge($existing, $headers)));
  776. if ($merged !== $existing) {
  777. config(['cors.exposed_headers' => $merged]);
  778. }
  779. }
  780. /**
  781. * Register service providers.
  782. */
  783. protected function registerServiceProviders(): void
  784. {
  785. $this->app->register(ApiPlatformExceptionHandlerServiceProvider::class);
  786. $this->app->register(DatabaseQueryLoggingProvider::class);
  787. $this->app->register(ExceptionHandlerServiceProvider::class);
  788. }
  789. /**
  790. * Register console commands.
  791. */
  792. protected function registerCommands(): void
  793. {
  794. $this->commands([
  795. \Webkul\BagistoApi\Console\Commands\InstallApiPlatformCommand::class,
  796. \Webkul\BagistoApi\Console\Commands\ClearApiPlatformCacheCommand::class,
  797. GenerateStorefrontKey::class,
  798. \Webkul\BagistoApi\Console\Commands\ApiKeyManagementCommand::class,
  799. \Webkul\BagistoApi\Console\Commands\ApiKeyMaintenanceCommand::class,
  800. ]);
  801. }
  802. /**
  803. * Override API Platform's ItemProvider and CollectionProvider to wrap the
  804. * LinksHandler with SnakeCaseLinksHandler, fixing the camelCase/snake_case
  805. * mismatch between GraphQL field names and Eloquent relationship names.
  806. */
  807. protected function registerSnakeCaseLinksHandlerFix(): void
  808. {
  809. $this->app->extend(
  810. \ApiPlatform\Laravel\Eloquent\State\ItemProvider::class,
  811. function ($original, $app) {
  812. $linksHandler = new \Webkul\BagistoApi\State\SnakeCaseLinksHandler(
  813. new \ApiPlatform\Laravel\Eloquent\State\LinksHandler(
  814. $app,
  815. $app->make(\ApiPlatform\Metadata\Resource\Factory\ResourceMetadataCollectionFactoryInterface::class)
  816. )
  817. );
  818. $tagged = iterator_to_array($app->tagged(\ApiPlatform\Laravel\Eloquent\State\LinksHandlerInterface::class));
  819. return new \ApiPlatform\Laravel\Eloquent\State\ItemProvider(
  820. $linksHandler,
  821. new \ApiPlatform\Laravel\ServiceLocator($tagged),
  822. $app->tagged(\ApiPlatform\Laravel\Eloquent\Extension\QueryExtensionInterface::class)
  823. );
  824. }
  825. );
  826. $this->app->extend(
  827. \ApiPlatform\Laravel\Eloquent\State\CollectionProvider::class,
  828. function ($original, $app) {
  829. $linksHandler = new \Webkul\BagistoApi\State\SnakeCaseLinksHandler(
  830. new \ApiPlatform\Laravel\Eloquent\State\LinksHandler(
  831. $app,
  832. $app->make(\ApiPlatform\Metadata\Resource\Factory\ResourceMetadataCollectionFactoryInterface::class)
  833. )
  834. );
  835. $tagged = iterator_to_array($app->tagged(\ApiPlatform\Laravel\Eloquent\State\LinksHandlerInterface::class));
  836. return new \ApiPlatform\Laravel\Eloquent\State\CollectionProvider(
  837. $app->make(\ApiPlatform\State\Pagination\Pagination::class),
  838. $linksHandler,
  839. $app->tagged(\ApiPlatform\Laravel\Eloquent\State\QueryExtensionInterface::class),
  840. new \ApiPlatform\Laravel\ServiceLocator($tagged)
  841. );
  842. }
  843. );
  844. }
  845. /**
  846. * Check if the package is running as a vendor package.
  847. */
  848. protected function isRunningAsVendorPackage(): bool
  849. {
  850. return str_contains(__DIR__, 'vendor');
  851. }
  852. }