Skip to content

Commit

Permalink
Inject the AbstractCriterion from CalendArt
Browse files Browse the repository at this point in the history
  • Loading branch information
Taluu committed Mar 10, 2015
1 parent c1cc453 commit 7ed02ad
Show file tree
Hide file tree
Showing 8 changed files with 386 additions and 5 deletions.
204 changes: 204 additions & 0 deletions src/AbstractCriterion.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,204 @@
<?php
/**
* This file is part of the CalendArt package
*
* For the full copyright and license information, please view the LICENSE file
* that was distributed with this source code.
*
* @copyright Wisembly
* @license http://www.opensource.org/licenses/MIT-License MIT License
*/

namespace CalendArt\Adapter\Google;

use CalendArt\Adapter\Google\Exception\CriterionNotFoundException;

use ArrayIterator,
IteratorAggregate,

InvalidArgumentException;

/**
* Represents a criterion for a query. Can be recursive
*
* @author Baptiste Clavié <baptiste@wisembly.com>
*/
abstract class AbstractCriterion implements IteratorAggregate
{
protected $name;

/** @var self[] Collection of criteria if it is a recursive criterion */
protected $criteria = [];

public function __construct($name, array $criteria = [])
{
$this->name = $name;

array_walk($criteria, function (self $criterion) {
$this->addCriterion($criterion);
});
}

public final function __clone()
{
$criteria = [];

foreach ($this->criteria as $criterion) {
$criteria[$criterion->getName()] = clone $criterion;
}

$this->criteria = $criteria;
}

/**
* Get the criterion's name
*
* @return string Criterion's name
*/
public function getName()
{
return $this->name;
}

/**
* Add a subcriterion
*
* @param self $criterion criterion to add
* @return $this
*/
public function addCriterion(self $criterion)
{
$this->criteria[$criterion->getName()] = $criterion;

return $this;
}

/**
* Get a specific subcriterion
*
* @param string $name Name of the criterion to find. If it is already a Criterion, its name will be used
*
* @return static The found criterion
* @throws CriterionNotFoundException if the criterion is not found
*/
public function getCriterion($name)
{
if ($name instanceof self) {
$name = $name->getName();
}

if (!isset($this->criteria[$name])) {
throw new CriterionNotFoundException(array_keys($this->criteria), $name);
}

return $this->criteria[$name];
}

/**
* Delete a criterion from the criteria stack
*
* @param string|self $name Name of the criterion to delete
*
* @return $this
* @throws CriterionNotFoundException If the criterion is not found
*/
protected function deleteCriterion($name)
{
if ($name instanceof self) {
$name = $name->getName();
}

if (!isset($this->criteria[$name])) {
throw new CriterionNotFoundException(array_keys($this->criteria), $name);
}

unset($this->criteria[$name]);

return $this;
}

/**
* Checks if this criterion is a recursive criterion
*
* @return boolean true if it is a recursive criterion, false otherwise
*/
public function isRecursive()
{
return !empty($this->criteria);
}

/** {@inheritDoc} */
public function getIterator()
{
return new ArrayIterator($this->criteria);
}

/**
* Merge two criterion together
*
* @return static
*/
public function merge(self $criterion)
{
if (!$criterion instanceof static) {
throw new InvalidArgumentException(sprintf('Can\'t merge two different collections. Expected a child of `%s`, got `%s`', __CLASS__, get_class($criterion)));
}

if ($this->getName() !== $criterion->getName()) {
throw new InvalidArgumentException(sprintf('Can\'t merge two different criteria. Had `%s` and `%s`', $this->getName(), $criterion->getName()));
}

// none of them are actually recursive... let's return a clone of this current object
if (!$this->isRecursive() && !$criterion->isRecursive()) {
return clone $this;
}

// is the current collection less specific than the merged collection ? Return the current collection
if (!$this->isRecursive() && $criterion->isRecursive()) {
return clone $this;
}

// is the collection to be merged less specific than the current collection ? Return the collection to be merged
if ($this->isRecursive() && !$criterion->isRecursive()) {
return clone $criterion;
}

$merge = clone $this;

/*
* Here is where the fun begins...
*
* The idea is, at this point, this criterion and the one that we want to
* merge are both recursive.
*
* The part where it is becoming funny (or cranky, it depends on the
* point of view...) is if the current criterion already has one of the
* sub-criteria. If that is the case, then we'll need to merge the
* sub-criterion of the criterion we want to merge ; if it is not within
* our current criterion, then we just need to add its clone.
*
* That's a lot of criteria in the same text, I know.
*/
foreach ($criterion->criteria as $subCriterion) {
try {
$tmp = $merge->getCriterion($subCriterion);

$merge->deleteCriterion($tmp);
$merge->addCriterion($tmp->merge($subCriterion));
} catch (CriterionNotFoundException $e) {
$merge->addCriterion(clone $subCriterion);
}
}

return $merge;

}

/**
* Build the criterion to be understandable by the adapter
*
* @return mixed Built query
*/
abstract public function build();
}

