Skip to content

Instantly share code, notes, and snippets.

@jjbohn
Created June 25, 2012 21:09
Show Gist options
  • Save jjbohn/2991258 to your computer and use it in GitHub Desktop.
Save jjbohn/2991258 to your computer and use it in GitHub Desktop.
<?php
namespace OpenSky\Bundle\MainBundle\Controller;
use OpenSky\Bundle\MainBundle\Document\Sellable\Sellable;
use OpenSky\Bundle\MainBundle\Document\Seller\Category;
use OpenSky\Bundle\MainBundle\Document\User;
use OpenSky\Component\Date\DateRange;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
use Symfony\Component\HttpKernel\HttpKernelInterface;
class BrowseController extends FrontendController
{
const SELLABLE_PAGE_SIZE = 24; // 24 is good for responsive design: divisible by 1,2,3,4,6,12.
const SELLER_PAGE_SIZE = 12;
const CLEARANCE_SHOP = '4f553a915c175d3e6d000043';
const COLLECTION_PAGE_SIZE = 4;
public function browseSellablesAction($slug = null, $page = 1)
{
if ($slug !== null) {
$taxon = $this->getDocumentRepository('MainBundle:Taxonomy\Taxon')->findOneBySlug($slug, true);
if ($taxon === null) {
throw new NotFoundHttpException();
}
return $this->render('MainBundle:Browse:products.html.twig', array(
'page' => $page,
'slug' => $slug,
'taxon' => $taxon,
));
}
return $this->render('MainBundle:Browse:products.html.twig', array(
'page' => $page,
'slug' => $slug,
));
}
/**
* TODO - This implementation is temporary while a new clearance implementation is being built
* @param int $page
*/
public function browseClearanceAction($page = 1)
{
return $this->render('MainBundle:Browse:products.html.twig', array(
'page' => $page,
'slug' => 'clearance',
));
}
public function browseSellersAction($slug = null, $page = 1)
{
$taxon = null;
if ($slug !== null) {
$taxon = $this->getDocumentRepository('MainBundle:Taxonomy\Taxon')->findOneBySlug($slug, true);
}
return $this->render('MainBundle:Browse:sellers.html.twig', array(
'page' => $page,
'taxon' => $taxon,
));
}
// internal
public function renderCategorySellablesAction(Request $request, $isLoggedIn = false)
{
$page = $request->get('page', 1);
$slug = $request->get('slug');
// only trust the current user on master requests
if (HttpKernelInterface::MASTER_REQUEST === $request->attributes->get('_type') && $user = $this->getLoggedInUser()) {
$isLoggedIn = true;
}
$taxon = $this->getDocumentRepository('MainBundle:Taxonomy\Taxon')->findOneBySlug($slug, true);
$categoryFlashes = $this->getDocumentRepository('MainBundle:Sellable\CategoryFlash')
->findFlashes(DateRange::getTodaysDateRange(), $taxon)
->toArray();
$this->getPrimer()->prime($categoryFlashes, 'sellable');
$categoryFlashSellables = array();
$categoryFlashSellableIds = array();
foreach ($categoryFlashes as $flash) {
$categoryFlashSellables[] = $flash->getSellable();
$categoryFlashSellableIds[] = $flash->getSellable()->getId();
}
$categoryFlashCount = count($categoryFlashSellableIds);
if ($page == 1) {
$sellableSkip = self::SELLABLE_PAGE_SIZE * ($page - 1);
$sellableLimit = self::SELLABLE_PAGE_SIZE - $categoryFlashCount;
$collectionSkip = self::COLLECTION_PAGE_SIZE * ($page - 1);
$collectionLimit = self::COLLECTION_PAGE_SIZE;
} else {
$sellableSkip = (self::SELLABLE_PAGE_SIZE * 2 * ($page - 1)) - self::SELLABLE_PAGE_SIZE - $categoryFlashCount;
$sellableLimit = self::SELLABLE_PAGE_SIZE * 2;
$collectionSkip = (self::COLLECTION_PAGE_SIZE * 2 * ($page - 1)) - self::COLLECTION_PAGE_SIZE;
$collectionLimit = self::COLLECTION_PAGE_SIZE * 2;
}
$category = $this->getDocumentRepository('MainBundle:Seller\Category')->findOneBySlug($slug, true);
$sellables = $this->getObjectsForCategory('MainBundle:Sellable\Sellable', $sellableSkip, $sellableLimit, $category);
$collections = $this->getObjectsForCategory('MainBundle:SellableCollection', $collectionSkip, $collectionLimit, $category);
$this->getPrimer()->prime($sellables, 'product');
// Filter sold out sellables, do this second so we only prime products where necessary
$inventoryManager = $this->container->get('inventory.manager');
$inventoryManager->primeSellables($sellables);
$sellables = array_filter($sellables, function(Sellable $sellable) use ($inventoryManager) {
return $inventoryManager->isInStock($sellable);
});
if ($page == 1) {
$sellables = array_merge($categoryFlashSellables, $sellables);
}
$response = $this->render('MainBundle:Browse:_category_products.html.twig', array(
'page' => $page,
'slug' => $slug,
'category' => $category,
'sellables' => $sellables,
'collections' => $collections,
'isLoggedIn' => $isLoggedIn,
));
if (HttpKernelInterface::SUB_REQUEST === $request->attributes->get('_type')) {
$response->setPublic();
$response->setExpires(new \DateTime(sprintf('%d seconds', 300 - time() % 300)));
}
return $response;
}
/**
* TODO - This implementation is temporary while a new clearance implementation is being built
*/
public function renderClearanceSellablesAction(Request $request, $isLoggedIn = false)
{
$page = $request->get('page', 1);
// only trust the current user on master requests
if (HttpKernelInterface::MASTER_REQUEST === $request->attributes->get('_type') && $user = $this->getLoggedInUser()) {
$isLoggedIn = true;
}
if ($page == 1) {
$skip = self::SELLABLE_PAGE_SIZE * ($page - 1);
$limit = self::SELLABLE_PAGE_SIZE;
} else {
$skip = (self::SELLABLE_PAGE_SIZE * 2 * ($page - 1)) - self::SELLABLE_PAGE_SIZE;
$limit = self::SELLABLE_PAGE_SIZE * 2;
}
$qb = $this->getDocumentRepository('MainBundle:Sellable\Sellable')->createActiveQueryBuilder()
->field('liveDate')->lte(new \DateTime())
->sort('lastActivityDate', 'desc')
->skip($skip)
->limit($limit)
->slaveOkay(true);
// Temporary until we finish the new clearance functionality
$qb->field('seller.$id')->equals(new \MongoId(self::CLEARANCE_SHOP));
$sellables = $qb->getQuery()->execute()->toArray();
$this->getPrimer()->prime($sellables, 'seller');
// Filter sellables for active sellers
$sellables = array_filter($sellables, function(Sellable $sellable) {
return $sellable->getSeller()->isActive();
});
$this->getPrimer()->prime($sellables, 'product');
// Filter sold out sellables, do this second so we only prime products where necessary
$inventoryManager = $this->container->get('inventory.manager');
$inventoryManager->primeSellables($sellables);
$sellables = array_filter($sellables, function(Sellable $sellable) use ($inventoryManager) {
return $inventoryManager->isInStock($sellable);
});
$response = $this->render('MainBundle:Browse:_category_products.html.twig', array(
'page' => $page,
'slug' => 'clearance',
'sellables' => $sellables,
'isLoggedIn' => $isLoggedIn,
));
if (HttpKernelInterface::SUB_REQUEST === $request->attributes->get('_type')) {
$response->setPublic();
$response->setExpires(new \DateTime(sprintf('%d seconds', 300 - time() % 300)));
}
return $response;
}
/**
* Get active Sellable or SellableCollection for a given categorySlug
*
* @return array
*/
private function getObjectsForCategory($type, $skip, $limit, Category $category = null)
{
if (!in_array($type, array('MainBundle:Sellable\Sellable', 'MainBundle:SellableCollection'))) {
throw new \RuntimeException(sprintf('Cannot handle %s', $type));
}
$qb = $this->getDocumentRepository($type)->createActiveQueryBuilder()
->sort('lastActivityDate', 'desc')
->skip($skip)
->limit($limit)
->slaveOkay(true)
;
if ($category) {
$qb->field('categories')->references($category);
} else {
$privateId = $this->container->getParameter('opensky.private_category.id');
$qb->field('categories.$id')->notEqual(new \MongoId($privateId));
}
$qb->field('liveDate')->lte(new \DateTime());
$objects = $qb->getQuery()->execute()->toArray();
return $objects;
}
public function renderCategorySellersAction(Request $request)
{
$page = $request->get('page', 1);
$slug = $request->get('slug');
// only trust the current user on master requests
if (HttpKernelInterface::MASTER_REQUEST === $request->attributes->get('_type') && $user = $this->getLoggedInUser()) {
$sellerSlugs = $user->getSellerSlugs();
} else {
$sellerSlugs = $request->get('sellerSlugs', array());
}
if ($page == 1) {
$skip = self::SELLER_PAGE_SIZE * ($page - 1);
$limit = self::SELLER_PAGE_SIZE;
} else {
$skip = (self::SELLER_PAGE_SIZE * 2 * ($page - 1)) - self::SELLER_PAGE_SIZE;
$limit = self::SELLER_PAGE_SIZE * 2;
}
$qb = $this->getDocumentRepository('MainBundle:Seller')
->createActiveQueryBuilder()
->sort('firstName', 'asc')
->skip($skip)
->limit($limit)
->slaveOkay(true)
;
if ($taxon = $this->getDocumentRepository('MainBundle:Taxonomy\Taxon')->findOneBySlug($slug, true)) {
$qb->field('taxonomy.$id')->equals(new \MongoId($taxon->getId()));
}
$sellers = $qb->getQuery()->execute()->toArray();
$this->getPrimer()->prime($sellers, 'mostRecentSellables');
$response = $this->render('MainBundle:Browse:_category_sellers.html.twig', array(
'taxon' => $taxon,
'sellers' => $sellers,
'sellerSlugs' => $sellerSlugs,
'page' => $page,
));
if (HttpKernelInterface::SUB_REQUEST === $request->attributes->get('_type')) {
$response->setPublic();
$response->setExpires(new \DateTime(sprintf('+%d seconds', 300 - time() % 300)));
}
return $response;
}
// private
/**
* @return OpenSky\Bundle\MainBundle\ODM\UnitOfWorkPrimer
*/
private function getPrimer()
{
return $this->get('odm.unitofworkprimer');
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment