Skip to content

Instantly share code, notes, and snippets.

@K-Phoen
Last active August 29, 2015 14:15
Show Gist options
  • Save K-Phoen/5c1b06a864d063c1ee4e to your computer and use it in GitHub Desktop.
Save K-Phoen/5c1b06a864d063c1ee4e to your computer and use it in GitHub Desktop.
RulerZ, specifications and Symfony are in a boat
class SpecificationToStringTransformer implements DataTransformerInterface
{
private $specificationClass;
private $valuePath;
private $accessor;
public function __construct($specificationClass, $valuePath)
{
$this->specificationClass = $specificationClass;
$this->valuePath = $valuePath;
$this->accessor = PropertyAccess::createPropertyAccessor();
}
/**
* Transforms a specification into a string.
*
* @param \RulerZ\Spec\Specification|null $specification
*
* @return string
*/
public function transform($specification)
{
if ($specification === null) {
return '';
}
return $this->accessor->getValue($specification, $this->valuePath);
}
/**
* Transforms a string into a specification.
*
* @param string $string
*
* @return \RulerZ\Spec\Specification|null
*/
public function reverseTransform($string)
{
if (!$string) {
return null;
}
$class = $this->specificationClass;
return new $class($string);
}
}
interface CompanyRepository
{
public function save(Company $company);
public function find($slug);
public function matchingSpec(Specification $spec);
}
class DoctrineCompanyRepository extends EntityRepository implements CompanyRepository
{
// ...
public function matchingSpec(Specification $spec)
{
$qb = $this->createQueryBuilder('c');
return $this->rulerz->filterSpec($qb, $spec);
}
}
class InMemoryCompanyRepository implements CompanyRepository
{
private $companies = [];
// ...
public function matchingSpec(Specification $spec)
{
return $this->rulerz->filterSpec($this->companies, $spec);
}
}
interface CompanyRepository
{
public function save(Company $company);
public function find($slug);
public function search(array $criteria = []);
}
class DoctrineCompanyRepository extends EntityRepository implements CompanyRepository
{
// ...
public function search(array $criteria = [])
{
$qb = $this->createQueryBuilder('c');
if (!empty($criteria['name'])) {
$qb
->andWhere('c.name LIKE :name')
->setParameter('name', sprintf('%%%s%%', $criteria['name']));
}
// other criteria
return $qb->getQuery()->getResult();
}
}
class InMemoryCompanyRepository implements CompanyRepository
{
// ...
public function search(array $criteria = [])
{
$companies = $this->companies;
if (!empty($criteria['name'])) {
$companies = array_filter($companies, function($company) use ($criteria) {
return stripos(strtolower($company->getName()), strtolower($criteria['name'])) !== false;
});
}
// other criteria
return $companies;
}
}
public function searchAction(Request $request)
{
$results = [];
$form = $this->formFactory->create('company_search');
$form->handleRequest($request);
if ($form->isValid()) {
$spec = new Spec\AndX(array_merge( // aggregate specifications
array_filter($form->getData()), // remove empty fields/specs
array(new AppSpec\CompanyPublished()) // only display published companies
));
$results = $this->companyRepository->matchingSpec($spec);
}
return $this->render('...');
}
class CompanySearchType extends AbstractType
{
public function buildForm(FormBuilderInterface $builder, array $options)
{
$terms = $builder
->create('who')
->addModelTransformer(
new SpecToStringTransformer(Spec\CompanyName::class, 'terms')
);
$location = $builder
->create('where')
->addModelTransformer(
new SpecToStringTransformer(Spec\CompanyLocation::class, 'location')
);
$builder
->add($terms)
->add($location);
}
// ...
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment