├── .gitignore ├── .travis.yml ├── LICENSE ├── README.md ├── composer.json ├── example ├── Domain │ ├── User.php │ └── UserId.php ├── Persistence │ └── Eloquent │ │ ├── User.php │ │ └── UserRepository.php ├── Service │ └── UserAdapter.php └── example.php ├── phpunit.xml.dist ├── src └── Infrastructure │ └── Model │ └── Repository │ └── EloquentMongoDB │ ├── BaseEloquentRepository.php │ ├── EloquentFilter.php │ ├── EloquentPageRepository.php │ ├── EloquentReadRepository.php │ ├── EloquentRepository.php │ ├── EloquentSorter.php │ ├── EloquentWriteRepository.php │ └── IdentityTrait.php └── tests ├── Database.php ├── Helpers ├── ClientId.php ├── ClientOrders.php ├── ClientOrdersRepository.php ├── Clients.php └── ClientsRepository.php ├── Infrastructure └── Model │ └── Repository │ └── Eloquent │ └── EloquentRepositoryTest.php └── autoload.php /.gitignore: -------------------------------------------------------------------------------- 1 | bin/ 2 | build/ 3 | vendor/ 4 | composer.lock 5 | .php_cs.cache 6 | example/mongo_populated.lock 7 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: php 2 | 3 | php: 4 | - 5.6 5 | - 7 6 | 7 | matrix: 8 | fast_finish: true 9 | 10 | sudo: false 11 | 12 | services: 13 | - mongodb 14 | 15 | addons: 16 | apt: 17 | sources: 18 | - mongodb-3.0-precise 19 | packages: 20 | - mongodb-org-server 21 | 22 | before_script: 23 | - pecl install mongodb 24 | - travis_retry composer self-update 25 | - travis_retry composer install --no-interaction 26 | 27 | script: 28 | - vendor/bin/phpunit 29 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2016 Nil Portugués Calderó 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Eloquent MongoDB Repository 2 | ![PHP7 Tested](http://php-eye.com/badge/nilportugues/eloquent-mongodb-repository/php70.svg) 3 | [![Build Status](https://travis-ci.org/PHPRepository/php-eloquent-mongodb-repository.svg)](https://travis-ci.org/PHPRepository/php-eloquent-mongodb-repository) [![Scrutinizer Code Quality](https://scrutinizer-ci.com/g/nilportugues/php-eloquent-mongodb-repository/badges/quality-score.png?b=master)](https://scrutinizer-ci.com/g/nilportugues/php-eloquent-mongodb-repository/?branch=master) [![SensioLabsInsight](https://insight.sensiolabs.com/projects/d993addb-38ad-4847-bd42-fa35fcfa0390/mini.png?gold)](https://insight.sensiolabs.com/projects/d993addb-38ad-4847-bd42-fa35fcfa0390) [![Latest Stable Version](https://poser.pugx.org/nilportugues/eloquent-mongodb-repository/v/stable?)](https://packagist.org/packages/nilportugues/eloquent-mongodb-repository) [![Total Downloads](https://poser.pugx.org/nilportugues/eloquent-mongodb-repository/downloads?)](https://packagist.org/packages/nilportugues/eloquent-mongodb-repository) [![License](https://poser.pugx.org/nilportugues/eloquent-mongodb-repository/license?)](https://packagist.org/packages/nilportugues/eloquent-mongodb-repository) 4 | [![Donate](https://www.paypalobjects.com/en_US/i/btn/btn_donate_SM.gif)](https://paypal.me/nilportugues) 5 | 6 | Eloquent MongoDB Repository using *[nilportugues/repository](https://github.com/nilportugues/php-repository)* as foundation, using *[jenssegers/mongodb](https://github.com/jenssegers/laravel-mongodb)*. 7 | 8 | ## Installation 9 | 10 | Use [Composer](https://getcomposer.org) to install the package: 11 | 12 | ```json 13 | $ composer require nilportugues/eloquent-mongodb-repository 14 | ``` 15 | 16 | ## Why? Drivers and Multiple Implementations! 17 | 18 | Using this implementation you can switch it out to test your code without setting up databases. 19 | 20 | Doesn't sound handy? Let's think of yet another use case you'll love using this. `Functional tests` and `Unitary tests`. 21 | 22 | No database connection will be needed, nor fakes. Using an `InMemoryRepository` or `FileSystemRepository` implementation will make those a breeze to code. And once the tests finish, all data may be destroyed with no worries at all. 23 | 24 | **Available drivers:** 25 | 26 | Also, if you feel like changing the repository implementation, no logic changes would be needed, as there are a set of drivers for you to use out of the box: 27 | 28 | - `composer require nilportugues/repository-cache` for [caching](https://github.com/nilportugues/php-repository-cache). 29 | - `composer require nilportugues/repository` for an [InMemoryRepository implementation](https://github.com/nilportugues/php-repository). 30 | - `composer require nilportugues/filesystem-repository` for a [FileSystemRepository implementation](https://github.com/nilportugues/php-filesystem-repository). 31 | - `composer require nilportugues/eloquent-repository` for a [SQL Eloquent implementation](https://github.com/nilportugues/php-eloquent-repository). 32 | - `composer require nilportugues/doctrine-repository` for a [SQL Doctrine implementation](https://github.com/nilportugues/php-doctrine-repository). 33 | 34 | 35 | 36 | ## Usage 37 | 38 | To set up Eloquent you don't need Laravel or Lumen frameworks at all. This is how you use Eloquent in any project. 39 | 40 | ```php 41 | getDatabaseManager()->extend('mongodb', function($config) { 46 | return new \Jenssegers\Mongodb\Connection($config); 47 | }); 48 | 49 | $capsule->addConnection([ 50 | 'driver' => 'mongodb', 51 | 'host' => 'localhost', 52 | 'port' => 27017, 53 | 'database' => 'default', 54 | 'username' => '', 55 | 'password' => '', 56 | 'options' => [ 57 | 'db' => 'admin' 58 | ] 59 | ], 60 | 'default' 61 | ); 62 | $capsule->bootEloquent(); 63 | $capsule->setAsGlobal(); 64 | ``` 65 | 66 | Now that Eloquent is running, we can use the Repository. 67 | 68 | ### A note about MongoDB Models 69 | 70 | The best way to ensure maximum compatibility with other Repository implementations is to **ignore** the MongoDB's ObjectId field: `_id` and declare one such as `id`. This means, not using MongoDB's ObjectId to fetch elements. 71 | 72 | This also means that you'll need an Adapter build from MongoDB object the expected Business objects. More on that further down, or check the [/example](https://github.com/nilportugues/php-eloquent-repository/tree/master/example) directory. 73 | 74 | ### One Repository for One Eloquent Model 75 | 76 | A well defined repository returns one kind of objects that belong to one Business model. 77 | 78 | ```php 79 | userAdapter = $userAdapter; 114 | } 115 | 116 | /** 117 | * {@inheritdoc} 118 | */ 119 | protected function modelClassName() 120 | { 121 | return User::class; 122 | } 123 | 124 | /** 125 | * {@inheritdoc} 126 | */ 127 | public function find(Identity $id, Fields $fields = null) 128 | { 129 | $eloquentModel = parent::find($id, $fields); 130 | 131 | return $this->userAdapter->fromEloquent($eloquentModel); 132 | } 133 | 134 | /** 135 | * {@inheritdoc} 136 | */ 137 | public function findBy(Filter $filter = null, Sort $sort = null, Fields $fields = null) 138 | { 139 | $eloquentModelArray = parent::findBy($filter, $sort, $fields); 140 | 141 | return $this->fromEloquentArray($eloquentModelArray); 142 | } 143 | 144 | /** 145 | * {@inheritdoc} 146 | */ 147 | public function findAll(Pageable $pageable = null) 148 | { 149 | $page = parent::findAll($pageable); 150 | 151 | return new Page( 152 | $this->fromEloquentArray($page->content()), 153 | $page->totalElements(), 154 | $page->pageNumber(), 155 | $page->totalPages(), 156 | $page->sortings(), 157 | $page->filters(), 158 | $page->fields() 159 | ); 160 | } 161 | 162 | /** 163 | * {@inheritdoc} 164 | */ 165 | public function add(Identity $value) 166 | { 167 | $value = $this->userAdapter->toEloquent($value); 168 | 169 | return parent::add($value); 170 | } 171 | 172 | /** 173 | * {@inheritdoc} 174 | */ 175 | public function addAll(array $values) 176 | { 177 | $eloquent = []; 178 | foreach ($values as $value) { 179 | $eloquent[] = $this->userAdapter->toEloquent($value); 180 | } 181 | 182 | parent::addAll($eloquent); 183 | } 184 | 185 | /** 186 | * @param array $eloquentModelArray 187 | * @return array 188 | */ 189 | protected function fromEloquentArray(array $eloquentModelArray) 190 | { 191 | $results = []; 192 | foreach ($eloquentModelArray as $eloquentModel) { 193 | //This is required to handle findAll returning array, not objects. 194 | $eloquentModel = (object) $eloquentModel; 195 | 196 | $results[] = $this->userAdapter->fromEloquent($eloquentModel); 197 | } 198 | 199 | return $results; 200 | } 201 | } 202 | ``` 203 | 204 | A sample implementation can be found in the [/example](https://github.com/nilportugues/php-eloquent-repository/tree/master/example) directory. 205 | 206 | ### One EloquentRepository for All Eloquent Models 207 | 208 | While **this is not the recommended way**, as a repository should only return one kind of Business objects, this works well with Laravel projects. 209 | 210 | While the amount of code is less than the previous example, bare in mind that your code will be coupled with Eloquent. 211 | 212 | ```php 213 | modelClass = (string) $modelClass; 229 | } 230 | 231 | /** 232 | * {@inheritdoc} 233 | */ 234 | protected function modelClassName() 235 | { 236 | return $this->modelClass; 237 | } 238 | } 239 | ``` 240 | 241 | ## Filtering data 242 | 243 | Filtering is as simple as using the `Filter` object. For instance, lets retrieve how many users are named `Ken`. 244 | 245 | ```php 246 | must()->contain('name', 'Ken'); 253 | 254 | echo $repository->count($filter); 255 | ``` 256 | 257 | Notice how the key `name` matches the database column `name` in the `users` table. 258 | 259 | **Available options** 260 | 261 | Filter allow you to use `must()`, `mustNot()` and `should()` methods to set up a fine-grained search. These provide a fluent interface with the following methods available: 262 | 263 | - `public function notEmpty($filterName)` 264 | - `public function hasEmpty($filterName)` 265 | - `public function startsWith($filterName, $value)` 266 | - `public function endsWith($filterName, $value)` 267 | - `public function equal($filterName, $value)` 268 | - `public function notEqual($filterName, $value)` 269 | - `public function includeGroup($filterName, array $value)` 270 | - `public function notIncludeGroup($filterName, array $value)` 271 | - `public function range($filterName, $firstValue, $secondValue)` 272 | - `public function notRange($filterName, $firstValue, $secondValue)` 273 | - `public function notContain($filterName, $value)` 274 | - `public function contain($filterName, $value)` 275 | - `public function beGreaterThanOrEqual($filterName, $value)` 276 | - `public function beGreaterThan($filterName, $value)` 277 | - `public function beLessThanOrEqual($filterName, $value)` 278 | - `public function beLessThan($filterName, $value)` 279 | 280 | ## Sorting data 281 | 282 | Sorting is straight forward. Create an instance of Sort and pass in the column names and ordering. 283 | 284 | ```php 285 | findBy($filter, $sort, $fields); 295 | ``` 296 | 297 | ## Fields data 298 | 299 | Create a Fields object to fetch only selected columns. If no Fields object is passed, all columns are selected by default. 300 | 301 | ```php 302 | findBy($filter, $sort, $fields); 312 | ``` 313 | 314 | ## Fetching data 315 | 316 | Repository allows you to fetch data from the database by using the following methods: 317 | 318 | - `public function findAll(Pageable $pageable = null)` 319 | - `public function find(Identity $id, Fields $fields = null)` 320 | - `public function findBy(Filter $filter = null, Sort $sort = null, Fields $fields = null)` 321 | 322 | 323 | ## Quality 324 | 325 | To run the PHPUnit tests at the command line, go to the tests directory and issue phpunit. 326 | 327 | This library attempts to comply with [PSR-1](http://www.php-fig.org/psr/psr-1/), [PSR-2](http://www.php-fig.org/psr/psr-2/), [PSR-4](http://www.php-fig.org/psr/psr-4/). 328 | 329 | If you notice compliance oversights, please send a patch via [Pull Request](https://github.com/nilportugues/php-eloquent-repository/pulls). 330 | 331 | 332 | ## Contribute 333 | 334 | Contributions to the package are always welcome! 335 | 336 | * Report any bugs or issues you find on the [issue tracker](https://github.com/nilportugues/php-eloquent-repository/issues/new). 337 | * You can grab the source code at the package's [Git Repository](https://github.com/nilportugues/php-eloquent-repository). 338 | 339 | 340 | ## Support 341 | 342 | Get in touch with me using one of the following means: 343 | 344 | - Emailing me at 345 | - Opening an [Issue](https://github.com/nilportugues/php-eloquent-repository/issues/new) 346 | 347 | 348 | ## Authors 349 | 350 | * [Nil Portugués Calderó](http://nilportugues.com) 351 | * [The Community Contributors](https://github.com/nilportugues/php-eloquent-repository/graphs/contributors) 352 | 353 | 354 | ## License 355 | The code base is licensed under the [MIT license](LICENSE). 356 | -------------------------------------------------------------------------------- /composer.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "nilportugues/eloquent-mongodb-repository", 3 | "description": "Eloquent MongoDB Repository implementation", 4 | "keywords": ["eloquent", "mongodb", "mongo", "laravel", "repository", "cache", "ddd", "hexagonal", "ports and adapters", "ports", "adapters", "repository", "pageable", "pagination", "nil portugues", "nilportugues"], 5 | "type": "library", 6 | "homepage": "http://nilportugues.com", 7 | "license": "MIT", 8 | "authors": [ 9 | { 10 | "name": "Nil Portugués", 11 | "email": "contact@nilportugues.com" 12 | } 13 | ], 14 | "require": { 15 | "nilportugues/repository": "^2.3", 16 | "nilportugues/assert": "^1.0", 17 | "illuminate/database": "^5.2", 18 | "illuminate/pagination": "^5.2", 19 | "jenssegers/mongodb" : "v3.0.*" 20 | }, 21 | "require-dev": { 22 | "phpunit/phpunit": "4.8.*", 23 | "fabpot/php-cs-fixer": "1.9.*" 24 | }, 25 | "autoload": { 26 | "psr-4": { 27 | "NilPortugues\\Foundation\\": "src", 28 | "NilPortugues\\Example\\": "example" 29 | } 30 | }, 31 | "autoload-dev": { 32 | "psr-4": { 33 | "NilPortugues\\Tests\\Foundation\\": "tests/" 34 | } 35 | }, 36 | "suggest": { 37 | "nilportugues/mongodb-repository": "MongoDB Repository implementation.", 38 | "nilportugues/eloquent-repository": "SQL Eloquent Repository implementation.", 39 | "nilportugues/filesystem-repository": "FileSystem repository implementation.", 40 | "nilportugues/repository-cache": "Cache any nilportugues/repository implementation." 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /example/Domain/User.php: -------------------------------------------------------------------------------- 1 | userId = $id; 33 | $this->name = $name; 34 | $this->registrationDate = $registrationDate; 35 | } 36 | 37 | /** 38 | * Returns value for userId property. 39 | * 40 | * @return UserId 41 | */ 42 | public function userId() 43 | { 44 | return $this->userId; 45 | } 46 | 47 | /** 48 | * Returns value for name property. 49 | * 50 | * @return string 51 | */ 52 | public function name() 53 | { 54 | return $this->name; 55 | } 56 | 57 | /** 58 | * Returns value for registrationDate property. 59 | * 60 | * @return DateTimeImmutable 61 | */ 62 | public function registrationDate() 63 | { 64 | return $this->registrationDate; 65 | } 66 | 67 | /** 68 | * @return mixed 69 | */ 70 | public function id() 71 | { 72 | return $this->userId()->id(); 73 | } 74 | 75 | /** 76 | * @return string 77 | */ 78 | public function __toString() 79 | { 80 | return (string) $this->id(); 81 | } 82 | } 83 | -------------------------------------------------------------------------------- /example/Domain/UserId.php: -------------------------------------------------------------------------------- 1 | 5 | * Date: 7/02/16 6 | * Time: 18:12. 7 | * 8 | * For the full copyright and license information, please view the LICENSE 9 | * file that was distributed with this source code. 10 | */ 11 | namespace NilPortugues\Example\Domain; 12 | 13 | use NilPortugues\Foundation\Domain\Model\Repository\Contracts\Identity; 14 | 15 | /** 16 | * Class UserId. 17 | */ 18 | class UserId implements Identity 19 | { 20 | private $id; 21 | 22 | /** 23 | * UserId constructor. 24 | * 25 | * @param $id 26 | */ 27 | public function __construct($id) 28 | { 29 | $this->id = $id; 30 | } 31 | 32 | /** 33 | * @return mixed 34 | */ 35 | public function id() 36 | { 37 | return $this->id; 38 | } 39 | 40 | /** 41 | * @return string 42 | */ 43 | public function __toString() 44 | { 45 | return (string) $this->id(); 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /example/Persistence/Eloquent/User.php: -------------------------------------------------------------------------------- 1 | 5 | * Date: 7/02/16 6 | * Time: 17:56. 7 | * 8 | * For the full copyright and license information, please view the LICENSE 9 | * file that was distributed with this source code. 10 | */ 11 | namespace NilPortugues\Example\Persistence\Eloquent; 12 | 13 | use Jenssegers\Mongodb\Eloquent\Model; 14 | use NilPortugues\Foundation\Domain\Model\Repository\Contracts\Identity; 15 | use NilPortugues\Foundation\Infrastructure\Model\Repository\EloquentMongoDB\IdentityTrait; 16 | 17 | /** 18 | * Class User. 19 | */ 20 | class User extends Model implements Identity 21 | { 22 | use IdentityTrait; 23 | 24 | /** 25 | * @var string 26 | */ 27 | protected $table = 'users'; 28 | 29 | /** 30 | * Override the default MongoDB key _id to maximize compatibility. 31 | * 32 | * @var string 33 | */ 34 | protected $primaryKey = 'id'; 35 | } 36 | -------------------------------------------------------------------------------- /example/Persistence/Eloquent/UserRepository.php: -------------------------------------------------------------------------------- 1 | 5 | * Date: 7/02/16 6 | * Time: 17:59. 7 | * 8 | * For the full copyright and license information, please view the LICENSE 9 | * file that was distributed with this source code. 10 | */ 11 | namespace NilPortugues\Example\Persistence\Eloquent; 12 | 13 | use Illuminate\Database\Eloquent\Model; 14 | use NilPortugues\Assert\Assert; 15 | use NilPortugues\Example\Service\UserAdapter; 16 | use NilPortugues\Foundation\Domain\Model\Repository\Contracts\Fields; 17 | use NilPortugues\Foundation\Domain\Model\Repository\Contracts\Filter; 18 | use NilPortugues\Foundation\Domain\Model\Repository\Contracts\Identity; 19 | use NilPortugues\Foundation\Domain\Model\Repository\Contracts\Pageable; 20 | use NilPortugues\Foundation\Domain\Model\Repository\Contracts\Sort; 21 | use NilPortugues\Foundation\Domain\Model\Repository\Page; 22 | use NilPortugues\Foundation\Infrastructure\Model\Repository\EloquentMongoDB\EloquentRepository; 23 | 24 | /** 25 | * Class UserRepository. 26 | */ 27 | class UserRepository extends EloquentRepository 28 | { 29 | /** 30 | * @var UserAdapter 31 | */ 32 | protected $userAdapter; 33 | 34 | /** 35 | * @param $userAdapter 36 | */ 37 | public function __construct($userAdapter) 38 | { 39 | $this->userAdapter = $userAdapter; 40 | } 41 | 42 | /** 43 | * {@inheritdoc} 44 | */ 45 | protected function modelClassName() 46 | { 47 | return User::class; 48 | } 49 | 50 | /** 51 | * {@inheritdoc} 52 | */ 53 | public function find(Identity $id, Fields $fields = null) 54 | { 55 | /** @var Model $eloquentModel */ 56 | $eloquentModel = parent::find($id, $fields); 57 | 58 | return $this->userAdapter->fromEloquent($eloquentModel->toArray()); 59 | } 60 | 61 | /** 62 | * {@inheritdoc} 63 | */ 64 | public function findBy(Filter $filter = null, Sort $sort = null, Fields $fields = null) 65 | { 66 | $eloquentModelArray = parent::findBy($filter, $sort, $fields); 67 | 68 | return $this->fromEloquentArray($eloquentModelArray); 69 | } 70 | 71 | /** 72 | * {@inheritdoc} 73 | */ 74 | public function findAll(Pageable $pageable = null) 75 | { 76 | $page = parent::findAll($pageable); 77 | 78 | return new Page( 79 | $this->fromEloquentArray($page->content()), 80 | $page->totalElements(), 81 | $page->pageNumber(), 82 | $page->totalPages(), 83 | $page->sortings(), 84 | $page->filters(), 85 | $page->fields() 86 | ); 87 | } 88 | 89 | /** 90 | * {@inheritdoc} 91 | */ 92 | public function add(Identity $value) 93 | { 94 | Assert::isInstanceOf($value, User::class); 95 | $value = $this->userAdapter->toEloquent($value); 96 | 97 | return parent::add($value); 98 | } 99 | 100 | /** 101 | * {@inheritdoc} 102 | */ 103 | public function addAll(array $values) 104 | { 105 | $eloquent = []; 106 | foreach ($values as $value) { 107 | Assert::isInstanceOf($value, User::class); 108 | $eloquent[] = $this->userAdapter->toEloquent($value); 109 | } 110 | 111 | parent::addAll($eloquent); 112 | } 113 | 114 | /** 115 | * @param array $eloquentModelArray 116 | * 117 | * @return array 118 | */ 119 | protected function fromEloquentArray(array $eloquentModelArray) 120 | { 121 | $results = []; 122 | foreach ($eloquentModelArray as $eloquentModel) { 123 | if (is_object($eloquentModel) && method_exists($eloquentModel, 'toArray')) { 124 | $eloquentModel = $eloquentModel->toArray(); 125 | } 126 | 127 | $results[] = $this->userAdapter->fromEloquent($eloquentModel); 128 | } 129 | 130 | return $results; 131 | } 132 | } 133 | -------------------------------------------------------------------------------- /example/Service/UserAdapter.php: -------------------------------------------------------------------------------- 1 | id = $user->id(); 21 | $mongoDB->name = $user->name(); 22 | $mongoDB->created_at = $user->registrationDate(); 23 | 24 | return $mongoDB; 25 | } 26 | /** 27 | * @param array $model 28 | * 29 | * @return \NilPortugues\Example\Domain\User 30 | */ 31 | public function fromEloquent(array $model) 32 | { 33 | return new User(new UserId($model['id']), $model['name'], new DateTimeImmutable($model['created_at'])); 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /example/example.php: -------------------------------------------------------------------------------- 1 | getDatabaseManager()->extend('mongodb', function ($config) { 21 | return new Jenssegers\Mongodb\Connection($config); 22 | }); 23 | 24 | //Create connection 25 | $capsule->addConnection([ 26 | 'driver' => 'mongodb', 27 | 'host' => 'localhost', 28 | 'port' => 27017, 29 | 'database' => 'users', 30 | 'username' => '', 31 | 'password' => '', 32 | 'options' => [ 33 | 'db' => 'admin', 34 | ], 35 | ], 36 | 'default' 37 | ); 38 | $capsule->bootEloquent(); 39 | $capsule->setAsGlobal(); 40 | 41 | //------------------------------------------------------------------------------------------------------------- 42 | // - Create dummy data for the same of the example. 43 | //------------------------------------------------------------------------------------------------------------- 44 | User::query()->delete(); 45 | 46 | $model = new User(); 47 | $model->id = 1; 48 | $model->name = 'Admin User'; 49 | $model->created_at = '2016-02-18'; 50 | $model->save(); 51 | 52 | for ($i = 2; $i <= 20; ++$i) { 53 | $model = new User(); 54 | $model->id = $i; 55 | $model->name = 'Dummy User '.$i; 56 | $model->created_at = (new DateTime())->setDate(2016, rand(1, 12), rand(1, 27)); 57 | $model->save(); 58 | } 59 | 60 | //------------------------------------------------------------------------------------------------------------- 61 | // - getUserAction 62 | //------------------------------------------------------------------------------------------------------------- 63 | $userAdapter = new UserAdapter(); 64 | $repository = new UserRepository($userAdapter); 65 | 66 | $userId = new UserId(1); 67 | print_r($repository->find($userId)); 68 | 69 | //------------------------------------------------------------------------------------------------------------- 70 | // - getUsersRegisteredLastMonth 71 | //------------------------------------------------------------------------------------------------------------- 72 | 73 | $filter = new Filter(); 74 | $filter->must()->notIncludeGroup('id', [2, 5]); 75 | $filter->must()->beGreaterThan('created_at', new DateTime('2016-03-01')); 76 | 77 | $sort = new Sort(); 78 | $sort->setOrderFor('created_at', new Order('ASC')); 79 | 80 | print_r($repository->findBy($filter, $sort)); 81 | -------------------------------------------------------------------------------- /phpunit.xml.dist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | ./tests 31 | 32 | 33 | 34 | 35 | 36 | ./ 37 | 38 | ./example 39 | ./tests 40 | ./vendor/ 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | -------------------------------------------------------------------------------- /src/Infrastructure/Model/Repository/EloquentMongoDB/BaseEloquentRepository.php: -------------------------------------------------------------------------------- 1 | 5 | * Date: 7/02/16 6 | * Time: 16:06. 7 | * 8 | * For the full copyright and license information, please view the LICENSE 9 | * file that was distributed with this source code. 10 | */ 11 | namespace NilPortugues\Foundation\Infrastructure\Model\Repository\EloquentMongoDB; 12 | 13 | use Jenssegers\Mongodb\Eloquent\Builder; 14 | use Illuminate\Database\Eloquent\Builder as EloquentBuilder; 15 | use NilPortugues\Foundation\Domain\Model\Repository\Contracts\BaseFilter; 16 | use NilPortugues\Foundation\Domain\Model\Repository\Contracts\Filter as FilterInterface; 17 | 18 | /** 19 | * Class EloquentFilter. 20 | */ 21 | class EloquentFilter 22 | { 23 | const MUST_NOT = 'must_not'; 24 | const MUST = 'must'; 25 | const SHOULD = 'should'; 26 | 27 | const CONTAINS_PATTERN = '/%s/i'; 28 | const STARTS_WITH_PATTERN = '/^%s/i'; 29 | const ENDS_WITH_PATTERN = '/%s$/i'; 30 | 31 | const NOT_CONTAINS_PATTERN = '/^((?!%s.))/i'; 32 | const NOT_ENDS_WITH_PATTERN = '/.*(?filters() as $condition => $filters) { 44 | $filters = self::removeEmptyFilters($filters); 45 | if (count($filters) > 0) { 46 | self::processConditions($query, $condition, $filters); 47 | } 48 | } 49 | 50 | return $query; 51 | } 52 | 53 | /** 54 | * @param array $filters 55 | * 56 | * @return array 57 | */ 58 | private static function removeEmptyFilters(array $filters) 59 | { 60 | $filters = array_filter($filters, function ($v) { 61 | return count($v) > 0; 62 | }); 63 | 64 | return $filters; 65 | } 66 | 67 | /** 68 | * @param Builder|EloquentBuilder $where 69 | * @param string $condition 70 | * @param array $filters 71 | */ 72 | private static function processConditions(Builder $where, $condition, array &$filters) 73 | { 74 | switch ($condition) { 75 | case self::MUST: 76 | self::apply($where, $filters, 'and'); 77 | break; 78 | 79 | case self::MUST_NOT: 80 | self::applyNot($where, $filters); 81 | break; 82 | 83 | case self::SHOULD: 84 | self::apply($where, $filters, 'or'); 85 | break; 86 | } 87 | } 88 | 89 | /** 90 | * @param Builder|EloquentBuilder $where 91 | * @param array $filters 92 | * @param $boolean 93 | */ 94 | protected static function apply(Builder $where, array $filters, $boolean) 95 | { 96 | foreach ($filters as $filterName => $valuePair) { 97 | foreach ($valuePair as $key => $value) { 98 | if (is_array($value) && count($value) > 0) { 99 | $value = array_values($value); 100 | if (count($value[0]) > 1) { 101 | switch ($filterName) { 102 | case BaseFilter::RANGES: 103 | $where->whereBetween($key, [$value[0][0], $value[0][1]], $boolean); 104 | break; 105 | case BaseFilter::NOT_RANGES: 106 | $where->whereNotBetween($key, [$value[0][0], $value[0][1]], $boolean); 107 | break; 108 | } 109 | } else { 110 | switch ($filterName) { 111 | case BaseFilter::GROUP: 112 | $where->whereIn($key, $value, $boolean); 113 | break; 114 | case BaseFilter::NOT_GROUP: 115 | $where->whereNotIn($key, $value, $boolean); 116 | $where->whereNotNull($key); 117 | break; 118 | } 119 | } 120 | } 121 | 122 | $value = (array) $value; 123 | $value = array_shift($value); 124 | switch ($filterName) { 125 | case BaseFilter::GREATER_THAN_OR_EQUAL: 126 | $where->where($key, '>=', $value, $boolean); 127 | break; 128 | case BaseFilter::GREATER_THAN: 129 | $where->where($key, '>', $value, $boolean); 130 | break; 131 | case BaseFilter::LESS_THAN_OR_EQUAL: 132 | $where->where($key, '<=', $value, $boolean); 133 | break; 134 | case BaseFilter::LESS_THAN: 135 | $where->where($key, '<', $value, $boolean); 136 | break; 137 | case BaseFilter::CONTAINS: 138 | $where->where($key, 'regex', sprintf(self::CONTAINS_PATTERN, $value), $boolean); 139 | break; 140 | case BaseFilter::NOT_CONTAINS: 141 | $where->where($key, 'regex', sprintf(self::NOT_CONTAINS_PATTERN, $value), $boolean); 142 | break; 143 | case BaseFilter::STARTS_WITH: 144 | $where->where($key, 'regex', sprintf(self::STARTS_WITH_PATTERN, $value), $boolean); 145 | break; 146 | case BaseFilter::ENDS_WITH: 147 | $where->where($key, 'regex', sprintf(self::ENDS_WITH_PATTERN, $value), $boolean); 148 | break; 149 | case BaseFilter::EQUALS: 150 | $where->where($key, '=', $value, $boolean); 151 | break; 152 | case BaseFilter::NOT_EQUAL: 153 | $where->where($key, '!=', $value, $boolean); 154 | break; 155 | } 156 | } 157 | } 158 | } 159 | 160 | /** 161 | * @param Builder $where 162 | * @param array $filters 163 | */ 164 | protected static function applyNot(Builder $where, array $filters) 165 | { 166 | foreach ($filters as $filterName => $valuePair) { 167 | foreach ($valuePair as $key => $value) { 168 | if (is_array($value) && count($value) > 0) { 169 | $value = array_values($value); 170 | if (count($value[0]) > 1) { 171 | switch ($filterName) { 172 | case BaseFilter::RANGES: 173 | $where->whereNotBetween($key, [$value[0][0], $value[0][1]]); 174 | break; 175 | case BaseFilter::NOT_RANGES: 176 | $where->whereBetween($key, [$value[0][0], $value[0][1]]); 177 | break; 178 | } 179 | } else { 180 | switch ($filterName) { 181 | case BaseFilter::GROUP: 182 | $where->whereNotIn($key, $value); 183 | $where->whereNotNull($key); 184 | break; 185 | case BaseFilter::NOT_GROUP: 186 | $where->whereIn($key, $value); 187 | break; 188 | } 189 | } 190 | } 191 | 192 | $value = array_shift($value); 193 | switch ($filterName) { 194 | case BaseFilter::GREATER_THAN_OR_EQUAL: 195 | $where->where($key, '<', $value); 196 | break; 197 | case BaseFilter::GREATER_THAN: 198 | $where->where($key, '<=', $value); 199 | break; 200 | case BaseFilter::LESS_THAN_OR_EQUAL: 201 | $where->where($key, '>', $value); 202 | break; 203 | case BaseFilter::LESS_THAN: 204 | $where->where($key, '>=', $value); 205 | break; 206 | case BaseFilter::CONTAINS: 207 | $where->where($key, 'regex', sprintf(self::NOT_CONTAINS_PATTERN, $value)); 208 | break; 209 | case BaseFilter::NOT_CONTAINS: 210 | $where->where($key, 'regex', sprintf(self::CONTAINS_PATTERN, $value)); 211 | break; 212 | case BaseFilter::STARTS_WITH: 213 | $where->where($key, 'regex', sprintf(self::NOT_STARTS_WITH_PATTERN, $value)); 214 | break; 215 | case BaseFilter::ENDS_WITH: 216 | $where->where($key, 'regex', sprintf(self::NOT_ENDS_WITH_PATTERN, $value)); 217 | break; 218 | case BaseFilter::EQUALS: 219 | $where->where($key, '!=', $value); 220 | break; 221 | case BaseFilter::NOT_EQUAL: 222 | $where->where($key, '=', $value); 223 | break; 224 | } 225 | } 226 | } 227 | } 228 | } 229 | -------------------------------------------------------------------------------- /src/Infrastructure/Model/Repository/EloquentMongoDB/EloquentPageRepository.php: -------------------------------------------------------------------------------- 1 | query(); 23 | 24 | if ($pageable) { 25 | $fields = $pageable->fields(); 26 | $columns = (!$fields->isNull()) ? $fields->get() : ['*']; 27 | 28 | $filter = $pageable->filters(); 29 | if (!$filter->isNull()) { 30 | EloquentFilter::filter($query, $filter); 31 | } 32 | 33 | $sort = $pageable->sortings(); 34 | if (!$sort->isNull()) { 35 | EloquentSorter::sort($query, $sort); 36 | } 37 | 38 | $model = $model 39 | ->take($pageable->pageSize()) 40 | ->offset($pageable->pageSize() * ($pageable->pageNumber() - 1)); 41 | 42 | if (count($distinctFields = $pageable->distinctFields()->get()) > 0) { 43 | $model = $model->distinct(); 44 | $columns = $distinctFields; 45 | } 46 | 47 | $pageSize = $pageable->pageSize(); 48 | $pageSize = ($pageSize>0) ? $pageSize : 1; 49 | 50 | return new ResultPage( 51 | $model->get($columns)->toArray(), 52 | $model->count(), 53 | $pageable->pageNumber(), 54 | ceil($query->paginate()->total() / $pageSize) 55 | ); 56 | } 57 | 58 | return new ResultPage( 59 | $query->paginate($query->paginate()->total(), ['*'], 'page', 1)->items(), 60 | $query->paginate()->total(), 61 | 1, 62 | 1 63 | ); 64 | } 65 | } 66 | -------------------------------------------------------------------------------- /src/Infrastructure/Model/Repository/EloquentMongoDB/EloquentReadRepository.php: -------------------------------------------------------------------------------- 1 | get() : ['*']; 26 | 27 | return $model->query()->where($model->getKeyName(), '=', $id->id())->get($columns)->first(); 28 | } 29 | 30 | /** 31 | * Returns all instances of the type. 32 | * 33 | * @param Filter|null $filter 34 | * @param Sort|null $sort 35 | * @param Fields|null $fields 36 | * 37 | * @return array 38 | */ 39 | public function findBy(Filter $filter = null, Sort $sort = null, Fields $fields = null) 40 | { 41 | $model = self::$instance; 42 | $query = $model->query(); 43 | $columns = ($fields) ? $fields->get() : ['*']; 44 | 45 | if ($filter) { 46 | EloquentFilter::filter($query, $filter); 47 | } 48 | 49 | if ($sort) { 50 | EloquentSorter::sort($query, $sort); 51 | } 52 | 53 | return $query->get($columns)->toArray(); 54 | } 55 | 56 | /** 57 | * Returns all instances of the type meeting $distinctFields values. 58 | * 59 | * @param Fields $distinctFields 60 | * @param Filter|null $filter 61 | * @param Sort|null $sort 62 | * 63 | * @return array 64 | */ 65 | public function findByDistinct(Fields $distinctFields, Filter $filter = null, Sort $sort = null) 66 | { 67 | $model = self::$instance; 68 | $query = $model->query(); 69 | 70 | $columns = (count($fields = $distinctFields->get()) > 0) ? $fields : ['*']; 71 | 72 | if ($filter) { 73 | EloquentFilter::filter($query, $filter); 74 | } 75 | 76 | if ($sort) { 77 | EloquentSorter::sort($query, $sort); 78 | } 79 | 80 | return $query->getQuery()->distinct()->get($columns); 81 | } 82 | 83 | /** 84 | * Returns the total amount of elements in the repository given the restrictions provided by the Filter object. 85 | * 86 | * @param Filter|null $filter 87 | * 88 | * @return int 89 | */ 90 | public function count(Filter $filter = null) 91 | { 92 | $model = self::$instance; 93 | $query = $model->query(); 94 | if ($filter) { 95 | EloquentFilter::filter($query, $filter); 96 | } 97 | return (int) $query->getQuery()->count(); 98 | } 99 | 100 | /** 101 | * Returns whether an entity with the given id exists. 102 | * 103 | * @param $id 104 | * 105 | * @return bool 106 | */ 107 | public function exists(Identity $id) 108 | { 109 | $model = self::$instance; 110 | $filter = new DomainFilter(); 111 | $filter->must()->equal($model->getKeyName(), $id->id()); 112 | return $this->count($filter) > 0; 113 | } 114 | } 115 | -------------------------------------------------------------------------------- /src/Infrastructure/Model/Repository/EloquentMongoDB/EloquentRepository.php: -------------------------------------------------------------------------------- 1 | 5 | * Date: 7/02/16 6 | * Time: 15:58. 7 | * 8 | * For the full copyright and license information, please view the LICENSE 9 | * file that was distributed with this source code. 10 | */ 11 | namespace NilPortugues\Foundation\Infrastructure\Model\Repository\EloquentMongoDB; 12 | 13 | use Jenssegers\Mongodb\Eloquent\Model; 14 | use NilPortugues\Foundation\Domain\Model\Repository\Contracts\Fields; 15 | use NilPortugues\Foundation\Domain\Model\Repository\Contracts\Filter; 16 | use NilPortugues\Foundation\Domain\Model\Repository\Contracts\Identity; 17 | use NilPortugues\Foundation\Domain\Model\Repository\Contracts\Page; 18 | use NilPortugues\Foundation\Domain\Model\Repository\Contracts\Pageable; 19 | use NilPortugues\Foundation\Domain\Model\Repository\Contracts\PageRepository; 20 | use NilPortugues\Foundation\Domain\Model\Repository\Contracts\ReadRepository; 21 | use NilPortugues\Foundation\Domain\Model\Repository\Contracts\Sort; 22 | use NilPortugues\Foundation\Domain\Model\Repository\Contracts\WriteRepository; 23 | 24 | /** 25 | * Class EloquentRepository. 26 | */ 27 | abstract class EloquentRepository implements ReadRepository, WriteRepository, PageRepository 28 | { 29 | /** @var Model */ 30 | protected static $instance; 31 | /** @var EloquentReadRepository */ 32 | protected $readRepository; 33 | /** @var EloquentWriteRepository */ 34 | protected $writeRepository; 35 | /** @var EloquentPageRepository */ 36 | protected $pageRepository; 37 | 38 | /** 39 | * EloquentRepository constructor. 40 | */ 41 | public function __construct() 42 | { 43 | $eloquentModel = $this->getModelInstance(); 44 | 45 | $this->readRepository = EloquentReadRepository::create($eloquentModel); 46 | $this->writeRepository = EloquentWriteRepository::create($eloquentModel); 47 | $this->pageRepository = EloquentPageRepository::create($eloquentModel); 48 | } 49 | 50 | /** 51 | * Retrieves an entity by its id. 52 | * 53 | * @param Identity|Model $id 54 | * @param Fields|null $fields 55 | * 56 | * @return array 57 | */ 58 | public function find(Identity $id, Fields $fields = null) 59 | { 60 | return $this->readRepository->find($id, $fields); 61 | } 62 | 63 | /** 64 | * Returns all instances of the type. 65 | * 66 | * @param Filter|null $filter 67 | * @param Sort|null $sort 68 | * @param Fields|null $fields 69 | * 70 | * @return array 71 | */ 72 | public function findBy(Filter $filter = null, Sort $sort = null, Fields $fields = null) 73 | { 74 | return $this->readRepository->findBy($filter, $sort, $fields); 75 | } 76 | 77 | /** 78 | * Returns an EloquentMongoDB Model instance. 79 | * 80 | * @return Model 81 | */ 82 | protected function getModelInstance() 83 | { 84 | if (null === self::$instance) { 85 | $modelInstance = $this->modelClassName(); 86 | self::$instance = new $modelInstance(); 87 | } 88 | 89 | return self::$instance; 90 | } 91 | 92 | /** 93 | * Must return the EloquentMongoDB Model Fully Qualified Class Name as a string. 94 | * 95 | * eg: return App\Model\User::class 96 | * 97 | * @return string 98 | */ 99 | abstract protected function modelClassName(); 100 | 101 | /** 102 | * Returns whether an entity with the given id exists. 103 | * 104 | * @param Identity|Model $id 105 | * 106 | * @return bool 107 | */ 108 | public function exists(Identity $id) 109 | { 110 | return $this->writeRepository->exists($id); 111 | } 112 | 113 | /** 114 | * Returns the total amount of elements in the repository given the restrictions provided by the Filter object. 115 | * 116 | * @param Filter|null $filter 117 | * 118 | * @return int 119 | */ 120 | public function count(Filter $filter = null) 121 | { 122 | return $this->writeRepository->count($filter); 123 | } 124 | 125 | /** 126 | * Adds a new entity to the storage. 127 | * 128 | * @param Identity|Model $value 129 | * 130 | * @return mixed 131 | */ 132 | public function add(Identity $value) 133 | { 134 | return $this->writeRepository->add($value); 135 | } 136 | 137 | /** 138 | * Adds a collections of entities to the storage. 139 | * 140 | * @param Model[] $values 141 | * 142 | * @return mixed 143 | * 144 | * @throws \Exception 145 | */ 146 | public function addAll(array $values) 147 | { 148 | return $this->writeRepository->addAll($values); 149 | } 150 | 151 | /** 152 | * Removes the entity with the given id. 153 | * 154 | * @param Identity|Model $id 155 | * 156 | * @return bool 157 | */ 158 | public function remove(Identity $id) 159 | { 160 | return $this->writeRepository->remove($id); 161 | } 162 | 163 | /** 164 | * Removes all elements in the repository given the restrictions provided by the Filter object. 165 | * If $filter is null, all the repository data will be deleted. 166 | * 167 | * @param Filter $filter 168 | * 169 | * @return bool 170 | */ 171 | public function removeAll(Filter $filter = null) 172 | { 173 | return $this->writeRepository->removeAll($filter); 174 | } 175 | 176 | /** 177 | * Returns a Page of entities meeting the paging restriction provided in the Pageable object. 178 | * 179 | * @param Pageable $pageable 180 | * 181 | * @return Page 182 | */ 183 | public function findAll(Pageable $pageable = null) 184 | { 185 | return $this->pageRepository->findAll($pageable); 186 | } 187 | 188 | /** 189 | * Returns all instances of the type meeting $distinctFields values. 190 | * 191 | * @param Fields $distinctFields 192 | * @param Filter|null $filter 193 | * @param Sort|null $sort 194 | * 195 | * @return array 196 | */ 197 | public function findByDistinct(Fields $distinctFields, Filter $filter = null, Sort $sort = null) 198 | { 199 | return $this->readRepository->findByDistinct($distinctFields, $filter, $sort); 200 | } 201 | 202 | /** 203 | * Repository data is added or removed as a whole block. 204 | * Must work or fail and rollback any persisted/erased data. 205 | * 206 | * @param callable $transaction 207 | * 208 | * @throws \Exception 209 | */ 210 | public function transactional(callable $transaction) 211 | { 212 | $this->writeRepository->transactional($transaction); 213 | } 214 | } 215 | -------------------------------------------------------------------------------- /src/Infrastructure/Model/Repository/EloquentMongoDB/EloquentSorter.php: -------------------------------------------------------------------------------- 1 | 5 | * Date: 7/02/16 6 | * Time: 16:06. 7 | * 8 | * For the full copyright and license information, please view the LICENSE 9 | * file that was distributed with this source code. 10 | */ 11 | namespace NilPortugues\Foundation\Infrastructure\Model\Repository\EloquentMongoDB; 12 | 13 | use Jenssegers\Mongodb\Eloquent\Builder; 14 | use Illuminate\Database\Eloquent\Builder as EloquentBuilder; 15 | use NilPortugues\Foundation\Domain\Model\Repository\Contracts\Order; 16 | use NilPortugues\Foundation\Domain\Model\Repository\Contracts\Sort as SortInterface; 17 | 18 | /** 19 | * Class EloquentSorter. 20 | */ 21 | class EloquentSorter 22 | { 23 | /** 24 | * @param Builder|EloquentBuilder $query 25 | * @param SortInterface $sort 26 | */ 27 | public static function sort(Builder $query, SortInterface $sort) 28 | { 29 | /** @var Order $order */ 30 | foreach ($sort->orders() as $propertyName => $order) { 31 | $query->getQuery()->orderBy($propertyName, $order->isAscending() ? 'ASC' : 'DESC'); 32 | } 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /src/Infrastructure/Model/Repository/EloquentMongoDB/EloquentWriteRepository.php: -------------------------------------------------------------------------------- 1 | query(); 22 | 23 | if ($filter) { 24 | EloquentFilter::filter($query, $filter); 25 | } 26 | 27 | return (int) $query->getQuery()->count(); 28 | } 29 | 30 | /** 31 | * Returns whether an entity with the given id exists. 32 | * 33 | * @param $id 34 | * 35 | * @return bool 36 | */ 37 | public function exists(Identity $id) 38 | { 39 | $model = self::$instance; 40 | $result = $model->query()->where($model->getKeyName(), '=', $id->id())->first(); 41 | 42 | return null !== $result; 43 | } 44 | 45 | /** 46 | * Adds a new entity to the storage. 47 | * 48 | * @param Identity $value 49 | * 50 | * @return mixed 51 | */ 52 | public function add(Identity $value) 53 | { 54 | $this->guard($value); 55 | $value->save(); 56 | 57 | return $value; 58 | } 59 | 60 | /** 61 | * Adds a collections of entities to the storage. 62 | * 63 | * @param array $values 64 | * 65 | * @return mixed 66 | * 67 | * @throws \Exception 68 | */ 69 | public function addAll(array $values) 70 | { 71 | $model = self::$instance; 72 | $ids = []; 73 | try { 74 | foreach ($values as $value) { 75 | $this->guard($value); 76 | $value->save(); 77 | $ids[] = $value->getIdAttribute('_id'); 78 | } 79 | } catch (\Exception $e) { 80 | $model->destroy($ids); 81 | throw $e; 82 | } 83 | } 84 | 85 | /** 86 | * Removes the entity with the given id. 87 | * 88 | * @param $id 89 | * 90 | * @return bool 91 | */ 92 | public function remove(Identity $id) 93 | { 94 | $model = self::$instance; 95 | 96 | return (bool) $model->query()->find($id->id())->delete(); 97 | } 98 | 99 | /** 100 | * Removes all elements in the repository given the restrictions provided by the Filter object. 101 | * If $filter is null, all the repository data will be deleted. 102 | * 103 | * @param Filter $filter 104 | * 105 | * @return bool 106 | */ 107 | public function removeAll(Filter $filter = null) 108 | { 109 | $model = self::$instance; 110 | $query = $model->query(); 111 | 112 | if ($filter) { 113 | EloquentFilter::filter($query, $filter); 114 | } 115 | 116 | return $query->delete(); 117 | } 118 | 119 | /** 120 | * Repository data is added or removed as a whole block. 121 | * Must work or fail and rollback any persisted/erased data. 122 | * 123 | * @param callable $transaction 124 | * 125 | * @throws \Exception 126 | */ 127 | public function transactional(callable $transaction) 128 | { 129 | try { 130 | $transaction(); 131 | } catch (\Exception $e) { 132 | throw $e; 133 | } 134 | } 135 | } 136 | -------------------------------------------------------------------------------- /src/Infrastructure/Model/Repository/EloquentMongoDB/IdentityTrait.php: -------------------------------------------------------------------------------- 1 | 5 | * Date: 9/02/16 6 | * Time: 20:31. 7 | * 8 | * For the full copyright and license information, please view the LICENSE 9 | * file that was distributed with this source code. 10 | */ 11 | namespace NilPortugues\Foundation\Infrastructure\Model\Repository\EloquentMongoDB; 12 | 13 | /** 14 | * Class IdentityTrait. 15 | */ 16 | trait IdentityTrait 17 | { 18 | /** 19 | * @return string 20 | * @codeCoverageIgnore 21 | */ 22 | public function __toString() 23 | { 24 | return $this->id(); 25 | } 26 | 27 | /** 28 | * @return string 29 | */ 30 | public function id() 31 | { 32 | $id = $this->getKeyName(); 33 | 34 | return $this->attributes[$id]; 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /tests/Database.php: -------------------------------------------------------------------------------- 1 | id = 1; 17 | $client1->name = 'John Doe'; 18 | $client1->date = (new DateTime('2014-12-11'))->format('Y-m-d H:i:s'); 19 | $client1->totalOrders = 3; 20 | $client1->totalEarnings = 25.125; 21 | $client1->save(); 22 | 23 | $clientOrders1 = new ClientOrders(); 24 | $clientOrders1->client_id = $client1->id(); 25 | $clientOrders1->date = (new DateTime('2014-12-16'))->format('Y-m-d H:i:s'); 26 | $clientOrders1->save(); 27 | 28 | $clientOrders1 = new ClientOrders(); 29 | $clientOrders1->client_id = $client1->id(); 30 | $clientOrders1->date = (new DateTime('2014-12-31'))->format('Y-m-d H:i:s'); 31 | $clientOrders1->save(); 32 | 33 | $clientOrders1 = new ClientOrders(); 34 | $clientOrders1->client_id = $client1->id(); 35 | $clientOrders1->date = (new DateTime('2015-03-11'))->format('Y-m-d H:i:s'); 36 | $clientOrders1->save(); 37 | 38 | //---------------------------------------------------------------------------------- 39 | 40 | $client2 = new Clients(); 41 | $client2->id = 2; 42 | $client2->name = 'Junichi Masuda'; 43 | $client2->date = (new DateTime('2013-02-22'))->format('Y-m-d H:i:s'); 44 | $client2->totalOrders = 3; 45 | $client2->totalEarnings = 50978.125; 46 | $client2->save(); 47 | 48 | $clientOrders2 = new ClientOrders(); 49 | $clientOrders2->client_id = $client2->id(); 50 | $clientOrders2->date = (new DateTime('2014-04-16'))->format('Y-m-d H:i:s'); 51 | $clientOrders2->save(); 52 | 53 | $clientOrders2 = new ClientOrders(); 54 | $clientOrders2->client_id = $client2->id(); 55 | $clientOrders2->date = (new DateTime('2015-12-31'))->format('Y-m-d H:i:s'); 56 | $clientOrders2->save(); 57 | 58 | $clientOrders2 = new ClientOrders(); 59 | $clientOrders2->client_id = $client2->id(); 60 | $clientOrders2->date = (new DateTime('2016-04-31'))->format('Y-m-d H:i:s'); 61 | $clientOrders2->save(); 62 | //---------------------------------------------------------------------------------- 63 | 64 | $client3 = new Clients(); 65 | $client3->id = 3; 66 | $client3->name = 'Shigeru Miyamoto'; 67 | $client3->date = (new DateTime('2010-12-01'))->format('Y-m-d H:i:s'); 68 | $client3->totalOrders = 5; 69 | $client3->totalEarnings = 47889850.125; 70 | $client3->save(); 71 | 72 | $clientOrders3 = new ClientOrders(); 73 | $clientOrders3->client_id = $client3->id(); 74 | $clientOrders3->date = (new DateTime('1999-04-16'))->format('Y-m-d H:i:s'); 75 | $clientOrders3->save(); 76 | 77 | $clientOrders3 = new ClientOrders(); 78 | $clientOrders3->client_id = $client3->id(); 79 | $clientOrders3->date = (new DateTime('1996-02-04'))->format('Y-m-d H:i:s'); 80 | $clientOrders3->save(); 81 | 82 | $clientOrders3 = new ClientOrders(); 83 | $clientOrders3->client_id = $client3->id(); 84 | $clientOrders3->date = (new DateTime('1992-06-01'))->format('Y-m-d H:i:s'); 85 | $clientOrders3->save(); 86 | 87 | $clientOrders3 = new ClientOrders(); 88 | $clientOrders3->client_id = $client3->id(); 89 | $clientOrders3->date = (new DateTime('2000-03-01'))->format('Y-m-d H:i:s'); 90 | $clientOrders3->save(); 91 | 92 | $clientOrders3 = new ClientOrders(); 93 | $clientOrders3->client_id = $client3->id(); 94 | $clientOrders3->date = (new DateTime('2002-09-11'))->format('Y-m-d H:i:s'); 95 | $clientOrders3->save(); 96 | 97 | //---------------------------------------------------------------------------------- 98 | 99 | $client4 = new Clients(); 100 | $client4->id = 4; 101 | $client4->name = 'Ken Sugimori'; 102 | $client4->date = (new DateTime('2010-12-10'))->format('Y-m-d H:i:s'); 103 | $client4->totalOrders = 4; 104 | $client4->totalEarnings = 69158.687; 105 | $client4->save(); 106 | 107 | $clientOrders4 = new ClientOrders(); 108 | $clientOrders4->client_id = $client4->id(); 109 | $clientOrders4->date = (new DateTime('1996-06-30'))->format('Y-m-d H:i:s'); 110 | $clientOrders4->save(); 111 | 112 | $clientOrders4 = new ClientOrders(); 113 | $clientOrders4->client_id = $client4->id(); 114 | $clientOrders4->date = (new DateTime('1992-09-25'))->format('Y-m-d H:i:s'); 115 | $clientOrders4->save(); 116 | 117 | $clientOrders4 = new ClientOrders(); 118 | $clientOrders4->client_id = $client4->id(); 119 | $clientOrders4->date = (new DateTime('2000-08-09'))->format('Y-m-d H:i:s'); 120 | $clientOrders4->save(); 121 | 122 | $clientOrders4 = new ClientOrders(); 123 | $clientOrders4->client_id = $client4->id(); 124 | $clientOrders4->date = (new DateTime('2002-07-15'))->format('Y-m-d H:i:s'); 125 | $clientOrders4->save(); 126 | } 127 | 128 | public static function dropAll() 129 | { 130 | Clients::query()->delete(); 131 | ClientOrders::query()->delete(); 132 | } 133 | } 134 | -------------------------------------------------------------------------------- /tests/Helpers/ClientId.php: -------------------------------------------------------------------------------- 1 | id = $id; 19 | } 20 | 21 | /** 22 | * @return mixed 23 | */ 24 | public function id() 25 | { 26 | return $this->id; 27 | } 28 | 29 | /** 30 | * @return string 31 | */ 32 | public function __toString() 33 | { 34 | return (string) $this->id; 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /tests/Helpers/ClientOrders.php: -------------------------------------------------------------------------------- 1 | belongsTo(Clients::class); 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /tests/Helpers/ClientOrdersRepository.php: -------------------------------------------------------------------------------- 1 | hasMany(ClientOrders::class); 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /tests/Helpers/ClientsRepository.php: -------------------------------------------------------------------------------- 1 | repository = new ClientsRepository(); 28 | Database::createAndPopulate(); 29 | } 30 | 31 | public function tearDown() 32 | { 33 | Database::dropAll(); 34 | } 35 | 36 | public function testItPageableFiltersAndDistinct() 37 | { 38 | $client1 = $this->repository->find(new ClientId(1)); 39 | $client1->name = 'Homer Simpson'; 40 | 41 | $client2 = $this->repository->find(new ClientId(2)); 42 | $client2->name = 'Homer Simpson'; 43 | 44 | $client3 = $this->repository->find(new ClientId(3)); 45 | $client3->name = 'Homer Simpson'; 46 | 47 | $client4 = $this->repository->find(new ClientId(4)); 48 | $client4->name = 'Homer Simpson'; 49 | 50 | $this->repository->addAll([$client1, $client2, $client3, $client4]); 51 | 52 | $distinctFields = new Fields(['name']); 53 | $pageable = new Pageable(1, 10, new Sort(['name'], new Order('DESC')), null, null, $distinctFields); 54 | 55 | $result = $this->repository->findAll($pageable); 56 | 57 | $this->assertEquals(1, count($result->content())); 58 | } 59 | 60 | public function testItCanRunSuccessfulTransaction() 61 | { 62 | $transaction = function () { 63 | $client1 = $this->repository->find(new ClientId(1)); 64 | $client1->name = 'Homer Simpson'; 65 | 66 | $client2 = $this->repository->find(new ClientId(2)); 67 | $client2->name = 'Homer Simpson'; 68 | 69 | $this->repository->addAll([$client1, $client2]); 70 | }; 71 | 72 | $this->repository->transactional($transaction); 73 | 74 | for ($i = 1; $i <= 2; ++$i) { 75 | $client = $this->repository->find(new ClientId($i)); 76 | $this->assertEquals('Homer Simpson', $client->name); 77 | } 78 | } 79 | 80 | public function testItCanFailTransactionAndThrowException() 81 | { 82 | $transaction = function () { 83 | $client1 = $this->repository->find(new ClientId(1)); 84 | $client1->name = 'Homer Simpson'; 85 | 86 | $client2 = $this->repository->find(new ClientId(2)); 87 | $client2->name = 'Homer Simpson'; 88 | 89 | $this->repository->addAll([$client1, $client2]); 90 | throw new \Exception('Just because'); 91 | }; 92 | 93 | $this->setExpectedException(Exception::class); 94 | $this->repository->transactional($transaction); 95 | } 96 | 97 | public function testItFindByDistinct() 98 | { 99 | $client1 = $this->repository->find(new ClientId(1)); 100 | $client1->name = 'Homer Simpson'; 101 | 102 | $client2 = $this->repository->find(new ClientId(2)); 103 | $client2->name = 'Homer Simpson'; 104 | 105 | $client3 = $this->repository->find(new ClientId(3)); 106 | $client3->name = 'Homer Simpson'; 107 | 108 | $client4 = $this->repository->find(new ClientId(4)); 109 | $client4->name = 'Homer Simpson'; 110 | 111 | $this->repository->addAll([$client1, $client2, $client3, $client4]); 112 | 113 | $distinctFields = new Fields(['name']); 114 | $filter = new Filter(); 115 | $filter->must()->notEmpty('name'); 116 | 117 | $results = $this->repository->findByDistinct( 118 | $distinctFields, 119 | $filter, 120 | new Sort(['name'], new Order('DESC')) 121 | ); 122 | 123 | $this->assertEquals(1, count($results)); 124 | } 125 | 126 | public function testItCanUpdateAnExistingClient() 127 | { 128 | $expected = $this->repository->find(new ClientId(4)); 129 | $expected->name = 'Homer Simpson'; 130 | $expected->date = (new DateTime('2010-12-10'))->format('Y-m-d H:i:s'); 131 | $expected->totalOrders = 4; 132 | $expected->totalEarnings = 69158.687; 133 | 134 | $client1 = $this->repository->add($expected); 135 | $this->assertEquals('Homer Simpson', $client1->name); 136 | 137 | $client1 = $this->repository->find(new ClientId(4)); 138 | $this->assertEquals('Homer Simpson', $client1->name); 139 | } 140 | 141 | public function testItCanUpdateAllClientsName() 142 | { 143 | $client1 = $this->repository->find(new ClientId(1)); 144 | $client1->name = 'Homer Simpson'; 145 | 146 | $client2 = $this->repository->find(new ClientId(2)); 147 | $client2->name = 'Homer Simpson'; 148 | 149 | $client3 = $this->repository->find(new ClientId(3)); 150 | $client3->name = 'Homer Simpson'; 151 | 152 | $client4 = $this->repository->find(new ClientId(4)); 153 | $client4->name = 'Homer Simpson'; 154 | 155 | $this->repository->addAll([$client1, $client2, $client3, $client4]); 156 | 157 | for ($i = 1; $i <= 4; ++$i) { 158 | $client = $this->repository->find(new ClientId($i)); 159 | $this->assertEquals('Homer Simpson', $client->name); 160 | } 161 | } 162 | 163 | public function testItCanFind() 164 | { 165 | /* @var Clients $client */ 166 | $id = new ClientId(1); 167 | $client = $this->repository->find($id); 168 | 169 | $this->assertInstanceOf(Clients::class, $client); 170 | $this->assertEquals(1, $client->id()); 171 | } 172 | 173 | public function testFindAll() 174 | { 175 | $result = $this->repository->findAll(); 176 | 177 | $this->assertInstanceOf(Page::class, $result); 178 | $this->assertEquals(4, count($result->content())); 179 | } 180 | 181 | public function testFindAllWithPageable() 182 | { 183 | $filter = new Filter(); 184 | $filter->must()->beGreaterThanOrEqual('id', 1); 185 | 186 | $pageable = new Pageable(2, 2, new Sort(['name'], new Order('DESC')), $filter); 187 | $result = $this->repository->findAll($pageable); 188 | 189 | $this->assertInstanceOf(Page::class, $result); 190 | $this->assertEquals(2, count($result->content())); 191 | } 192 | 193 | public function testCount() 194 | { 195 | $this->assertEquals(4, $this->repository->count()); 196 | } 197 | 198 | public function testCountWithFilter() 199 | { 200 | $filter = new Filter(); 201 | $filter->must()->contain('name', 'Ken'); 202 | 203 | $this->assertEquals(1, $this->repository->count($filter)); 204 | } 205 | 206 | public function testExists() 207 | { 208 | $this->assertTrue($this->repository->exists(new ClientId(1))); 209 | } 210 | 211 | public function testRemove() 212 | { 213 | $id = new ClientId(1); 214 | $this->repository->remove($id); 215 | $this->assertFalse($this->repository->exists($id)); 216 | } 217 | 218 | public function testRemoveAll() 219 | { 220 | $this->repository->removeAll(); 221 | $this->assertFalse($this->repository->exists(new ClientId(1))); 222 | } 223 | 224 | public function testRemoveAllWithFilter() 225 | { 226 | $filter = new Filter(); 227 | $filter->must()->contain('name', 'Doe'); 228 | 229 | $this->repository->removeAll($filter); 230 | $this->assertFalse($this->repository->exists(new ClientId(1))); 231 | } 232 | 233 | public function testFindByWithEmptyRepository() 234 | { 235 | $this->repository->removeAll(); 236 | 237 | $sort = new Sort(['name'], new Order('ASC')); 238 | $filter = new Filter(); 239 | $filter->must()->contain('name', 'Ken'); 240 | 241 | $this->assertEquals([], $this->repository->findBy($filter, $sort)); 242 | } 243 | 244 | public function testAdd() 245 | { 246 | $client = new Clients(); 247 | $client->id = 5; 248 | $client->name = 'Ken Sugimori'; 249 | $client->date = (new DateTime('2010-12-10'))->format('Y-m-d H:i:s'); 250 | $client->totalOrders = 4; 251 | $client->totalEarnings = 69158.687; 252 | 253 | $this->repository->add($client); 254 | 255 | $this->assertNotNull($this->repository->find(new ClientId(5))); 256 | } 257 | 258 | public function testFindReturnsNullIfNotFound() 259 | { 260 | $this->assertNull($this->repository->find(new ClientId(99999))); 261 | } 262 | 263 | public function testAddAll() 264 | { 265 | $client5 = new Clients(); 266 | $client5->id = 5; 267 | $client5->name = 'New Client 1'; 268 | $client5->date = (new DateTime('2010-12-10'))->format('Y-m-d H:i:s'); 269 | $client5->totalOrders = 4; 270 | $client5->totalEarnings = 69158.687; 271 | 272 | $client6 = new Clients(); 273 | $client6->id = 6; 274 | $client6->name = 'New Client 2'; 275 | $client6->date = (new DateTime('2010-12-10'))->format('Y-m-d H:i:s'); 276 | $client6->totalOrders = 4; 277 | $client6->totalEarnings = 69158.687; 278 | 279 | $clients = [$client5, $client6]; 280 | $this->repository->addAll($clients); 281 | 282 | $this->assertNotNull($this->repository->find(new ClientId(5))); 283 | $this->assertNotNull($this->repository->find(new ClientId(6))); 284 | } 285 | 286 | public function testAddAllRollbacks() 287 | { 288 | $this->setExpectedException(Exception::class); 289 | $clients = ['a', 'b']; 290 | $this->repository->addAll($clients); 291 | } 292 | 293 | public function testFind() 294 | { 295 | $expected = new Clients(); 296 | $expected->id = 4; 297 | $expected->name = 'Ken Sugimori'; 298 | $expected->date = (new DateTime('2010-12-10'))->format('Y-m-d H:i:s'); 299 | $expected->totalOrders = 4; 300 | $expected->totalEarnings = 69158.687; 301 | 302 | $this->assertEquals($expected->id(), $this->repository->find(new ClientId(4))->id()); 303 | } 304 | 305 | public function testFindBy() 306 | { 307 | $sort = new Sort(['name'], new Order('ASC')); 308 | 309 | $filter = new Filter(); 310 | $filter->must()->contain('name', 'Ken'); 311 | 312 | $expected = new Clients(); 313 | $expected->id = 4; 314 | $expected->name = 'Ken Sugimori'; 315 | $expected->date = (new DateTime('2010-12-10'))->format('Y-m-d H:i:s'); 316 | $expected->totalOrders = 4; 317 | $expected->totalEarnings = 69158.687; 318 | 319 | $result = $this->repository->findBy($filter, $sort); 320 | 321 | $this->assertNotEmpty($result); 322 | $this->assertEquals(1, count($result)); 323 | } 324 | 325 | //-------------------------------------------------------------------------------- 326 | // MUST FILTER TESTS 327 | //-------------------------------------------------------------------------------- 328 | 329 | public function testFindByWithMustEqual() 330 | { 331 | $filter = new Filter(); 332 | $filter->must()->equal('name', 'Ken Sugimori'); 333 | 334 | $fields = new Fields(['name']); 335 | $results = $this->repository->findBy($filter, null, $fields); 336 | 337 | $this->assertEquals(1, count($results)); 338 | foreach ($results as $result) { 339 | $this->assertTrue(false !== strpos($result['name'], 'Ken')); 340 | } 341 | } 342 | 343 | public function testFindByWithMustNotEqualTest() 344 | { 345 | $filter = new Filter(); 346 | $filter->must()->notEqual('name', 'Ken Sugimori'); 347 | 348 | $fields = new Fields(['name']); 349 | $results = $this->repository->findBy($filter, null, $fields); 350 | 351 | $this->assertEquals(3, count($results)); 352 | foreach ($results as $result) { 353 | $this->assertFalse(strpos($result['name'], 'Ken')); 354 | } 355 | } 356 | 357 | public function testFindByWithMustContain() 358 | { 359 | $filter = new Filter(); 360 | $filter->must()->contain('name', 'Ken'); 361 | 362 | $fields = new Fields(['name']); 363 | $results = $this->repository->findBy($filter, null, $fields); 364 | 365 | $this->assertEquals(1, count($results)); 366 | foreach ($results as $result) { 367 | $this->assertTrue(false !== strpos($result['name'], 'Ken')); 368 | } 369 | } 370 | 371 | public function testFindByWithMustNotContainTest() 372 | { 373 | $filter = new Filter(); 374 | $filter->must()->notContain('name', 'Ken'); 375 | 376 | $fields = new Fields(['name']); 377 | $results = $this->repository->findBy($filter, null, $fields); 378 | 379 | $this->assertEquals(3, count($results)); 380 | foreach ($results as $result) { 381 | $this->assertFalse(strpos($result['name'], 'Ken')); 382 | } 383 | } 384 | 385 | public function testFindByWithMustEndsWith() 386 | { 387 | $filter = new Filter(); 388 | $filter->must()->endsWith('name', 'mori'); 389 | 390 | $fields = new Fields(['name']); 391 | $results = $this->repository->findBy($filter, null, $fields); 392 | 393 | $this->assertEquals(1, count($results)); 394 | foreach ($results as $result) { 395 | $this->assertTrue(false !== strpos($result['name'], 'Ken')); 396 | } 397 | } 398 | 399 | public function testFindByWithMustStartsWith() 400 | { 401 | $filter = new Filter(); 402 | $filter->must()->startsWith('name', 'Ke'); 403 | 404 | $fields = new Fields(['name']); 405 | $results = $this->repository->findBy($filter, null, $fields); 406 | 407 | $this->assertEquals(1, count($results)); 408 | foreach ($results as $result) { 409 | $this->assertTrue(false !== strpos($result['name'], 'Ken')); 410 | } 411 | } 412 | 413 | public function testFindByWithMustBeLessThan() 414 | { 415 | $filter = new Filter(); 416 | $filter->must()->beLessThan('totalOrders', 6); 417 | 418 | $fields = new Fields(['name']); 419 | $results = $this->repository->findBy($filter, null, $fields); 420 | 421 | $this->assertEquals(4, count($results)); 422 | } 423 | 424 | public function testFindByWithMustBeLessThanOrEqual() 425 | { 426 | $filter = new Filter(); 427 | $filter->must()->beLessThanOrEqual('totalOrders', 4); 428 | 429 | $fields = new Fields(['name']); 430 | $results = $this->repository->findBy($filter, null, $fields); 431 | 432 | $this->assertEquals(3, count($results)); 433 | } 434 | 435 | public function testFindByWithMustBeGreaterThan() 436 | { 437 | $filter = new Filter(); 438 | $filter->must()->beGreaterThan('totalOrders', 2); 439 | 440 | $fields = new Fields(['name']); 441 | $results = $this->repository->findBy($filter, null, $fields); 442 | 443 | $this->assertEquals(4, count($results)); 444 | } 445 | 446 | public function testFindByWithMustBeGreaterThanOrEqual() 447 | { 448 | $filter = new Filter(); 449 | $filter->must()->beGreaterThanOrEqual('totalOrders', 2); 450 | 451 | $fields = new Fields(['name']); 452 | $results = $this->repository->findBy($filter, null, $fields); 453 | 454 | $this->assertEquals(4, count($results)); 455 | } 456 | 457 | public function testFindByMustIncludeGroup() 458 | { 459 | $filter = new Filter(); 460 | $filter->must()->includeGroup('date', ['2010-12-01 00:00:00', '2010-12-10 00:00:00', '2013-02-22 00:00:00']); 461 | 462 | $results = $this->repository->findBy($filter); 463 | 464 | $this->assertEquals(3, count($results)); 465 | } 466 | 467 | public function testFindByMustNotIncludeGroupTest() 468 | { 469 | $filter = new Filter(); 470 | $filter->must()->notIncludeGroup('date', ['2010-12-01 00:00:00', '2010-12-10 00:00:00', '2013-02-22 00:00:00']); 471 | 472 | $results = $this->repository->findBy($filter); 473 | 474 | $this->assertEquals(1, count($results)); 475 | } 476 | 477 | public function testFindByMustRange() 478 | { 479 | $filter = new Filter(); 480 | $filter->must()->range('totalOrders', 2, 4); 481 | 482 | $results = $this->repository->findBy($filter); 483 | 484 | $this->assertEquals(3, count($results)); 485 | } 486 | 487 | public function testFindByMustNotRangeTest() 488 | { 489 | $filter = new Filter(); 490 | $filter->must()->notRange('totalOrders', 2, 4); 491 | 492 | $results = $this->repository->findBy($filter); 493 | $this->assertEquals(2, count($results)); 494 | } 495 | 496 | //-------------------------------------------------------------------------------- 497 | // MUST NOT FILTER TESTS 498 | //-------------------------------------------------------------------------------- 499 | 500 | 501 | public function testFindByWithMustNotEqual() 502 | { 503 | $filter = new Filter(); 504 | $filter->mustNot()->equal('name', 'Ken Sugimori'); 505 | 506 | $fields = new Fields(['name']); 507 | $results = $this->repository->findBy($filter, null, $fields); 508 | 509 | $this->assertEquals(3, count($results)); 510 | foreach ($results as $result) { 511 | $this->assertFalse(strpos($result['name'], 'Ken')); 512 | } 513 | } 514 | 515 | public function testFindByWithMustNotNotEqual() 516 | { 517 | $filter = new Filter(); 518 | $filter->mustNot()->notEqual('name', 'Ken Sugimori'); 519 | 520 | $fields = new Fields(['name']); 521 | $results = $this->repository->findBy($filter, null, $fields); 522 | 523 | $this->assertEquals(1, count($results)); 524 | foreach ($results as $result) { 525 | $this->assertTrue(false !== strpos($result['name'], 'Ken')); 526 | } 527 | } 528 | 529 | public function testFindByWithMustNotContain() 530 | { 531 | $filter = new Filter(); 532 | $filter->mustNot()->contain('name', 'Ken'); 533 | 534 | $fields = new Fields(['name']); 535 | $results = $this->repository->findBy($filter, null, $fields); 536 | 537 | $this->assertEquals(3, count($results)); 538 | foreach ($results as $result) { 539 | $this->assertFalse(strpos($result['name'], 'Ken')); 540 | } 541 | } 542 | 543 | public function testFindByWithMustNotNotContain() 544 | { 545 | $filter = new Filter(); 546 | $filter->mustNot()->notContain('name', 'Ken'); 547 | 548 | $fields = new Fields(['name']); 549 | $results = $this->repository->findBy($filter, null, $fields); 550 | 551 | $this->assertEquals(1, count($results)); 552 | foreach ($results as $result) { 553 | $this->assertTrue(false !== strpos($result['name'], 'Ken')); 554 | } 555 | } 556 | 557 | public function testFindByWithMustNotEndsWith() 558 | { 559 | $filter = new Filter(); 560 | $filter->mustNot()->endsWith('name', 'mori'); 561 | 562 | $fields = new Fields(['name']); 563 | $results = $this->repository->findBy($filter, null, $fields); 564 | 565 | $this->assertEquals(3, count($results)); 566 | foreach ($results as $result) { 567 | $this->assertFalse(strpos($result['name'], 'Ken')); 568 | } 569 | } 570 | 571 | public function testFindByWithMustNotStartsWith() 572 | { 573 | $filter = new Filter(); 574 | $filter->mustNot()->startsWith('name', 'Ke'); 575 | 576 | $fields = new Fields(['name']); 577 | $results = $this->repository->findBy($filter, null, $fields); 578 | 579 | $this->assertEquals(3, count($results)); 580 | foreach ($results as $result) { 581 | $this->assertFalse(strpos($result['name'], 'Ken')); 582 | } 583 | } 584 | 585 | public function testFindByWithMustNotBeLessThan() 586 | { 587 | $filter = new Filter(); 588 | $filter->mustNot()->beLessThan('totalOrders', 2); 589 | 590 | $results = $this->repository->findBy($filter); 591 | 592 | $this->assertEquals(4, count($results)); 593 | } 594 | 595 | public function testFindByWithMustNotBeLessThanOrEqual() 596 | { 597 | $filter = new Filter(); 598 | $filter->mustNot()->beLessThanOrEqual('totalOrders', 4); 599 | 600 | $results = $this->repository->findBy($filter); 601 | 602 | $this->assertEquals(1, count($results)); 603 | } 604 | 605 | public function testFindByWithMustNotBeGreaterThan() 606 | { 607 | $filter = new Filter(); 608 | $filter->mustNot()->beGreaterThan('totalOrders', 6); 609 | 610 | $results = $this->repository->findBy($filter); 611 | 612 | $this->assertEquals(4, count($results)); 613 | } 614 | 615 | public function testFindByWithMustNotBeGreaterThanOrEqual() 616 | { 617 | $filter = new Filter(); 618 | $filter->mustNot()->beGreaterThanOrEqual('totalOrders', 6); 619 | 620 | $results = $this->repository->findBy($filter); 621 | 622 | $this->assertEquals(4, count($results)); 623 | } 624 | 625 | public function testFindByMustNotIncludeGroup() 626 | { 627 | $filter = new Filter(); 628 | $filter->mustNot()->includeGroup('date', ['2010-12-01 00:00:00', '2010-12-10 00:00:00', '2013-02-22 00:00:00']); 629 | 630 | $results = $this->repository->findBy($filter); 631 | 632 | $this->assertEquals(1, count($results)); 633 | } 634 | 635 | public function testFindByMustNotNotIncludeGroup() 636 | { 637 | $filter = new Filter(); 638 | $filter->mustNot()->notIncludeGroup('date', 639 | ['2010-12-01 00:00:00', '2010-12-10 00:00:00', '2013-02-22 00:00:00']); 640 | 641 | $results = $this->repository->findBy($filter); 642 | 643 | $this->assertEquals(3, count($results)); 644 | } 645 | 646 | public function testFindByMustNotRange() 647 | { 648 | $filter = new Filter(); 649 | $filter->mustNot()->range('totalOrders', 2, 4); 650 | $results = $this->repository->findBy($filter); 651 | $this->assertEquals(2, count($results)); 652 | } 653 | 654 | public function testFindByMustNotNotRangeTest() 655 | { 656 | $filter = new Filter(); 657 | $filter->mustNot()->notRange('totalOrders', 2, 4); 658 | 659 | $results = $this->repository->findBy($filter); 660 | $this->assertEquals(3, count($results)); 661 | } 662 | 663 | //-------------------------------------------------------------------------------- 664 | // SHOULD FILTER TESTS 665 | //-------------------------------------------------------------------------------- 666 | 667 | public function testFindByWithShouldEqual() 668 | { 669 | $filter = new Filter(); 670 | $filter->must()->contain('name', 'Hideo Kojima'); 671 | $filter->should()->equal('name', 'Ken Sugimori'); 672 | 673 | $fields = new Fields(['name']); 674 | $results = $this->repository->findBy($filter, null, $fields); 675 | 676 | $this->assertEquals(1, count($results)); 677 | } 678 | 679 | public function testFindByShouldContain() 680 | { 681 | $filter = new Filter(); 682 | $filter->must()->contain('name', 'Hideo Kojima'); 683 | $filter->should()->contain('name', 'Ken'); 684 | 685 | $fields = new Fields(['name']); 686 | $results = $this->repository->findBy($filter, null, $fields); 687 | 688 | $this->assertEquals(1, count($results)); 689 | } 690 | 691 | public function testFindByShouldNotContainTest() 692 | { 693 | $filter = new Filter(); 694 | $filter->must()->contain('name', 'Hideo Kojima'); 695 | $filter->should()->notContain('name', 'Ken'); 696 | 697 | $fields = new Fields(['name']); 698 | $results = $this->repository->findBy($filter, null, $fields); 699 | 700 | $this->assertEquals(3, count($results)); 701 | } 702 | 703 | public function testFindByShouldEndsWith() 704 | { 705 | $filter = new Filter(); 706 | $filter->must()->contain('name', 'Hideo Kojima'); 707 | $filter->should()->endsWith('name', 'mori'); 708 | 709 | $fields = new Fields(['name']); 710 | $results = $this->repository->findBy($filter, null, $fields); 711 | 712 | $this->assertEquals(1, count($results)); 713 | } 714 | 715 | public function testFindByShouldStartsWith() 716 | { 717 | $filter = new Filter(); 718 | $filter->must()->contain('name', 'Hideo Kojima'); 719 | $filter->should()->startsWith('name', 'Ke'); 720 | 721 | $fields = new Fields(['name']); 722 | $results = $this->repository->findBy($filter, null, $fields); 723 | 724 | $this->assertEquals(1, count($results)); 725 | } 726 | 727 | public function testFindByShouldBeLessThan() 728 | { 729 | $filter = new Filter(); 730 | $filter->must()->contain('name', 'Hideo Kojima'); 731 | $filter->should()->beLessThan('totalOrders', 6); 732 | 733 | $fields = new Fields(['name']); 734 | $results = $this->repository->findBy($filter, null, $fields); 735 | 736 | $this->assertEquals(4, count($results)); 737 | } 738 | 739 | public function testFindByShouldBeLessThanOrEqual() 740 | { 741 | $filter = new Filter(); 742 | $filter->must()->contain('name', 'Hideo Kojima'); 743 | $filter->should()->beLessThanOrEqual('totalOrders', 4); 744 | 745 | $fields = new Fields(['name']); 746 | $results = $this->repository->findBy($filter, null, $fields); 747 | 748 | $this->assertEquals(3, count($results)); 749 | } 750 | 751 | public function testFindByShouldBeGreaterThan() 752 | { 753 | $filter = new Filter(); 754 | $filter->must()->contain('name', 'Hideo Kojima'); 755 | $filter->should()->beGreaterThan('totalOrders', 2); 756 | 757 | $fields = new Fields(['name']); 758 | $results = $this->repository->findBy($filter, null, $fields); 759 | 760 | $this->assertEquals(4, count($results)); 761 | } 762 | 763 | public function testFindByShouldBeGreaterThanOrEqual() 764 | { 765 | $filter = new Filter(); 766 | $filter->must()->contain('name', 'Hideo Kojima'); 767 | $filter->should()->beGreaterThanOrEqual('totalOrders', 2); 768 | 769 | $fields = new Fields(['name']); 770 | $results = $this->repository->findBy($filter, null, $fields); 771 | 772 | $this->assertEquals(4, count($results)); 773 | } 774 | 775 | public function testFindByShouldIncludeGroup() 776 | { 777 | $filter = new Filter(); 778 | $filter->must()->contain('name', 'Hideo Kojima'); 779 | $filter->should()->includeGroup('date', ['2010-12-01 00:00:00', '2010-12-10 00:00:00', '2013-02-22 00:00:00']); 780 | 781 | $results = $this->repository->findBy($filter); 782 | 783 | $this->assertEquals(3, count($results)); 784 | } 785 | 786 | public function testFindByShouldNotIncludeGroupTest() 787 | { 788 | $filter = new Filter(); 789 | $filter->must()->contain('name', 'Hideo Kojima'); 790 | $filter->should()->notIncludeGroup('date', ['2010-12-01 00:00:00', '2010-12-10 00:00:00', '2013-02-22 00:00:00']); 791 | 792 | $results = $this->repository->findBy($filter); 793 | 794 | $this->assertEquals(1, count($results)); 795 | } 796 | 797 | public function testFindByShouldRange() 798 | { 799 | $filter = new Filter(); 800 | $filter->must()->contain('name', 'Hideo Kojima'); 801 | $filter->should()->range('totalOrders', 2, 4); 802 | 803 | $results = $this->repository->findBy($filter); 804 | 805 | $this->assertEquals(3, count($results)); 806 | } 807 | 808 | public function testFindByShouldNotRangeTest() 809 | { 810 | $filter = new Filter(); 811 | $filter->must()->contain('name', 'Hideo Kojima'); 812 | $filter->should()->notRange('totalOrders', 2, 4); 813 | 814 | $results = $this->repository->findBy($filter); 815 | 816 | $this->assertEquals(2, count($results)); 817 | } 818 | } 819 | -------------------------------------------------------------------------------- /tests/autoload.php: -------------------------------------------------------------------------------- 1 | getDatabaseManager()->extend('mongodb', function ($config) { 11 | return new Jenssegers\Mongodb\Connection($config); 12 | }); 13 | 14 | //Create connection 15 | $capsule->addConnection([ 16 | 'driver' => 'mongodb', 17 | 'host' => 'localhost', 18 | 'port' => 27017, 19 | 'database' => 'default', 20 | 'options' => [ 21 | 'db' => 'admin', 22 | ], 23 | ], 24 | 'default' 25 | ); 26 | $capsule->bootEloquent(); 27 | $capsule->setAsGlobal(); 28 | --------------------------------------------------------------------------------