Skip to content

Instantly share code, notes, and snippets.

@saksmt
Created August 27, 2014 11:08
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save saksmt/d820ad527756407c1ac1 to your computer and use it in GitHub Desktop.
Save saksmt/d820ad527756407c1ac1 to your computer and use it in GitHub Desktop.
Finds providers
<?php
namespace FS\MyOnCallDocBundle\Model\Provider;
use Buzz\Browser;
use Doctrine\ORM\Query;
use Doctrine\ORM\QueryBuilder;
use Symfony\Component\Form\Form;
use FS\UserBundle\Entity\Patient;
use Symfony\Component\Form\FormFactory;
use Knp\Component\Pager\PaginatorInterface;
use Symfony\Component\HttpFoundation\Request;
use Doctrine\Common\Persistence\ObjectManager;
use Symfony\Component\HttpFoundation\RequestStack;
use FS\MyOnCallDocBundle\Form\Type\DoctorFilterType;
use Lexik\Bundle\FormFilterBundle\Filter\FilterBuilderUpdaterInterface; // ladder of dependencies :)
/**
* Class ProviderFinder
* @package FS\MyOnCallDocBundle\Model\Provider
* Provides find actions
*/
class ProviderFinder implements ProviderFinderInterface
{
/**
* @var QueryBuilder
*/
private $builder;
/**
* @var ObjectManager
*/
private $em;
/**
* @var array
*/
private $favorites = array();
/**
* @var array
*/
private $notifications = array();
/**
* @var Request
*/
private $request;
/**
* @var array
*/
private static $doctorsPriorities;
/**
* @var FilterBuilderUpdaterInterface
*/
private $filterBuilder;
/**
* @var Form
*/
private $form;
/**
* @var FormFactory
*/
private $formFactory;
/**
* @var Browser
*/
private $browser;
/**
* @var PaginatorInterface
*/
private $paginator;
public function __construct(
ObjectManager $objectManager,
RequestStack $requestStack,
FilterBuilderUpdaterInterface $updaterInterface,
FormFactory $formFactory,
Browser $browser,
PaginatorInterface $paginator
)
{
$this->em = $objectManager;
$this->request = $requestStack->getCurrentRequest();
$this->filterBuilder = $updaterInterface;
$this->formFactory = $formFactory;
$this->browser = $browser;
$this->paginator = $paginator;
}
public function findForUser(Patient $patient)
{
$this->processForUser($patient);
return array(
'paginator' => $this->createPagination(),
'form' => $this->form->createView(),
'favourites' => $this->favorites,
'notifications' => $this->notifications,
);
}
public function processForUser(Patient $patient)
{
$this->initQueryBuilder();
$this->processUserSpecific($patient);
$this->buildRest($patient->getState());
$this->processForm();
return $this;
}
public function processForAnonymous()
{
$this->initQueryBuilder();
$this->buildRest($this->getUserState());
$this->processForm();
return $this;
}
public function getQueryBuilder()
{
return clone $this->builder;
}
public function findForAnonymous()
{
$this->processForAnonymous();
return array(
'paginator' => $this->createPagination(),
'form' => $this->form->createView(),
'favourites' => $this->favorites,
'notifications' => $this->notifications,
);
}
private function initDoctorPriorities()
{
if (!isset(self::$doctorsPriorities)) {
self::$doctorsPriorities = array(
'd.id IN (:favorites) AND c IS NOT NULL',
'd.id IN (:favorites) AND c IS NULL',
'd.id NOT IN (:favorites) AND c IS NOT NULL',
);
}
}
private function initQueryBuilder()
{
$this->builder = $this->em->getRepository('FSUserBundle:Doctor')->createQueryBuilder('d');
$this->builder
->select('d')
->leftJoin('d.certifiedStates', 'c', 'WITH', 'c.state = :state')
->andWhere('d.enabled = 1');
}
private function buildRest($patientState)
{
$orderClause = $this->buildDoctorPriorities();
$this->builder->addSelect('('.$orderClause.') AS HIDDEN DoctorOrder');
$this->builder->setParameters(array(
'favorites' => $this->favorites,
'state' => $patientState,
));
$this->setSort();
}
private function processUserSpecific(Patient $patient)
{
$favorites = $this->favorites;
$notifications = $this->notifications;
$patientFavorites = $patient->getFavourites();
foreach ($patientFavorites as $patientFavorite) {
$favorites[] = $patientFavorite->getDoctorId()->getId();
if ($patientFavorite->getNotifications()) {
$notifications[] = $patientFavorite->getDoctorId()->getId();
}
}
$this->favorites = $favorites;
$this->notifications = $notifications;
}
private function buildDoctorPriorities()
{
$this->initDoctorPriorities();
$priority = 0;
$orderClause = 'CASE ';
foreach (self::$doctorsPriorities as $doctorPriority) {
$orderClause .= 'WHEN ';
$orderClause .= $doctorPriority;
$orderClause .= ' THEN ';
$orderClause .= $priority++;
$orderClause .= ' ';
}
$orderClause .= 'ELSE '.$priority;
$orderClause .= ' END';
return $orderClause;
}
private function buildFilterForm()
{
$doctorCertifiedStates = $this->em
->getRepository('FSMyOnCallDocBundle:CertifiedState')
->getDoctorCertifiedStates();
$this->form = $this->formFactory->create(new DoctorFilterType($doctorCertifiedStates));
}
private function getUserState()
{
$apiRequest = $this->browser->get('http://freegeoip.net/json/' . $_SERVER['REMOTE_ADDR']);
$response = $apiRequest->getContent();
if ($response) {
$result = json_decode($response);
if (is_object($result) && $result->region_code != '') {
return $result->region_code;
}
}
return null;
}
private function processForm()
{
$this->buildFilterForm();
if ($this->request->query->has('submit-filter')) {
$this->form->submit($this->request);
$filterBuilder = $this->builder;
$this->builder = $this->filterBuilder->addFilterConditions($this->form, $filterBuilder);
}
}
private function setSort()
{
$this->builder
->addOrderBy('DoctorOrder')
->addOrderBy('d.rating', 'DESC')
->addOrderBy('d.lastLogin', 'DESC')
->addOrderBy('d.firstName', 'ASC')
->addOrderBy('d.lastName', 'ASC');
}
private function createPagination()
{
return $this->paginator->paginate(
$this->builder->getQuery(),
$this->request->query->get('page', 1),
10
);
}
public function getFavorites()
{
return $this->favorites;
}
public function getNotifications()
{
return $this->notifications;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment