diff --git a/Criteria.php b/Criteria.php new file mode 100644 index 0000000..486f596 --- /dev/null +++ b/Criteria.php @@ -0,0 +1,103 @@ +softDelete(); + * } + * + * @package Frogg + * @method static addSoftDelete(string $column = 'deleted', int $activeValue = 0) add soft delete criteria to the query + * @method static removeSoftDelete() removes soft delete criteria from the criteriaQueue + */ +class Criteria extends PhalconModel\Criteria +{ + private $modelCriterias = []; + + /** + * removes soft deleted entries from the result. + * + * @param string $column + * @param int $activeValue + * + * @return PhalconModel\Criteria + * @internal param $add + * + */ + public function softDeleteCriteria($column = 'deleted', $activeValue = 0) + { + return $this->andWhere($column.'='.$activeValue); + } + + /** + * alias to make more sense when calling it on query building. + * + * @return $this + */ + public function withDeleted() + { + return $this->removeSoftDelete(); + } + + public function execute() + { + $instance = $this; + foreach ($this->modelCriterias as $criteria => $value) { + $method = lcfirst($criteria).'Criteria'; + $instance = $instance->$method(...$value); + } + + return $instance->parentExecute(); + } + + public function getPhql() + { + return $this->createBuilder()->getPhql(); + } + + public function getQuery() + { + return $this->createBuilder()->getQuery(); + } + + public function getActiveCriterias() + { + return $this->modelCriterias; + } + + private function parentExecute() + { + return parent::execute(); + } + + public function __call($name, $arguments) + { + if (strpos($name, 'add') !== false) { + $criteria = str_replace('add', '', $name); + $this->modelCriterias[$criteria] = $arguments; + } else if (strpos($name, 'remove') !== false) { + $criteria = str_replace('remove', '', $name); + if (isset($this->modelCriterias[$criteria])) { + unset($this->modelCriterias[$criteria]); + } + } else { + Throw new \Exception('Method '.$name.' does not exist.'); + } + + return $this; + } +} diff --git a/Model.php b/Model.php index 3971f54..9ddac7b 100644 --- a/Model.php +++ b/Model.php @@ -3,16 +3,33 @@ namespace Frogg; use Frogg\Crypto\WT; +use Phalcon\Di; +use Phalcon\DiInterface; use Phalcon\Mvc\Model as PhalconModel; -/** - * Class Model - * @package Frogg - * - * @method static static findFirstById(int $id) +/** + * Class Model + * @package Frogg + * + * @method static static findFirstById(int $id) */ class Model extends PhalconModel { + /** + * @param DiInterface|null $dependencyInjector + * + * @return \Frogg\Criteria $criteria + */ + public static function query(DiInterface $dependencyInjector = null) + { + $class = '\\'.get_called_class().'Criteria'; + /** @var \Frogg\Criteria $criteria */ + $criteria = new $class(); + $criteria->setDI($dependencyInjector ?? Di::getDefault()); + $criteria->setModelName(get_called_class()); + + return $criteria; + } public function columnMap() { @@ -30,24 +47,14 @@ public function columnMap() return $columnMap; } - /** - * @param string $attribute Name of the attribute that will be used to create a permalink - * - * @return string A permalink formatted string - */ - public function permalinkFor(string $attribute): string + public function permalinkFor($attribute) { $tmp = new Permalink($this->$attribute); return $this->getNumeration($tmp->create()); } - /** - * @param array $values Values that will be used to create a permalink - * - * @return string A permalink formatted string - */ - public function permalinkForValues(array $values): string + public function permalinkForValues($values) { for ($i = 0; $i < count($values); $i++) { $values[$i] = Permalink::createSlug($values[$i]); @@ -57,7 +64,7 @@ public function permalinkForValues(array $values): string return $this->getNumeration($value); } - public function tokenId($key): string + public function tokenId($key) { return WT::encode(['id' => $this->id], $key); } @@ -69,7 +76,7 @@ public static function getByTokenId($token, $key) return isset($data->id) ? static::findFirstById($data->id) : false; } - private function getNumeration($slug): string + private function getNumeration($slug) { $resultset = $this->getReadConnection()->query("SELECT `permalink` FROM `".$this->getSource()."` @@ -89,3 +96,4 @@ private function getNumeration($slug): string } } + diff --git a/README.md b/README.md new file mode 100644 index 0000000..a6bc11b --- /dev/null +++ b/README.md @@ -0,0 +1,54 @@ +#### Model Criteria usage example: + +```php +class ModelCriteria extends Frogg\Criteria +{ + /** + * @return \Phalcon\Mvc\Model\Criteria + */ + public function ofUser($id) + { + return $this->where('user_id = '.$id); + } +} +``` + +```php +$result = Model::query()->ofUser(1)->where('x' > 'y')->execute(); +``` + +#### Global Criteria usage example: + +```php +class Model extends Frogg\Model +{ + /** + * @return ModelCriteria + */ + public static function query(DiInterface $dependencyInjector = null) + { + return parent::query($dependencyInjector)->addSoftDelete(); + } +} +``` + +```php +// this result applies softDelete for default, so all 'deleted = 1' results will be filtered +// (this filter is added at the end of the query) +$result = Model::query()->where('x' > 'y')->execute(); + +// but you can remove a global criteria calling removeCriteriaName +$resultWithDeleted = Model::query()->removeSoftDelete()->where('x' > 'y')->execute(); +// or for this specific method, we have an alias +$resultWithDeleted = Model::query()->withDeleted()->where('x' > 'y')->execute(); +``` + +#### Debugg tip + +You can get some infos like: +```php +$builder = Model::query()->where('x' > 'y'); +$phql = $builder->getPhql(); +$buildedQuery = $builder->getQuery(); +$criterias = $builder->getActiveCriterias(); +```