2 changes: 1 addition & 1 deletion src/CalendarApi.php
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@
use CalendArt\Adapter\Google\Calendar,
CalendArt\Adapter\Google\Exception\ApiErrorException,

CalendArt\Adapter\AbstractCriterion,
CalendArt\Adapter\Google\AbstractCriterion,
CalendArt\Adapter\Google\Criterion\Field,
CalendArt\Adapter\Google\Criterion\Collection,

Expand Down
2 changes: 1 addition & 1 deletion src/Criterion/Collection.php
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@

namespace CalendArt\Adapter\Google\Criterion;

use CalendArt\Adapter\AbstractCriterion,
use CalendArt\Adapter\Google\AbstractCriterion,

CalendArt\Adapter\Google\Criterion\Collection\Element,
CalendArt\Adapter\Google\Criterion\Collection\Reducible,
Expand Down
2 changes: 1 addition & 1 deletion src/Criterion/Field.php
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@

namespace CalendArt\Adapter\Google\Criterion;

use CalendArt\Adapter\AbstractCriterion;
use CalendArt\Adapter\Google\AbstractCriterion;

/**
* Represents a Field criterion
Expand Down
2 changes: 1 addition & 1 deletion src/EventApi.php
Original file line number Diff line number Diff line change
Expand Up @@ -18,13 +18,13 @@
use Doctrine\Common\Collections\ArrayCollection;

use CalendArt\Adapter\EventApiInterface,
CalendArt\Adapter\AbstractCriterion,
CalendArt\AbstractEvent as CalendArtAbstractEvent,
CalendArt\Adapter\Exception\CriterionNotFoundException,

CalendArt\Adapter\Google\Event\BasicEvent,
CalendArt\Adapter\Google\Exception\ApiErrorException,

CalendArt\Adapter\Google\AbstractCriterion,
CalendArt\Adapter\Google\Criterion\Field,
CalendArt\Adapter\Google\Criterion\Collection;

Expand Down
47 changes: 47 additions & 0 deletions src/Exception/CriterionNotFoundException.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
<?php
/**
* This file is part of the CalendArt package
*
* For the full copyright and license information, please view the LICENSE file
* that was distributed with this source code.
*
* @copyright Wisembly
* @license http://www.opensource.org/licenses/MIT-License MIT License
*/

namespace CalendArt\Adapter\Google\Exception;

use RuntimeException;

/**
* Used when a criterion is not found within another criterion
*
* @author Baptiste Clavié <baptiste@wisembly.com>
*/
class CriterionNotFoundException extends RuntimeException
{
/** @var string[] list of available criterions */
private $available;

/** @var string Name of the not found criterion */
private $name;

public function __construct(array $list, $name)
{
$this->name = $name;
$this->available = $list;

parent::__construct(sprintf('The criterion `%s` was not found. Available criterions are the following : [`%s`]', $name, implode('`, `', $list)), 404);
}

public function getName()
{
return $this->name;
}

public function getAvailableCriterions()
{
return $this->available;
}
}

Loading

0 comments on commit 7ed02ad

Please sign in to comment.