src/Bidcoz/Bundle/FrontendBundle/Controller/Auction/ItemController.php line 42

Open in your IDE?
  1. <?php
  2. namespace Bidcoz\Bundle\FrontendBundle\Controller\Auction;
  3. use Bidcoz\Bundle\CoreBundle\Controller\CoreController;
  4. use Bidcoz\Bundle\CoreBundle\Entity\Auction\Auction;
  5. use Bidcoz\Bundle\CoreBundle\Entity\Auction\FundANeed;
  6. use Bidcoz\Bundle\CoreBundle\Entity\Auction\Item;
  7. use Bidcoz\Bundle\CoreBundle\Entity\Auction\ItemRepository;
  8. use Bidcoz\Bundle\CoreBundle\Entity\Auction\Shop;
  9. use Bidcoz\Bundle\CoreBundle\Entity\Campaign;
  10. use Bidcoz\Bundle\CoreBundle\Entity\Organization;
  11. use Bidcoz\Bundle\CoreBundle\Entity\Proxy\ItemPurchaseProxy;
  12. use Bidcoz\Bundle\FrontendBundle\Form\Type\ItemBidType;
  13. use Bidcoz\Bundle\FrontendBundle\Form\Type\ItemBuyType;
  14. use Bidcoz\Bundle\FrontendBundle\Form\Type\ItemDonationType;
  15. use Sensio\Bundle\FrameworkExtraBundle\Configuration\Cache;
  16. use Sensio\Bundle\FrameworkExtraBundle\Configuration\Entity;
  17. use Sensio\Bundle\FrameworkExtraBundle\Configuration\IsGranted;
  18. use Symfony\Component\HttpFoundation\Request;
  19. use Symfony\Component\Routing\Annotation\Route;
  20. /**
  21.  * @Route("/{orgSlug}/{campaignSlug}")
  22.  *
  23.  * @IsGranted("VIEW", subject="organization")
  24.  * @IsGranted("FRONT_END", subject="campaign")
  25.  */
  26. class ItemController extends CoreController
  27. {
  28.     use ItemCatalogQueryTrait;
  29.     /**
  30.      * @Route("/auction/item/{itemId}", name="auction_item", methods={"GET"})
  31.      *
  32.      * @Cache(maxage="0", smaxage="0", expires="now", public="false")
  33.      *
  34.      * @Entity("item", class="Bidcoz\Bundle\CoreBundle\Entity\Auction\Item", options={"id" = "itemId"}, expr="repository.findHydrated(itemId)")
  35.      *
  36.      * @IsGranted("VIEW", subject="item")
  37.      */
  38.     public function viewAuctionItemAction(Request $requestOrganization $organizationCampaign $campaignAuction $auctionItem $item)
  39.     {
  40.         return $this->viewItem($request$organization$campaign$auction$item);
  41.     }
  42.     /**
  43.      * @Route("/shop/item/{itemId}", name="shop_item", methods={"GET"})
  44.      *
  45.      * @Cache(maxage="0", smaxage="0", expires="now", public="false")
  46.      *
  47.      * @Entity("item", class="Bidcoz\Bundle\CoreBundle\Entity\Auction\Item", options={"id" = "itemId"}, expr="repository.findHydrated(itemId)")
  48.      *
  49.      * @IsGranted("VIEW", subject="item")
  50.      */
  51.     public function viewShopItemAction(Request $requestOrganization $organizationCampaign $campaignShop $shopItem $item)
  52.     {
  53.         return $this->viewItem($request$organization$campaign$shop$item);
  54.     }
  55.     /**
  56.      * @Route("/fund-a-need/item/{itemId}", name="fund_a_need_item", methods={"GET"})
  57.      *
  58.      * @Cache(maxage="0", smaxage="0", expires="now", public="false")
  59.      *
  60.      * @Entity("item", class="Bidcoz\Bundle\CoreBundle\Entity\Auction\Item", options={"id" = "itemId"}, expr="repository.findHydrated(itemId)")
  61.      *
  62.      * @IsGranted("VIEW", subject="item")
  63.      */
  64.     public function viewFundANeedItemAction(Request $requestOrganization $organizationCampaign $campaign, ?FundANeed $fundANeedItem $item)
  65.     {
  66.         if (!$fundANeed) {
  67.             throw $this->createNotFoundException('Fund-a-Need not found');
  68.         }
  69.         return $this->viewItem($request$organization$campaign$fundANeed$item);
  70.     }
  71.     /**
  72.      * Lightweight JSON bid status for the item detail page's live poll
  73.      * (auction-item-poll.js). Returns the re-rendered read-only bid-status
  74.      * fragment plus flags so the client can detect a bid change and adapt.
  75.      *
  76.      * @Route("/auction/item/{itemId}/status", name="auction_item_status", methods={"GET"})
  77.      *
  78.      * @Entity("item", class="Bidcoz\Bundle\CoreBundle\Entity\Auction\Item", options={"id" = "itemId"}, expr="repository.findHydrated(itemId)")
  79.      *
  80.      * @IsGranted("VIEW", subject="item")
  81.      */
  82.     public function itemStatusAction(Request $requestOrganization $organizationCampaign $campaignItem $item)
  83.     {
  84.         $user       $this->getUser();
  85.         $biddable   $this->isItemBiddable($item);
  86.         $winningBid $item->getWinningBid();
  87.         $isWinning  $user && $winningBid && $winningBid->getUser() === $user;
  88.         $isOutbid   $user && !$isWinning && $item->hasUserBid($user);
  89.         $bidCount   $item->getActiveBids()->count();
  90.         $html $this->renderView('@BidcozFrontend/Auction/_item_bid_status.html.twig', [
  91.             'item'     => $item,
  92.             'biddable' => $biddable,
  93.         ]);
  94.         // Signature of the state the heavy fragments depend on: the winning bid and
  95.         // the bid count. The client echoes back the signature it last rendered
  96.         // (?signature=); when it matches, skip re-rendering _bid_activity and
  97.         // _outbid_note. The client only consumes those fragments on a real change
  98.         // (see auction-item-poll.js), so near auction close — polling every 1–3s
  99.         // per viewer while the DB is under bid-write load — a hot item no longer
  100.         // does hundreds of full activity-table renders/min that are discarded.
  101.         $signature = ($winningBid $winningBid->getId() : 0) . ':' $bidCount;
  102.         $activityHtml   null;
  103.         $outbidNoteHtml null;
  104.         if ($request->query->get('signature') !== $signature) {
  105.             // Re-rendered bidding activity so the poll can refresh the table live.
  106.             $activityHtml $this->renderView('@BidcozFrontend/Auction/_bid_activity.html.twig', [
  107.                 'item'     => $item,
  108.                 'campaign' => $campaign,
  109.             ]);
  110.             // Re-rendered outbid notice so the poll can update its visibility AND wording
  111.             // (regular vs auto-bidder) + next-increment amount live, without a page reload.
  112.             $outbidNoteHtml $this->renderView('@BidcozFrontend/Auction/_outbid_note.html.twig', [
  113.                 'item' => $item,
  114.             ]);
  115.         }
  116.         return $this->json([
  117.             'html'          => $html,
  118.             'activityHtml'  => $activityHtml,
  119.             'outbidNoteHtml' => $outbidNoteHtml,
  120.             'signature'    => $signature,
  121.             'currentBid'   => $winningBid $winningBid->getAmount() : $item->getMinBid(),
  122.             'bidCount'     => $bidCount,
  123.             'biddable'     => $biddable,
  124.             'isWinning'    => (bool) $isWinning,
  125.             'isOutbid'     => (bool) $isOutbid,
  126.             // True when the user is outbid AND the current winner is an auto-bid proxy raise.
  127.             'outbidByAuto' => (bool) ($isOutbid && $winningBid && $winningBid->isAutoBid()),
  128.         ]);
  129.     }
  130.     private function viewItem(Request $requestOrganization $organizationCampaign $campaignAuction $auctionItem $item)
  131.     {
  132.         [$proxy$bidForm$buyForm$donationForm$showBidForm$showBuyForm$showDonationForm] = $this->getItemVars($item);
  133.         $internalUsers null;
  134.         if ($auction instanceof Shop) {
  135.             $type          'shop';
  136.             $internalUsers $this->getRepository('InternalUser')->findByOrganization($organization);
  137.         } elseif ($auction instanceof FundANeed) {
  138.             $type 'fund-a-need';
  139.         } else {
  140.             $type 'auction';
  141.         }
  142.         // Dedicated carousel query (CAU-242). Replaces a paginated call to the
  143.         // shared getAuctionQueryBuilder(): pagination is meaningless for a fixed
  144.         // strip and leaked ?page from the URL into it, and the shared builder was
  145.         // being called with $groupBy = false, which cost the strip a card per
  146.         // item that had more than one purchase row.
  147.         //
  148.         // CAU-356: the strip now mirrors the catalog the donor came from. The
  149.         // catalog's sort and filters arrive as query parameters on the link they
  150.         // followed (see ItemCatalogQueryTrait::getCatalogCarryParams) and are
  151.         // applied to the same builder the catalog uses.
  152.         $repository $this->getRepository('Auction\Item');
  153.         $filterForm $this->getItemFilterForm($auction);
  154.         $orderForm  $this->getItemOrderForm();
  155.         // Only the auction catalog drops fixed-price items when sorting by bid
  156.         // count; shop and Fund-a-Need catalogs never have. Mirror whichever
  157.         // catalog this item actually belongs to, so the strip matches the page
  158.         // the donor left.
  159.         $excludeFixedPriceOnBidCountSort Auction::class === get_class($auction);
  160.         $filteredQb $repository->getCarouselQueryBuilder($auction);
  161.         $this->applyFilters($request$filterForm$filteredQb);
  162.         $this->applyOrder($request$orderForm$filteredQb$excludeFixedPriceOnBidCountSort);
  163.         $this->applyTabFilter($request$filteredQb);
  164.         $auctionItems $repository->sliceCarouselItems($filteredQb$item);
  165.         // Fallback (CAU-356): filters that leave too few items to fill the strip
  166.         // are dropped, but the sort is kept. A near-empty carousel is worse than
  167.         // a wider one — the donor came here to find something else to look at.
  168.         if (count($auctionItems) < ItemRepository::CAROUSEL_MIN_ITEMS) {
  169.             $sortedQb $repository->getCarouselQueryBuilder($auction);
  170.             // A fresh order form: a Symfony form can only be submitted once, and
  171.             // applyOrder() swallows the resulting exception, which would silently
  172.             // cost us the sort we are trying to preserve.
  173.             $this->applyOrder($request$this->getItemOrderForm(), $sortedQb$excludeFixedPriceOnBidCountSort);
  174.             $auctionItems $repository->sliceCarouselItems($sortedQb$item);
  175.         }
  176.         $params = [
  177.             'organization'      => $organization,
  178.             'campaign'          => $campaign,
  179.             'auction'           => $auction,
  180.             'item'              => $item,
  181.             'bidForm'           => $bidForm->createView(),
  182.             'buyForm'           => $buyForm->createView(),
  183.             'donationForm'      => $donationForm->createView(),
  184.             'showBidForm'       => $showBidForm,
  185.             'showBuyForm'       => $showBuyForm,
  186.             'showDonationForm'  => $showDonationForm,
  187.             'requireCC'         => !$this->isGranted('WITH_CC'$campaign),
  188.             'type'              => $type,
  189.             'auctionItems'      => $auctionItems,
  190.             'internalUsers'     => $internalUsers,
  191.             // Passed straight through to the carousel's cards so the sort/filter
  192.             // context survives item → item → item, not just catalog → item.
  193.             'carryParams'       => $this->getCatalogCarryParams($request$filterForm$orderForm),
  194.         ];
  195.         return $this->render('@BidcozFrontend/Auction/item.html.twig'$params);
  196.     }
  197.     /**
  198.      * @Route("/auction/item/{itemId}/bid", name="item_bid")
  199.      *
  200.      * @Entity("item", class="Bidcoz\Bundle\CoreBundle\Entity\Auction\Item", options={"id" = "itemId"}, expr="repository.findHydrated(itemId)")
  201.      *
  202.      * @IsGranted("VIEW", subject="item")
  203.      */
  204.     public function bidItemAction(Request $requestOrganization $organizationCampaign $campaignAuction $auctionItem $item)
  205.     {
  206.         $user $this->getUser();
  207.         if (!$user) {
  208.             $this->messageAccessDeniedException('You must login or create an account to place a bid');
  209.         }
  210.         if ('POST' !== $request->getMethod() || !$this->isItemBiddable($item)) {
  211.             return $this->redirectToRoute('auction_item', [
  212.                 'orgSlug'      => $organization->getSlug(),
  213.                 'campaignSlug' => $campaign->getSlug(),
  214.                 'itemId'       => $item->getId(),
  215.             ]);
  216.         }
  217.         [$proxy$bidForm$buyForm$donationForm$showBidForm$showBuyForm$showDonationForm] = $this->getItemVars($item);
  218.         if (!$this->isGranted('WITH_CC'$campaign)) {
  219.             $params = [
  220.                 'organization'      => $organization,
  221.                 'campaign'          => $campaign,
  222.                 'auction'           => $auction,
  223.                 'item'              => $item,
  224.                 'bidForm'           => $bidForm->createView(),
  225.                 'buyForm'           => $buyForm->createView(),
  226.                 'donationForm'      => $donationForm->createView(),
  227.                 'showBidForm'       => $showBidForm,
  228.                 'showBuyForm'       => $showBuyForm,
  229.                 'showDonationForm'  => $showDonationForm,
  230.                 'ccRequiredWarning' => true,
  231.                 'requireCC'         => true,
  232.                 'type'              => 'auction',
  233.             ];
  234.             return $this->render('@BidcozFrontend/Auction/item.html.twig'$params);
  235.         }
  236.         $bidForm->handleRequest($request);
  237.         if ($bidForm->isValid()) {
  238.             try {
  239.                 $this->getBidManager()->createBid($user$proxy);
  240.                 $this->getEntityManager()->flush();
  241.             } catch (\Exception $e) {
  242.                 $this->addFlash('danger'$e->getMessage());
  243.             }
  244.             return $this->redirectToRoute('auction_item', [
  245.                 'orgSlug'      => $organization->getSlug(),
  246.                 'campaignSlug' => $campaign->getSlug(),
  247.                 'itemId'       => $item->getId(),
  248.             ]);
  249.         } else {
  250.             $this->addFlash('warning''There was an error placing your bid, please try again');
  251.         }
  252.         $params = [
  253.             'organization'     => $organization,
  254.             'campaign'         => $campaign,
  255.             'auction'          => $auction,
  256.             'item'             => $item,
  257.             'bidForm'          => $bidForm->createView(),
  258.             'buyForm'          => $buyForm->createView(),
  259.             'donationForm'     => $donationForm->createView(),
  260.             'showBidForm'      => $showBidForm,
  261.             'showBuyForm'      => $showBuyForm,
  262.             'showDonationForm' => $showDonationForm,
  263.             'requireCC'        => false,
  264.             'type'             => 'auction',
  265.         ];
  266.         return $this->render('@BidcozFrontend/Auction/item.html.twig'$params);
  267.     }
  268.     /**
  269.      * @Route("/auction/item/{itemId}/buy", name="auction_item_buy")
  270.      *
  271.      * @Entity("item", class="Bidcoz\Bundle\CoreBundle\Entity\Auction\Item", options={"id" = "itemId"}, expr="repository.findHydrated(itemId)")
  272.      *
  273.      * @IsGranted("VIEW", subject="item")
  274.      */
  275.     public function buyAuctionItemAction(Request $requestOrganization $organizationCampaign $campaignAuction $auctionItem $item)
  276.     {
  277.         return $this->buyItem($request$organization$campaign$auction$item);
  278.     }
  279.     /**
  280.      * @Route("/shop/item/{itemId}/buy", name="shop_item_buy")
  281.      * @Route("/shop/item/{itemId}/donation", name="shop_item_donation")
  282.      *
  283.      * @Entity("item", class="Bidcoz\Bundle\CoreBundle\Entity\Auction\Item", options={"id" = "itemId"}, expr="repository.findHydrated(itemId)")
  284.      *
  285.      * @IsGranted("VIEW", subject="item")
  286.      */
  287.     public function buyShopItemAction(Request $requestOrganization $organizationCampaign $campaignShop $shopItem $item)
  288.     {
  289.         return $this->buyItem($request$organization$campaign$shop$item);
  290.     }
  291.     /**
  292.      * @Route("/fund-a-need/item/{itemId}/buy", name="fund_a_need_item_buy")
  293.      * @Route("/fund-a-need/item/{itemId}/donation", name="fund_a_need_item_donation")
  294.      *
  295.      * @Entity("item", class="Bidcoz\Bundle\CoreBundle\Entity\Auction\Item", options={"id" = "itemId"}, expr="repository.findHydrated(itemId)")
  296.      *
  297.      * @IsGranted("VIEW", subject="item")
  298.      */
  299.     public function buyFundANeedItemAction(Request $requestOrganization $organizationCampaign $campaign, ?FundANeed $fundANeedItem $item)
  300.     {
  301.         if (!$fundANeed) {
  302.             throw $this->createNotFoundException('Fund-a-Need not found');
  303.         }
  304.         return $this->buyItem($request$organization$campaign$fundANeed$item);
  305.     }
  306.     private function buyItem(Request $requestOrganization $organizationCampaign $campaignAuction $auctionItem $item)
  307.     {
  308.         $user $this->getUser();
  309.         if (!$user) {
  310.             $this->messageAccessDeniedException('You must login or create an account to purchase an item');
  311.         }
  312.         if ('POST' !== $request->getMethod() || !($this->isItemBuyitNow($item) || $this->isItemDonation($item))) {
  313.             return $this->redirectToRoute('auction_item', [
  314.                 'orgSlug'      => $organization->getSlug(),
  315.                 'campaignSlug' => $campaign->getSlug(),
  316.                 'itemId'       => $item->getId(),
  317.             ]);
  318.         }
  319.         [$proxy$bidForm$buyForm$donationForm$showBidForm$showBuyForm$showDonationForm] = $this->getItemVars($item);
  320.         if ($auction instanceof Shop) {
  321.             $type 'shop';
  322.         } elseif ($auction instanceof FundANeed) {
  323.             $type 'fund-a-need';
  324.         } else {
  325.             $type 'auction';
  326.         }
  327.         if (!$this->isGranted('WITH_CC'$campaign)) {
  328.             $params = [
  329.                 'organization'      => $organization,
  330.                 'campaign'          => $campaign,
  331.                 'auction'           => $auction,
  332.                 'item'              => $item,
  333.                 'bidForm'           => $bidForm->createView(),
  334.                 'buyForm'           => $buyForm->createView(),
  335.                 'donationForm'      => $donationForm->createView(),
  336.                 'showBidForm'       => $showBidForm,
  337.                 'showBuyForm'       => $showBuyForm,
  338.                 'showDonationForm'  => $showDonationForm,
  339.                 'ccRequiredWarning' => true,
  340.                 'requireCC'         => true,
  341.                 'type'              => $type,
  342.             ];
  343.             return $this->render('@BidcozFrontend/Auction/item.html.twig'$params);
  344.         }
  345.         if ($showBuyForm) {
  346.             $buyForm->handleRequest($request);
  347.             if ($buyForm->isValid()) {
  348.                 try {
  349.                     $holdInCart $campaign->getHoldItemsInCart();
  350.                     $expirationDate $holdInCart
  351.                         null
  352.                         : new \DateTime('+15 minutes');
  353.                     $this->getPurchaseManager()->createBuyItNowItemPurchase($user$proxy$campaign->getHoldItemsInCart(), $expirationDate);
  354.                     if ('auction' == $type) {
  355.                         $this->getWatchListManager()->createWatchListItem($user$proxy->getItem());
  356.                     }
  357.                     $this->getEntityManager()->flush();
  358.                 } catch (\Exception $e) {
  359.                     $this->addFlash('warning'$e->getMessage());
  360.                 }
  361.                 return $this->redirectToRoute('account_campaign_purchases', [
  362.                     'orgSlug'      => $organization->getSlug(),
  363.                     'campaignSlug' => $campaign->getSlug(),
  364.                 ]);
  365.             } else {
  366.                 $this->addFlash('warning''There was an error purchasing this item, please try again');
  367.             }
  368.         } elseif ($showDonationForm) {
  369.             $donationForm->handleRequest($request);
  370.             if ($donationForm->isValid()) {
  371.                 try {
  372.                     $this->getPurchaseManager()->createDonationItemPurchase($user$proxy);
  373.                     $this->getEntityManager()->flush();
  374.                 } catch (\Exception $e) {
  375.                     $this->addFlash('warning'$e->getMessage());
  376.                 }
  377.                 return $this->redirectToRoute('account_campaign_purchases', [
  378.                     'orgSlug'      => $organization->getSlug(),
  379.                     'campaignSlug' => $campaign->getSlug(),
  380.                 ]);
  381.             } else {
  382.                 $this->addFlash('warning''There was an error making this purchase, please try again');
  383.             }
  384.         }
  385.         $params = [
  386.             'organization'     => $organization,
  387.             'campaign'         => $campaign,
  388.             'auction'          => $auction,
  389.             'item'             => $item,
  390.             'bidForm'          => $bidForm->createView(),
  391.             'buyForm'          => $buyForm->createView(),
  392.             'donationForm'     => $donationForm->createView(),
  393.             'showBidForm'      => $showBidForm,
  394.             'showBuyForm'      => $showBuyForm,
  395.             'showDonationForm' => $showDonationForm,
  396.             'requireCC'        => false,
  397.             'type'             => $auction instanceof Shop 'shop' 'auction',
  398.         ];
  399.         return $this->render('@BidcozFrontend/Auction/item.html.twig'$params);
  400.     }
  401.     /**
  402.      * @Route("/auction/item/{itemId}/max-bid", name="item_max_bid")
  403.      *
  404.      * @Entity("item", class="Bidcoz\Bundle\CoreBundle\Entity\Auction\Item", options={"id" = "itemId"}, expr="repository.findHydrated(itemId)")
  405.      *
  406.      * @IsGranted("VIEW", subject="item")
  407.      */
  408.     public function updateMaxBidAction(Request $requestOrganization $organizationCampaign $campaignAuction $auctionItem $item)
  409.     {
  410.         $user $this->getUser();
  411.         if (!$user) {
  412.             $this->messageAccessDeniedException('You must login or create an account to place a bid');
  413.         }
  414.         if ('POST' !== $request->getMethod() || !$this->isItemBiddable($item)) {
  415.             return $this->redirectToRoute('auction_item', [
  416.                 'orgSlug'      => $organization->getSlug(),
  417.                 'campaignSlug' => $campaign->getSlug(),
  418.                 'itemId'       => $item->getId(),
  419.             ]);
  420.         }
  421.         if (!$this->isGranted('WITH_CC'$campaign)) {
  422.             [$proxy$bidForm$buyForm$donationForm$showBidForm$showBuyForm$showDonationForm] = $this->getItemVars($item);
  423.             $params = [
  424.                 'organization'      => $organization,
  425.                 'campaign'          => $campaign,
  426.                 'auction'           => $auction,
  427.                 'item'              => $item,
  428.                 'bidForm'           => $bidForm->createView(),
  429.                 'buyForm'           => $buyForm->createView(),
  430.                 'donationForm'      => $donationForm->createView(),
  431.                 'showBidForm'       => $showBidForm,
  432.                 'showBuyForm'       => $showBuyForm,
  433.                 'showDonationForm'  => $showDonationForm,
  434.                 'ccRequiredWarning' => true,
  435.                 'requireCC'         => true,
  436.                 'type'              => 'auction',
  437.             ];
  438.             return $this->render('@BidcozFrontend/Auction/item.html.twig'$params);
  439.         }
  440.         try {
  441.             $amount    $request->request->get('amount'0);
  442.             $cancelBid = (bool) $request->request->get('_cancel'false);
  443.             $this->getBidManager()->setMaxBid($user$item$amount$cancelBid);
  444.             $this->getEntityManager()->flush();
  445.         } catch (\Exception $e) {
  446.             $this->addFlash('warning'$e->getMessage());
  447.         }
  448.         return $this->redirectToRoute('auction_item', [
  449.             'orgSlug'      => $organization->getSlug(),
  450.             'campaignSlug' => $campaign->getSlug(),
  451.             'itemId'       => $item->getId(),
  452.         ]);
  453.     }
  454.     protected function isItemBiddable(Item $item)
  455.     {
  456.         return $this->getItemManager()->isItemBiddable($item);
  457.     }
  458.     protected function isItemBuyitNow(Item $item)
  459.     {
  460.         return $this->getItemManager()->isItemBuyitNow($item);
  461.     }
  462.     protected function isItemDonation(Item $item)
  463.     {
  464.         return $this->getItemManager()->isItemDonation($item);
  465.     }
  466.     protected function createItemPurchaseProxy(Item $item)
  467.     {
  468.         return new ItemPurchaseProxy($item);
  469.     }
  470.     protected function getBidForm(ItemPurchaseProxy $proxy)
  471.     {
  472.         $item $proxy->getItem();
  473.         if ($item->isAuctionType()) {
  474.             $itemMinimumBid $this->getBidManager()->getItemMinimumBid($item);
  475.             $proxy->setAmount($itemMinimumBid);
  476.         }
  477.         $form $this->createForm(ItemBidType::class, $proxy);
  478.         return $form;
  479.     }
  480.     protected function getBuyForm(ItemPurchaseProxy $proxy)
  481.     {
  482.         $item $proxy->getItem();
  483.         $form $this->createForm(ItemBuyType::class, $proxy, [
  484.             'item' => $item,
  485.         ]);
  486.         if ($item->isFixedPrice()) {
  487.             $form->get('quantity')->setData(1);
  488.         }
  489.         return $form;
  490.     }
  491.     protected function getDonationForm(ItemPurchaseProxy $proxy)
  492.     {
  493.         $item $proxy->getItem();
  494.         return $this->createForm(ItemDonationType::class, $proxy, [
  495.             'item' => $item,
  496.         ]);
  497.     }
  498.     protected function getItemVars(Item $item)
  499.     {
  500.         $proxy            $this->createItemPurchaseProxy($item);
  501.         $bidForm          $this->getBidForm($proxy);
  502.         $buyForm          $this->getBuyForm($proxy);
  503.         $donationForm     $this->getDonationForm($proxy);
  504.         $showBidForm      $this->getItemManager()->isItemBiddable($item);
  505.         $showBuyForm      $this->getItemManager()->isItemBuyitNow($item);
  506.         $showDonationForm $this->getItemManager()->isItemDonation($item);
  507.         return [$proxy$bidForm$buyForm$donationForm$showBidForm$showBuyForm$showDonationForm];
  508.     }
  509. }