ProductReviewProvider.php 2.5 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485
  1. <?php
  2. namespace Webkul\BagistoApi\State;
  3. use ApiPlatform\Laravel\Eloquent\Paginator;
  4. use ApiPlatform\Metadata\Operation;
  5. use ApiPlatform\State\Pagination\Pagination;
  6. use ApiPlatform\State\ProviderInterface;
  7. use Illuminate\Pagination\LengthAwarePaginator;
  8. use Webkul\BagistoApi\Models\ProductReview;
  9. /**
  10. * Provider for ProductReview queries
  11. * Handles filtering by product_id, status, and rating
  12. */
  13. class ProductReviewProvider implements ProviderInterface
  14. {
  15. public function __construct(
  16. private readonly Pagination $pagination
  17. ) {}
  18. public function provide(Operation $operation, array $uriVariables = [], array $context = []): object|array|null
  19. {
  20. $args = $context['args'] ?? [];
  21. $query = ProductReview::query();
  22. // Apply filters
  23. if (! empty($args['product_id'])) {
  24. $query->where('product_id', (int) $args['product_id']);
  25. }
  26. /** Default to approved reviews for storefront API */
  27. $query->where('status', isset($args['status']) ? (string) $args['status'] : 'approved');
  28. if (! empty($args['rating'])) {
  29. $query->where('rating', (int) $args['rating']);
  30. }
  31. // Eager load relationships
  32. $query->with(['product', 'customer']);
  33. // Cursor-based pagination (offset-based cursors from API Platform)
  34. $first = isset($args['first']) ? (int) $args['first'] : null;
  35. $last = isset($args['last']) ? (int) $args['last'] : null;
  36. $after = $args['after'] ?? null;
  37. $before = $args['before'] ?? null;
  38. $perPage = $first ?? $last ?? 30;
  39. $offset = 0;
  40. if ($after) {
  41. $decoded = base64_decode($after, true);
  42. $offset = ctype_digit((string) $decoded) ? ((int) $decoded + 1) : 0;
  43. }
  44. if ($before) {
  45. $decoded = base64_decode($before, true);
  46. $cursor = ctype_digit((string) $decoded) ? (int) $decoded : 0;
  47. $offset = max(0, $cursor - $perPage);
  48. }
  49. $query->orderBy('id', 'asc');
  50. $total = (clone $query)->count();
  51. if ($offset > $total) {
  52. $offset = max(0, $total - $perPage);
  53. }
  54. $items = $query
  55. ->offset($offset)
  56. ->limit($perPage)
  57. ->get();
  58. $currentPage = $total > 0 ? (int) floor($offset / $perPage) + 1 : 1;
  59. return new Paginator(
  60. new LengthAwarePaginator(
  61. $items,
  62. $total,
  63. $perPage,
  64. $currentPage,
  65. ['path' => request()->url()]
  66. )
  67. );
  68. }
  69. }