├── .travis.ini ├── tests ├── Model │ ├── Book.php │ ├── Info.php │ ├── User.php │ ├── Image.php │ ├── Author.php │ ├── Cached.php │ ├── Source.php │ ├── Article.php │ ├── Comment.php │ ├── Message.php │ ├── Category.php │ ├── BookQuery.php │ ├── UserQuery.php │ ├── ArticleVote.php │ ├── EventsQuery.php │ ├── ImageQuery.php │ ├── TextElement.php │ ├── AuthorQuery.php │ ├── CachedQuery.php │ ├── SimpleDocument.php │ ├── ABIdGenerator.php │ ├── ArticleQuery.php │ ├── CategoryQuery.php │ ├── ComplexDocument.php │ ├── ComplexEmbedded.php │ ├── ElementQuery.php │ ├── MessageQuery.php │ ├── SimpleEmbedded.php │ ├── BookRepository.php │ ├── NoneIdGenerator.php │ ├── UserRepository.php │ ├── CircularReference.php │ ├── ConnectionGlobal.php │ ├── EventsRepository.php │ ├── ImageRepository.php │ ├── RadioFormElement.php │ ├── ArticleVoteQuery.php │ ├── AuthorRepository.php │ ├── CachedRepository.php │ ├── FieldTypeExamples.php │ ├── FormElementQuery.php │ ├── NativeIdGenerator.php │ ├── TextElementQuery.php │ ├── ABIdGeneratorQuery.php │ ├── ArticleInformation.php │ ├── ArticleRepository.php │ ├── CategoryRepository.php │ ├── CommentRepository.php │ ├── ElementRepository.php │ ├── MessageRepository.php │ ├── SequenceIdGenerator.php │ ├── SimpleDocumentQuery.php │ ├── ComplexDocumentQuery.php │ ├── InitializeArgsQuery.php │ ├── SequenceIdGenerator2.php │ ├── SimpleEmbeddedQuery.php │ ├── CircularReferenceQuery.php │ ├── NoneIdGeneratorQuery.php │ ├── TextTextElementQuery.php │ ├── ArticleVoteRepository.php │ ├── ConnectionGlobalQuery.php │ ├── FormElementRepository.php │ ├── RadioFormElementQuery.php │ ├── TextElementRepository.php │ ├── ABIdGeneratorRepository.php │ ├── ArticleInformationQuery.php │ ├── FieldTypeExamplesQuery.php │ ├── NativeIdGeneratorQuery.php │ ├── SequenceIdGeneratorStart.php │ ├── SimpleDocumentRepository.php │ ├── ComplexDocumentRepository.php │ ├── InitializeArgsRepository.php │ ├── SequenceIdGeneratorQuery.php │ ├── SimpleEmbeddedRepository.php │ ├── TextareaFormElementQuery.php │ ├── CircularReferenceRepository.php │ ├── NoneIdGeneratorRepository.php │ ├── SequenceIdGenerator2Query.php │ ├── TextTextElementRepository.php │ ├── ConnectionGlobalRepository.php │ ├── RadioFormElementRepository.php │ ├── ArticleInformationRepository.php │ ├── FieldTypeExamplesRepository.php │ ├── NativeIdGeneratorRepository.php │ ├── SequenceIdGeneratorDescending.php │ ├── SequenceIdGeneratorRepository.php │ ├── SequenceIdGeneratorStartQuery.php │ ├── TextareaFormElementRepository.php │ ├── SequenceIdGenerator2Repository.php │ ├── IdGeneratorSingleInheritanceChild.php │ ├── IdGeneratorSingleInheritanceParent.php │ ├── SequenceIdGeneratorDescendingQuery.php │ ├── SequenceIdGeneratorStartRepository.php │ ├── IdGeneratorSingleInheritanceChildQuery.php │ ├── IdGeneratorSingleInheritanceGrandParent.php │ ├── IdGeneratorSingleInheritanceParentQuery.php │ ├── SequenceIdGeneratorDescendingRepository.php │ ├── InitializeArgs.php │ ├── IdGeneratorSingleInheritanceChildRepository.php │ ├── IdGeneratorSingleInheritanceGrandParentQuery.php │ ├── IdGeneratorSingleInheritanceParentRepository.php │ ├── TextTextElement.php │ ├── IdGeneratorSingleInheritanceGrandParentRepository.php │ ├── FormElement.php │ ├── TextareaFormElement.php │ ├── Element.php │ └── Events.php ├── Mongator │ ├── Tests │ │ ├── Cache │ │ │ ├── ArrayCacheTest.php │ │ │ ├── RedisCacheTest.php │ │ │ ├── FilesystemCacheTest.php │ │ │ ├── APCCacheTest.php │ │ │ └── MemcachedCacheTest.php │ │ ├── Id │ │ │ ├── ABId.php │ │ │ ├── ABIdGenerator.php │ │ │ └── IdGeneratorContainerTest.php │ │ ├── Type │ │ │ ├── TestCase.php │ │ │ ├── StringTypeTest.php │ │ │ ├── IntegerTypeTest.php │ │ │ ├── FloatTypeTest.php │ │ │ ├── BooleanTypeTest.php │ │ │ ├── SerializedTypeTest.php │ │ │ ├── RawTypeTest.php │ │ │ ├── BinDataTypeTest.php │ │ │ ├── DateTypeTest.php │ │ │ └── ContainerTest.php │ │ ├── Logger │ │ │ ├── TimeTest.php │ │ │ ├── LoggableMongoCursorTest.php │ │ │ ├── LoggableMongoGridFSCursorTest.php │ │ │ ├── LoggableMongoCollectionTest.php │ │ │ ├── LoggableMongoGridFSTest.php │ │ │ ├── LoggableMongoTest.php │ │ │ └── LoggableMongoDBTest.php │ │ ├── Group │ │ │ ├── ReferenceGroupTest.php │ │ │ ├── GroupTest.php │ │ │ ├── PolymorphicGroupTest.php │ │ │ └── PolymorphicReferenceGroupTest.php │ │ ├── Extension │ │ │ ├── DocumentPropertyOverloadingTest.php │ │ │ ├── DocumentArrayAccessTest.php │ │ │ ├── CoreRepositoryFixMissingReferencesTest.php │ │ │ └── CoreMetadataTest.php │ │ ├── ArchiveTest.php │ │ ├── IdentityMapTest.php │ │ ├── Query │ │ │ ├── CachedQueryTest.php │ │ │ └── ResultTest.php │ │ └── IndexManagerTest.php │ └── Benchmarks │ │ ├── DeletingEvent.php │ │ ├── InsertingEvent.php │ │ ├── UpdatingEvent.php │ │ └── FindingEvent.php └── bootstrap.php ├── .travis.sh ├── .gitignore ├── src └── Mongator │ ├── Query │ ├── ChunkInterface.php │ ├── ChunkResult.php │ ├── CachedQuery.php │ ├── Chunk.php │ └── Result.php │ ├── Extension │ ├── templates │ │ ├── Core │ │ │ ├── DocumentEventsMethods.php.twig │ │ │ ├── DocumentSetDefaults.php.twig │ │ │ ├── Document.php.twig │ │ │ ├── DocumentResetGroups.php.twig │ │ │ ├── DocumentEmbeddedsMany.php.twig │ │ │ ├── DocumentRelations.php.twig │ │ │ ├── DocumentSaveReferences.php.twig │ │ │ ├── DocumentReferencesMany.php.twig │ │ │ ├── DocumentSetDocumentData.php.twig │ │ │ ├── DocumentProcessOnDelete.php.twig │ │ │ ├── DocumentFields.php.twig │ │ │ └── DocumentEmbeddedsOne.php.twig │ │ ├── DocumentPropertyOverloading.php.twig │ │ └── DocumentArrayAccess.php.twig │ ├── DocumentPropertyOverloading.php │ └── DocumentArrayAccess.php │ ├── Document │ └── Event.php │ ├── ConnectionInterface.php │ ├── Id │ ├── NativeIdGenerator.php │ ├── NoneIdGenerator.php │ ├── BaseIdGenerator.php │ ├── SequenceIdGenerator.php │ └── IdGeneratorContainer.php │ ├── Type │ ├── RawType.php │ ├── FloatType.php │ ├── IntegerType.php │ ├── BooleanType.php │ ├── StringType.php │ ├── SerializedType.php │ ├── ArrayObjectType.php │ ├── BinDataType.php │ ├── Type.php │ ├── ObjectType.php │ ├── ArrayType.php │ └── DateType.php │ ├── Group │ ├── Group.php │ ├── PolymorphicGroup.php │ ├── ReferenceGroup.php │ ├── EmbeddedGroup.php │ └── PolymorphicReferenceGroup.php │ ├── UnitOfWorkInterface.php │ ├── Cache │ ├── ArrayCache.php │ ├── APCCache.php │ ├── MemcachedCache.php │ ├── RedisCache.php │ ├── FilesystemCache.php │ └── AbstractCache.php │ ├── IdentityMapInterface.php │ ├── IdentityMap.php │ └── Archive.php ├── .travis.yml ├── phpunit.xml.dist ├── LICENSE └── composer.json /.travis.ini: -------------------------------------------------------------------------------- 1 | extension=redis.so 2 | extension=memcached.so 3 | 4 | extension=apc.so 5 | apc.enabled=1 6 | apc.enable_cli=1 -------------------------------------------------------------------------------- /tests/Model/Book.php: -------------------------------------------------------------------------------- 1 | setAuthor($author); 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /tests/Model/IdGeneratorSingleInheritanceChildRepository.php: -------------------------------------------------------------------------------- 1 | events[] = 'TextTextElementPreInsert'; 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /tests/Model/IdGeneratorSingleInheritanceGrandParentRepository.php: -------------------------------------------------------------------------------- 1 | {{ method }}(); 10 | {% endfor %} 11 | 12 | parent::{{ event }}Event(); 13 | } 14 | {% endif %} 15 | {% endfor %} 16 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: php 2 | 3 | php: 4 | - 5.3 5 | - 5.4 6 | - 5.5 7 | - 5.6 8 | 9 | env: 10 | - MONGO_VERSION=1.4.5 11 | - MONGO_VERSION=1.3.6 12 | 13 | services: 14 | - mongodb 15 | - redis-server 16 | 17 | before_script: 18 | - printf "\n" | pecl install -f mongo-${MONGO_VERSION} 19 | - /bin/bash ./.travis.sh 20 | - composer --dev --prefer-source install 21 | - phpenv config-add ./.travis.ini 22 | - phpenv rehash 23 | 24 | script: phpunit 25 | -------------------------------------------------------------------------------- /phpunit.xml.dist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 8 | 9 | 10 | ./tests/ 11 | 12 | 13 | 14 | 15 | 16 | ./src 17 | 18 | 19 | 20 | -------------------------------------------------------------------------------- /src/Mongator/Extension/templates/Core/DocumentSetDefaults.php.twig: -------------------------------------------------------------------------------- 1 | get{{ name|ucfirst }}() === null || !isset($this->data['fields']['{{ name }}'])) { 11 | $this->set{{ name|ucfirst }}({{ field.default|var_export }}); 12 | } 13 | 14 | {% endif %} 15 | {% endfor %} 16 | } 17 | -------------------------------------------------------------------------------- /tests/Mongator/Tests/Cache/ArrayCacheTest.php: -------------------------------------------------------------------------------- 1 | 7 | * 8 | * This source file is subject to the MIT license that is bundled 9 | * with this source code in the file LICENSE. 10 | */ 11 | 12 | namespace Mongator\Tests\Cache; 13 | 14 | use Mongator\Cache\ArrayCache; 15 | 16 | class ArrayCacheTest extends Cache 17 | { 18 | protected function getCacheDriver() 19 | { 20 | return new ArrayCache(); 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /src/Mongator/Query/ChunkResult.php: -------------------------------------------------------------------------------- 1 | total = $total; 11 | } 12 | 13 | public function getData() { return $this->getArrayCopy(); } 14 | public function getTotal() 15 | { 16 | if ($this->total instanceOf \Closure) { 17 | $this->total = $this->total->__invoke(); 18 | } 19 | 20 | return $this->total; 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /tests/Mongator/Tests/Id/ABId.php: -------------------------------------------------------------------------------- 1 | a = new ObjectID(); 16 | $this->b = new ObjectID(); 17 | } else { 18 | $this->a = $id['a']; 19 | $this->b = $id['b']; 20 | } 21 | } 22 | 23 | public function __toString() 24 | { 25 | return sprintf('a:%s:b:%s', $this->a, $this->b); 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /tests/Mongator/Tests/Id/ABIdGenerator.php: -------------------------------------------------------------------------------- 1 | eventPattern = '{{ config_class.eventPattern }}'; 25 | 26 | parent::__construct($mongator); 27 | } 28 | -------------------------------------------------------------------------------- /tests/Mongator/Tests/Type/TestCase.php: -------------------------------------------------------------------------------- 1 | 7 | * 8 | * This source file is subject to the MIT license that is bundled 9 | * with this source code in the file LICENSE. 10 | */ 11 | 12 | namespace Mongator\Tests\Type; 13 | 14 | use Mongator\Tests\TestCase as BaseTestCase; 15 | 16 | abstract class TestCase extends BaseTestCase 17 | { 18 | protected function getTypeFunction($string) 19 | { 20 | eval('$function = function($from) { '.strtr($string, array( 21 | '%from%' => '$from', 22 | '%to%' => '$to', 23 | )).' return $to; };'); 24 | 25 | return $function; 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /tests/Mongator/Tests/Logger/TimeTest.php: -------------------------------------------------------------------------------- 1 | 7 | * 8 | * This source file is subject to the MIT license that is bundled 9 | * with this source code in the file LICENSE. 10 | */ 11 | 12 | namespace Mongator\Tests\Logger; 13 | 14 | use Mongator\Logger\Time; 15 | 16 | class TimeTest extends \PHPUnit\Framework\TestCase 17 | { 18 | public function testTime() 19 | { 20 | if (!class_exists('Mongator\Logger\Time')) { 21 | $this->markTestSkipped('Mongator\Logger\Time is not available.'); 22 | } 23 | 24 | $time = new Time(); 25 | $time->start(); 26 | 27 | $this->assertTrue(is_int($time->stop())); 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /tests/Mongator/Tests/Group/ReferenceGroupTest.php: -------------------------------------------------------------------------------- 1 | 7 | * 8 | * This source file is subject to the MIT license that is bundled 9 | * with this source code in the file LICENSE. 10 | */ 11 | 12 | namespace Mongator\Tests\Group; 13 | 14 | use Mongator\Tests\TestCase; 15 | use Mongator\Group\ReferenceGroup; 16 | 17 | class ReferenceGroupTest extends TestCase 18 | { 19 | public function testConstructor() 20 | { 21 | $group = new ReferenceGroup('Model\Category', $article = $this->mongator->create('Model\Article'), 'category_ids'); 22 | $this->assertSame($article, $group->getParent()); 23 | $this->assertSame('category_ids', $group->getField()); 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /src/Mongator/Extension/templates/DocumentPropertyOverloading.php.twig: -------------------------------------------------------------------------------- 1 | set($name, $value); 14 | } 15 | 16 | /** 17 | * Returns data of the document. 18 | * 19 | * @param string $name The data name. 20 | * 21 | * @return mixed Some data. 22 | * 23 | * @throws \InvalidArgumentException If the data name does not exists. 24 | */ 25 | public function __get($name) 26 | { 27 | return $this->get($name); 28 | } 29 | -------------------------------------------------------------------------------- /tests/Mongator/Benchmarks/DeletingEvent.php: -------------------------------------------------------------------------------- 1 | 7 | * 8 | * This source file is subject to the MIT license that is bundled 9 | * with this source code in the file LICENSE. 10 | */ 11 | 12 | namespace Mongator\Benchmarks; 13 | 14 | class DeletingEvent extends AthleticEvent 15 | { 16 | public function setUp(): void 17 | { 18 | parent::setUp(); 19 | $this->simpleDocument = $this->buildSimpleDocument()->save(); 20 | } 21 | 22 | /** 23 | * @iterations 500 24 | */ 25 | public function simpleDocument() 26 | { 27 | $this 28 | ->getRepository(self::SIMPLE_DOCUMENT_CLASS) 29 | ->delete($this->simpleDocument); 30 | } 31 | } -------------------------------------------------------------------------------- /src/Mongator/Extension/DocumentPropertyOverloading.php: -------------------------------------------------------------------------------- 1 | 7 | * 8 | * This source file is subject to the MIT license that is bundled 9 | * with this source code in the file LICENSE. 10 | */ 11 | 12 | namespace Mongator\Extension; 13 | 14 | use Mandango\Mondator\Extension; 15 | 16 | /** 17 | * DocumentPropertyOverloading extension. 18 | * 19 | * @author Pablo Díez 20 | */ 21 | class DocumentPropertyOverloading extends Extension 22 | { 23 | /** 24 | * {@inheritdoc} 25 | */ 26 | protected function doClassProcess() 27 | { 28 | $this->processTemplate($this->definitions['document_base'], file_get_contents(__DIR__.'/templates/DocumentPropertyOverloading.php.twig')); 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /tests/Mongator/Tests/Group/GroupTest.php: -------------------------------------------------------------------------------- 1 | 7 | * 8 | * This source file is subject to the MIT license that is bundled 9 | * with this source code in the file LICENSE. 10 | */ 11 | 12 | namespace Mongator\Tests\Group; 13 | 14 | use Mongator\Tests\TestCase; 15 | use Mongator\Group\Group as BaseGroup; 16 | 17 | class Group extends BaseGroup 18 | { 19 | public $forSaved = array(); 20 | 21 | protected function doInitializeSavedData() 22 | { 23 | return $this->forSaved; 24 | } 25 | } 26 | 27 | class GroupTest extends TestCase 28 | { 29 | public function testConstructor() 30 | { 31 | $group = new Group('Model\Comment'); 32 | $this->assertSame('Model\Comment', $group->getDocumentClass()); 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /src/Mongator/Extension/DocumentArrayAccess.php: -------------------------------------------------------------------------------- 1 | 7 | * 8 | * This source file is subject to the MIT license that is bundled 9 | * with this source code in the file LICENSE. 10 | */ 11 | 12 | namespace Mongator\Extension; 13 | 14 | use Mandango\Mondator\Extension; 15 | 16 | /** 17 | * DocumentArrayAccess extension. 18 | * 19 | * @author Pablo Díez 20 | */ 21 | class DocumentArrayAccess extends Extension 22 | { 23 | /** 24 | * {@inheritdoc} 25 | */ 26 | protected function doClassProcess() 27 | { 28 | $this->definitions['document_base']->addInterface('\ArrayAccess'); 29 | 30 | $this->processTemplate($this->definitions['document_base'], file_get_contents(__DIR__.'/templates/DocumentArrayAccess.php.twig')); 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /src/Mongator/Document/Event.php: -------------------------------------------------------------------------------- 1 | 7 | * (c) Eduardo Gulias 8 | * 9 | * This source file is subject to the MIT license that is bundled 10 | * with this source code in the file LICENSE. 11 | */ 12 | 13 | namespace Mongator\Document; 14 | 15 | use Symfony\Contracts\EventDispatcher\Event as BaseEvent; 16 | 17 | /** 18 | * The Event class for documents. 19 | * 20 | * @author Máximo Cuadros 21 | * @author Eduardo Gulias 22 | * 23 | * @api 24 | */ 25 | class Event extends BaseEvent 26 | { 27 | private $document; 28 | 29 | public function __construct(AbstractDocument $document) 30 | { 31 | $this->document = $document; 32 | } 33 | 34 | public function getDocument() 35 | { 36 | return $this->document; 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /src/Mongator/ConnectionInterface.php: -------------------------------------------------------------------------------- 1 | 7 | * 8 | * This source file is subject to the MIT license that is bundled 9 | * with this source code in the file LICENSE. 10 | */ 11 | 12 | namespace Mongator; 13 | use MongoDB\Client; 14 | 15 | /** 16 | * ConnectionInterface. 17 | * 18 | * @author Pablo Díez 19 | * 20 | * @api 21 | */ 22 | interface ConnectionInterface 23 | { 24 | /** 25 | * Returns the mongo connection object. 26 | * 27 | * @return \MongoDB\Client The mongo collection object. 28 | * 29 | * @api 30 | */ 31 | public function getMongo(); 32 | 33 | /** 34 | * Returns the database object. 35 | * 36 | * @return \MongoDB\Database The database object. 37 | * 38 | * @api 39 | */ 40 | public function getMongoDB(); 41 | } 42 | -------------------------------------------------------------------------------- /src/Mongator/Id/NativeIdGenerator.php: -------------------------------------------------------------------------------- 1 | 7 | * 8 | * This source file is subject to the MIT license that is bundled 9 | * with this source code in the file LICENSE. 10 | */ 11 | 12 | namespace Mongator\Id; 13 | 14 | /** 15 | * Generates a native identifier. 16 | * 17 | * @author Pablo Díez 18 | */ 19 | class NativeIdGenerator extends BaseIdGenerator 20 | { 21 | /** 22 | * {@inheritdoc} 23 | */ 24 | public function getCode(array $options) 25 | { 26 | return '%id% = new \MongoDB\BSON\ObjectID();'; 27 | } 28 | 29 | /** 30 | * {@inheritdoc} 31 | */ 32 | public function getToMongoCode() 33 | { 34 | return << 7 | * 8 | * This source file is subject to the MIT license that is bundled 9 | * with this source code in the file LICENSE. 10 | */ 11 | 12 | namespace Mongator\Tests\Group; 13 | 14 | use Mongator\Tests\TestCase; 15 | use Mongator\Group\PolymorphicGroup as BasePolymorphicGroup; 16 | 17 | class PolymorphicGroup extends BasePolymorphicGroup 18 | { 19 | public $forSaved = array(); 20 | 21 | protected function doInitializeSavedData() 22 | { 23 | return $this->forSaved; 24 | } 25 | } 26 | 27 | class PolymorphicGroupTest extends TestCase 28 | { 29 | public function testConstructor() 30 | { 31 | $group = new PolymorphicGroup('my_discriminatorField'); 32 | $this->assertSame('my_discriminatorField', $group->getDiscriminatorField()); 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /tests/bootstrap.php: -------------------------------------------------------------------------------- 1 | add('Mongator\Tests', __DIR__); 6 | $loader->add('Mongator\Benchmarks', __DIR__); 7 | $loader->add('Model', __DIR__); 8 | 9 | // mondator 10 | use Mandango\Mondator\Mondator; 11 | use Mongator\Id\IdGeneratorContainer; 12 | 13 | $mondator = new Mondator(); 14 | $mondator->setConfigClasses($configClasses); 15 | $mondator->setExtensions(array( 16 | new Mongator\Extension\Core(array( 17 | 'metadata_factory_class' => 'Model\Mapping\Metadata', 18 | 'metadata_factory_output' => __DIR__, 19 | 'default_output' => __DIR__, 20 | )), 21 | new Mongator\Extension\DocumentArrayAccess(), 22 | new Mongator\Extension\DocumentPropertyOverloading(), 23 | )); 24 | 25 | IdGeneratorContainer::add('ab-id', 'Mongator\Tests\Id\ABIdGenerator'); 26 | $mondator->process(); 27 | -------------------------------------------------------------------------------- /tests/Mongator/Tests/Cache/RedisCacheTest.php: -------------------------------------------------------------------------------- 1 | 7 | * 8 | * This source file is subject to the MIT license that is bundled 9 | * with this source code in the file LICENSE. 10 | */ 11 | 12 | namespace Mongator\Tests\Cache; 13 | 14 | use Mongator\Cache\RedisCache; 15 | 16 | class RedisCacheTest extends Cache 17 | { 18 | protected function getCacheDriver() 19 | { 20 | if ( class_exists('Redis') == false ) { 21 | $this->markTestSkipped( 22 | 'redis extension must be loaded' 23 | ); 24 | } 25 | 26 | $redis = new \Redis(); 27 | if ( !$connection = $redis->pconnect('127.0.0.1') ) { 28 | $this->markTestSkipped( 29 | 'unable to connect to localhost redis server' 30 | ); 31 | } 32 | 33 | return new RedisCache($redis); 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /src/Mongator/Id/NoneIdGenerator.php: -------------------------------------------------------------------------------- 1 | 7 | * 8 | * This source file is subject to the MIT license that is bundled 9 | * with this source code in the file LICENSE. 10 | */ 11 | 12 | namespace Mongator\Id; 13 | 14 | use Mongator\Document\Document; 15 | 16 | /** 17 | * Does not generate anything. 18 | * 19 | * You can put your own identifiers or rely on Mongo. 20 | * 21 | * @author Pablo Díez 22 | */ 23 | class NoneIdGenerator extends BaseIdGenerator 24 | { 25 | /** 26 | * {@inheritdoc} 27 | */ 28 | public function getCode(array $options) 29 | { 30 | return <<getId()) { 32 | %id% = \$document->getId(); 33 | } 34 | EOF; 35 | } 36 | 37 | /** 38 | * {@inheritdoc} 39 | */ 40 | public function getToMongoCode() 41 | { 42 | return ''; 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /tests/Mongator/Tests/Cache/FilesystemCacheTest.php: -------------------------------------------------------------------------------- 1 | 7 | * 8 | * This source file is subject to the MIT license that is bundled 9 | * with this source code in the file LICENSE. 10 | */ 11 | 12 | namespace Mongator\Tests\Cache; 13 | 14 | use Mongator\Cache\FilesystemCache; 15 | 16 | class FilesystemCacheTest extends Cache 17 | { 18 | private $folder; 19 | protected function getCacheDriver() 20 | { 21 | $this->folder = sys_get_temp_dir().'/Mongator_filesystem_cache_tests'.mt_rand(111111, 999999); 22 | 23 | return new FilesystemCache($this->folder); 24 | } 25 | 26 | public function testGetWithFileCache() 27 | { 28 | $this->cache->set('read', 'foo'); 29 | $this->assertSame('foo', $this->cache->get('read')); 30 | 31 | unlink($this->folder . '/read.php'); 32 | $this->assertSame('foo', $this->cache->get('read')); 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /src/Mongator/Type/RawType.php: -------------------------------------------------------------------------------- 1 | 7 | * 8 | * This source file is subject to the MIT license that is bundled 9 | * with this source code in the file LICENSE. 10 | */ 11 | 12 | namespace Mongator\Type; 13 | 14 | /** 15 | * RawType. 16 | * 17 | * @author Pablo Díez 18 | * 19 | * @api 20 | */ 21 | class RawType extends Type 22 | { 23 | /** 24 | * {@inheritdoc} 25 | */ 26 | public function toMongo($value) 27 | { 28 | return $value; 29 | } 30 | 31 | /** 32 | * {@inheritdoc} 33 | */ 34 | public function toPHP($value) 35 | { 36 | return $value; 37 | } 38 | 39 | /** 40 | * {@inheritdoc} 41 | */ 42 | public function toMongoInString() 43 | { 44 | return '%to% = %from%;'; 45 | } 46 | 47 | /** 48 | * {@inheritdoc} 49 | */ 50 | public function toPHPInString() 51 | { 52 | return '%to% = %from%;'; 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /src/Mongator/Id/BaseIdGenerator.php: -------------------------------------------------------------------------------- 1 | 7 | * 8 | * This source file is subject to the MIT license that is bundled 9 | * with this source code in the file LICENSE. 10 | */ 11 | 12 | namespace Mongator\Id; 13 | 14 | /** 15 | * BaseIdGenerator. 16 | * 17 | * @author Pablo Díez 18 | */ 19 | abstract class BaseIdGenerator 20 | { 21 | /** 22 | * Returns the code to generate the id. 23 | * 24 | * @param array $options An array of options. 25 | * 26 | * @return string The code to generate. 27 | */ 28 | abstract public function getCode(array $options); 29 | 30 | /** 31 | * Returns the code to convert an id to the mongo value. 32 | */ 33 | abstract public function getToMongoCode(); 34 | 35 | /** 36 | * Returns the code to convert a mongo id to the id used in Mongator. Nothing done by default 37 | * 38 | */ 39 | public function getToPHPCode() 40 | { 41 | return ''; 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /tests/Model/FormElement.php: -------------------------------------------------------------------------------- 1 | events[] = $this->eventPrefix.'FormElementPreInserting'; 13 | } 14 | 15 | protected function formElementPostInsert() 16 | { 17 | $this->events[] = $this->eventPrefix.'FormElementPostInserting'; 18 | } 19 | 20 | protected function formElementPreUpdate() 21 | { 22 | $this->events[] = $this->eventPrefix.'FormElementPreUpdating'; 23 | } 24 | 25 | protected function formElementPostUpdate() 26 | { 27 | $this->events[] = $this->eventPrefix.'FormElementPostUpdating'; 28 | } 29 | 30 | protected function formElementPreDelete() 31 | { 32 | $this->events[] = $this->eventPrefix.'FormElementPreDeleting'; 33 | } 34 | 35 | protected function formElementPostDelete() 36 | { 37 | $this->events[] = $this->eventPrefix.'FormElementPostDeleting'; 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /tests/Model/TextareaFormElement.php: -------------------------------------------------------------------------------- 1 | events[] = $this->eventPrefix.'TextareaPreInserting'; 13 | } 14 | 15 | protected function textareaPostInsert() 16 | { 17 | $this->events[] = $this->eventPrefix.'TextareaPostInserting'; 18 | } 19 | 20 | protected function textareaPreUpdate() 21 | { 22 | $this->events[] = $this->eventPrefix.'TextareaPreUpdating'; 23 | } 24 | 25 | protected function textareaPostUpdate() 26 | { 27 | $this->events[] = $this->eventPrefix.'TextareaPostUpdating'; 28 | } 29 | 30 | protected function textareaPreDelete() 31 | { 32 | $this->events[] = $this->eventPrefix.'TextareaPreDeleting'; 33 | } 34 | 35 | protected function textareaPostDelete() 36 | { 37 | $this->events[] = $this->eventPrefix.'TextareaPostDeleting'; 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /tests/Mongator/Tests/Cache/APCCacheTest.php: -------------------------------------------------------------------------------- 1 | 7 | * 8 | * This source file is subject to the MIT license that is bundled 9 | * with this source code in the file LICENSE. 10 | */ 11 | 12 | namespace Mongator\Tests\Cache; 13 | 14 | use Mongator\Cache\APCCache; 15 | 16 | class APCCacheTest extends Cache 17 | { 18 | protected function getCacheDriver() 19 | { 20 | if ( function_exists('apc_fetch') == false ) { 21 | $this->markTestSkipped( 22 | 'apc extension must be loaded' 23 | ); 24 | } 25 | 26 | if ( (boolean) ini_get('apc.enabled') == false ) { 27 | $this->markTestSkipped( 28 | 'apc.enable must be true' 29 | ); 30 | } 31 | 32 | if ( (boolean) ini_get('apc.enable_cli') == false ) { 33 | $this->markTestSkipped( 34 | 'apc.enable_cli must be true' 35 | ); 36 | } 37 | 38 | return new APCCache(); 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /src/Mongator/Type/FloatType.php: -------------------------------------------------------------------------------- 1 | 7 | * 8 | * This source file is subject to the MIT license that is bundled 9 | * with this source code in the file LICENSE. 10 | */ 11 | 12 | namespace Mongator\Type; 13 | 14 | /** 15 | * FloatType. 16 | * 17 | * @author Pablo Díez 18 | * 19 | * @api 20 | */ 21 | class FloatType extends Type 22 | { 23 | /** 24 | * {@inheritdoc} 25 | */ 26 | public function toMongo($value) 27 | { 28 | return (float) $value; 29 | } 30 | 31 | /** 32 | * {@inheritdoc} 33 | */ 34 | public function toPHP($value) 35 | { 36 | return (float) $value; 37 | } 38 | 39 | /** 40 | * {@inheritdoc} 41 | */ 42 | public function toMongoInString() 43 | { 44 | return '%to% = (float) %from%;'; 45 | } 46 | 47 | /** 48 | * {@inheritdoc} 49 | */ 50 | public function toPHPInString() 51 | { 52 | return '%to% = (float) %from%;'; 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /src/Mongator/Type/IntegerType.php: -------------------------------------------------------------------------------- 1 | 7 | * 8 | * This source file is subject to the MIT license that is bundled 9 | * with this source code in the file LICENSE. 10 | */ 11 | 12 | namespace Mongator\Type; 13 | 14 | /** 15 | * IntegerType. 16 | * 17 | * @author Pablo Díez 18 | * 19 | * @api 20 | */ 21 | class IntegerType extends Type 22 | { 23 | /** 24 | * {@inheritdoc} 25 | */ 26 | public function toMongo($value) 27 | { 28 | return (int) $value; 29 | } 30 | 31 | /** 32 | * {@inheritdoc} 33 | */ 34 | public function toPHP($value) 35 | { 36 | return (int) $value; 37 | } 38 | 39 | /** 40 | * {@inheritdoc} 41 | */ 42 | public function toMongoInString() 43 | { 44 | return '%to% = (int) %from%;'; 45 | } 46 | 47 | /** 48 | * {@inheritdoc} 49 | */ 50 | public function toPHPInString() 51 | { 52 | return '%to% = (int) %from%;'; 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /tests/Mongator/Benchmarks/InsertingEvent.php: -------------------------------------------------------------------------------- 1 | 7 | * 8 | * This source file is subject to the MIT license that is bundled 9 | * with this source code in the file LICENSE. 10 | */ 11 | 12 | namespace Mongator\Benchmarks; 13 | 14 | class InsertingEvent extends AthleticEvent 15 | { 16 | /** 17 | * @iterations 500 18 | */ 19 | public function simpleDocument() 20 | { 21 | $this->buildSimpleDocument()->save(); 22 | } 23 | 24 | /** 25 | * @iterations 500 26 | */ 27 | public function simpleNestedDocument() 28 | { 29 | $this->buildSimpleNestedDocument()->save(); 30 | } 31 | 32 | /** 33 | * @iterations 500 34 | */ 35 | public function complexDocument() 36 | { 37 | $this->buildComplexDocument()->save(); 38 | } 39 | 40 | /** 41 | * @iterations 500 42 | */ 43 | public function complexNestedDocument() 44 | { 45 | $this->buildComplexNestedDocument()->save(); 46 | } 47 | } -------------------------------------------------------------------------------- /src/Mongator/Group/Group.php: -------------------------------------------------------------------------------- 1 | 7 | * 8 | * This source file is subject to the MIT license that is bundled 9 | * with this source code in the file LICENSE. 10 | */ 11 | 12 | namespace Mongator\Group; 13 | 14 | use Mongator\Archive; 15 | use Mongator\Document\Document; 16 | 17 | /** 18 | * Group. 19 | * 20 | * @author Pablo Díez 21 | * 22 | * @api 23 | */ 24 | abstract class Group extends AbstractGroup 25 | { 26 | /** 27 | * Constructor. 28 | * 29 | * @param string $documentClass The document class. 30 | * 31 | * @api 32 | */ 33 | public function __construct($documentClass) 34 | { 35 | parent::__construct(); 36 | $this->getArchive()->set('document_class', $documentClass); 37 | } 38 | 39 | /** 40 | * Returns the document class. 41 | * 42 | * @api 43 | */ 44 | public function getDocumentClass() 45 | { 46 | return $this->getArchive()->get('document_class'); 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /src/Mongator/Type/BooleanType.php: -------------------------------------------------------------------------------- 1 | 7 | * 8 | * This source file is subject to the MIT license that is bundled 9 | * with this source code in the file LICENSE. 10 | */ 11 | 12 | namespace Mongator\Type; 13 | 14 | /** 15 | * BooleanType. 16 | * 17 | * @author Pablo Díez 18 | * 19 | * @api 20 | */ 21 | class BooleanType extends Type 22 | { 23 | /** 24 | * {@inheritdoc} 25 | */ 26 | public function toMongo($value) 27 | { 28 | return (bool) $value; 29 | } 30 | 31 | /** 32 | * {@inheritdoc} 33 | */ 34 | public function toPHP($value) 35 | { 36 | return (bool) $value; 37 | } 38 | 39 | /** 40 | * {@inheritdoc} 41 | */ 42 | public function toMongoInString() 43 | { 44 | return '%to% = (bool) %from%;'; 45 | } 46 | 47 | /** 48 | * {@inheritdoc} 49 | */ 50 | public function toPHPInString() 51 | { 52 | return '%to% = (bool) %from%;'; 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /src/Mongator/Type/StringType.php: -------------------------------------------------------------------------------- 1 | 7 | * 8 | * This source file is subject to the MIT license that is bundled 9 | * with this source code in the file LICENSE. 10 | */ 11 | 12 | namespace Mongator\Type; 13 | 14 | /** 15 | * StringType. 16 | * 17 | * @author Pablo Díez 18 | * 19 | * @api 20 | */ 21 | class StringType extends Type 22 | { 23 | /** 24 | * {@inheritdoc} 25 | */ 26 | public function toMongo($value) 27 | { 28 | return (string) $value; 29 | } 30 | 31 | /** 32 | * {@inheritdoc} 33 | */ 34 | public function toPHP($value) 35 | { 36 | return (string) $value; 37 | } 38 | 39 | /** 40 | * {@inheritdoc} 41 | */ 42 | public function toMongoInString() 43 | { 44 | return '%to% = (string) %from%;'; 45 | } 46 | 47 | /** 48 | * {@inheritdoc} 49 | */ 50 | public function toPHPInString() 51 | { 52 | return '%to% = (string) %from%;'; 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /src/Mongator/Type/SerializedType.php: -------------------------------------------------------------------------------- 1 | 7 | * 8 | * This source file is subject to the MIT license that is bundled 9 | * with this source code in the file LICENSE. 10 | */ 11 | 12 | namespace Mongator\Type; 13 | 14 | /** 15 | * SerializedType. 16 | * 17 | * @author Pablo Díez 18 | * 19 | * @api 20 | */ 21 | class SerializedType extends Type 22 | { 23 | /** 24 | * {@inheritdoc} 25 | */ 26 | public function toMongo($value) 27 | { 28 | return serialize($value); 29 | } 30 | 31 | /** 32 | * {@inheritdoc} 33 | */ 34 | public function toPHP($value) 35 | { 36 | return unserialize($value); 37 | } 38 | 39 | /** 40 | * {@inheritdoc} 41 | */ 42 | public function toMongoInString() 43 | { 44 | return '%to% = serialize(%from%);'; 45 | } 46 | 47 | /** 48 | * {@inheritdoc} 49 | */ 50 | public function toPHPInString() 51 | { 52 | return '%to% = unserialize(%from%);'; 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2010-2011 Pablo Díez 2 | Copyright (c) 2012-2014 Máximo Cuadros 3 | 4 | Permission is hereby granted, free of charge, to any person obtaining a copy 5 | of this software and associated documentation files (the "Software"), to deal 6 | in the Software without restriction, including without limitation the rights 7 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | copies of the Software, and to permit persons to whom the Software is furnished 9 | to do so, subject to the following conditions: 10 | 11 | The above copyright notice and this permission notice shall be included in all 12 | copies or substantial portions of the Software. 13 | 14 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 20 | THE SOFTWARE. 21 | -------------------------------------------------------------------------------- /src/Mongator/Group/PolymorphicGroup.php: -------------------------------------------------------------------------------- 1 | 7 | * 8 | * This source file is subject to the MIT license that is bundled 9 | * with this source code in the file LICENSE. 10 | */ 11 | 12 | namespace Mongator\Group; 13 | 14 | use Mongator\Archive; 15 | 16 | /** 17 | * PolymorphicGroup. 18 | * 19 | * @author Pablo Díez 20 | * 21 | * @api 22 | */ 23 | abstract class PolymorphicGroup extends AbstractGroup 24 | { 25 | /** 26 | * Constructor. 27 | * 28 | * @param string $discriminatorField The discriminator field. 29 | * 30 | * @api 31 | */ 32 | public function __construct($discriminatorField) 33 | { 34 | parent::__construct(); 35 | 36 | $this->getArchive()->set('discriminatorField', $discriminatorField); 37 | } 38 | 39 | /** 40 | * Returns the discriminator field. 41 | * 42 | * @return string The discriminator field. 43 | * 44 | * @api 45 | */ 46 | public function getDiscriminatorField() 47 | { 48 | return $this->getArchive()->get('discriminatorField'); 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /tests/Mongator/Tests/Cache/MemcachedCacheTest.php: -------------------------------------------------------------------------------- 1 | 7 | * 8 | * This source file is subject to the MIT license that is bundled 9 | * with this source code in the file LICENSE. 10 | */ 11 | 12 | namespace Mongator\Tests\Cache; 13 | 14 | use Mongator\Cache\MemcachedCache; 15 | 16 | class MemcachedCacheTest extends Cache 17 | { 18 | protected function getCacheDriver() 19 | { 20 | 21 | $this->markTestSkipped( 22 | 'memcached tests fails at travis' 23 | ); 24 | 25 | if ( class_exists('Memcached') == false ) { 26 | $this->markTestSkipped( 27 | 'memcached extension must be loaded' 28 | ); 29 | } 30 | 31 | $memcached = new \Memcached(); 32 | if ( !$memcached->addServer('127.0.0.1', 11211) ) { 33 | $this->markTestSkipped( 34 | 'unable to connect to localhost memcached server' 35 | ); 36 | } 37 | 38 | return new MemcachedCache($memcached); 39 | } 40 | 41 | public function testCacheSetTtl() 42 | { 43 | $this->assertTrue(true); 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /tests/Mongator/Tests/Type/StringTypeTest.php: -------------------------------------------------------------------------------- 1 | 7 | * 8 | * This source file is subject to the MIT license that is bundled 9 | * with this source code in the file LICENSE. 10 | */ 11 | 12 | namespace Mongator\Tests\Type; 13 | 14 | use Mongator\Type\StringType; 15 | 16 | class StringTypeTest extends TestCase 17 | { 18 | public function testToMongo() 19 | { 20 | $type = new StringType(); 21 | $this->assertSame('123', $type->toMongo(123)); 22 | } 23 | 24 | public function testToPHP() 25 | { 26 | $type = new StringType(); 27 | $this->assertSame('123', $type->toPHP(123)); 28 | } 29 | 30 | public function testToMongoInString() 31 | { 32 | $type = new StringType(); 33 | $function = $this->getTypeFunction($type->toMongoInString()); 34 | 35 | $this->assertSame('123', $function(123)); 36 | } 37 | 38 | public function testToPHPInString() 39 | { 40 | $type = new StringType(); 41 | $function = $this->getTypeFunction($type->toPHPInString()); 42 | 43 | $this->assertSame('123', $function(123)); 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /tests/Mongator/Tests/Type/IntegerTypeTest.php: -------------------------------------------------------------------------------- 1 | 7 | * 8 | * This source file is subject to the MIT license that is bundled 9 | * with this source code in the file LICENSE. 10 | */ 11 | 12 | namespace Mongator\Tests\Type; 13 | 14 | use Mongator\Type\IntegerType; 15 | 16 | class IntegerTypeTest extends TestCase 17 | { 18 | public function testToMongo() 19 | { 20 | $type = new IntegerType(); 21 | $this->assertSame(123, $type->toMongo('123')); 22 | } 23 | 24 | public function testToPHP() 25 | { 26 | $type = new IntegerType(); 27 | $this->assertSame(123, $type->toPHP('123')); 28 | } 29 | 30 | public function testToMongoInString() 31 | { 32 | $type = new IntegerType(); 33 | $function = $this->getTypeFunction($type->toMongoInString()); 34 | 35 | $this->assertSame(123, $function('123')); 36 | } 37 | 38 | public function testToPHPInString() 39 | { 40 | $type = new IntegerType(); 41 | $function = $this->getTypeFunction($type->toPHPInString()); 42 | 43 | $this->assertSame(123, $function('123')); 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /tests/Mongator/Tests/Type/FloatTypeTest.php: -------------------------------------------------------------------------------- 1 | 7 | * 8 | * This source file is subject to the MIT license that is bundled 9 | * with this source code in the file LICENSE. 10 | */ 11 | 12 | namespace Mongator\Tests\Type; 13 | 14 | use Mongator\Type\FloatType; 15 | 16 | class FloatTypeTest extends TestCase 17 | { 18 | public function testToMongo() 19 | { 20 | $type = new FloatType(); 21 | $this->assertSame(123.45, $type->toMongo('123.45')); 22 | } 23 | 24 | public function testToPHP() 25 | { 26 | $type = new FloatType(); 27 | $this->assertSame(123.45, $type->toPHP('123.45')); 28 | } 29 | 30 | public function testToMongoInString() 31 | { 32 | $type = new FloatType(); 33 | $function = $this->getTypeFunction($type->toMongoInString()); 34 | 35 | $this->assertSame(123.45, $function('123.45')); 36 | } 37 | 38 | public function testToPHPInString() 39 | { 40 | $type = new FloatType(); 41 | $function = $this->getTypeFunction($type->toPHPInString()); 42 | 43 | $this->assertSame(123.45, $function('123.45')); 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /src/Mongator/UnitOfWorkInterface.php: -------------------------------------------------------------------------------- 1 | 7 | * 8 | * This source file is subject to the MIT license that is bundled 9 | * with this source code in the file LICENSE. 10 | */ 11 | 12 | namespace Mongator; 13 | 14 | /** 15 | * UnitOfWorkInterface. 16 | * 17 | * @author Pablo Díez 18 | * 19 | * @api 20 | */ 21 | interface UnitOfWorkInterface 22 | { 23 | /** 24 | * Persist a document. 25 | * 26 | * @param \Mongator\Document\Document|array $documents A document or an array of documents. 27 | * 28 | * @api 29 | */ 30 | public function persist($documents); 31 | 32 | /** 33 | * Remove a document. 34 | * 35 | * @param \Mongator\Document\Document|array $documents A document or an array of documents. 36 | * 37 | * @api 38 | */ 39 | public function remove($documents); 40 | 41 | /** 42 | * Commit pending persist and remove operations. 43 | * 44 | * @api 45 | */ 46 | public function commit(); 47 | 48 | /** 49 | * Clear the pending operations 50 | * 51 | * @api 52 | */ 53 | public function clear(); 54 | } 55 | -------------------------------------------------------------------------------- /tests/Mongator/Tests/Group/PolymorphicReferenceGroupTest.php: -------------------------------------------------------------------------------- 1 | 7 | * 8 | * This source file is subject to the MIT license that is bundled 9 | * with this source code in the file LICENSE. 10 | */ 11 | 12 | namespace Mongator\Tests\Group; 13 | 14 | use Mongator\Tests\TestCase; 15 | use Mongator\Group\PolymorphicReferenceGroup; 16 | 17 | class PolymorphicReferenceGroupTest extends TestCase 18 | { 19 | public function testConstructor() 20 | { 21 | $group = new PolymorphicReferenceGroup('_MongatorDocumentClass', $article = $this->mongator->create('Model\Article'), 'related_ref'); 22 | $this->assertSame($article, $group->getParent()); 23 | $this->assertSame('related_ref', $group->getField()); 24 | $this->assertFalse($group->getDiscriminatorMap()); 25 | 26 | $discriminatorMap = array( 27 | 'au' => 'Model\Author', 28 | 'ct' => 'Model\Category', 29 | ); 30 | $group = new PolymorphicReferenceGroup('_MongatorDocumentClass', $article = $this->mongator->create('Model\Article'), 'related_ref', $discriminatorMap); 31 | $this->assertSame($discriminatorMap, $group->getDiscriminatorMap()); 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /src/Mongator/Cache/ArrayCache.php: -------------------------------------------------------------------------------- 1 | 7 | * 8 | * This source file is subject to the MIT license that is bundled 9 | * with this source code in the file LICENSE. 10 | */ 11 | 12 | namespace Mongator\Cache; 13 | 14 | /** 15 | * AbstractCache. 16 | * 17 | * @author Máximo Cuadros 18 | */ 19 | class ArrayCache extends AbstractCache 20 | { 21 | private $data = array(); 22 | 23 | /** 24 | * {@inheritdoc} 25 | */ 26 | public function set($key, $value, $ttl = 0) 27 | { 28 | $content = $this->pack($key, $value, $ttl); 29 | 30 | $this->data[$key] = $this->pack($key, $value, $ttl); 31 | } 32 | 33 | /** 34 | * {@inheritdoc} 35 | */ 36 | public function remove($key) 37 | { 38 | unset($this->data[$key]); 39 | } 40 | 41 | /** 42 | * {@inheritdoc} 43 | */ 44 | public function info($key) 45 | { 46 | if ( !isset($this->data[$key]) ) { 47 | return null; 48 | } 49 | 50 | return $this->data[$key]; 51 | } 52 | 53 | /** 54 | * {@inheritdoc} 55 | */ 56 | public function clear() 57 | { 58 | $this->data = array(); 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /src/Mongator/Cache/APCCache.php: -------------------------------------------------------------------------------- 1 | 7 | * 8 | * This source file is subject to the MIT license that is bundled 9 | * with this source code in the file LICENSE. 10 | */ 11 | 12 | namespace Mongator\Cache; 13 | 14 | /** 15 | * AbstractCache. 16 | * 17 | * @author Máximo Cuadros 18 | */ 19 | class APCCache extends AbstractCache 20 | { 21 | private $data = array(); 22 | 23 | /** 24 | * {@inheritdoc} 25 | */ 26 | public function set($key, $value, $ttl = 0) 27 | { 28 | $content = $this->pack($key, $value, $ttl); 29 | $string = serialize($content); 30 | apc_store((string) $key, $string, $ttl); 31 | } 32 | 33 | /** 34 | * {@inheritdoc} 35 | */ 36 | public function remove($key) 37 | { 38 | return apc_delete($key); 39 | } 40 | 41 | /** 42 | * {@inheritdoc} 43 | */ 44 | public function clear() 45 | { 46 | return apc_clear_cache('user'); 47 | } 48 | 49 | /** 50 | * {@inheritdoc} 51 | */ 52 | public function info($key) 53 | { 54 | if ( !$content = apc_fetch($key) ) { 55 | return false; 56 | } 57 | 58 | return unserialize($content); 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /src/Mongator/Type/ArrayObjectType.php: -------------------------------------------------------------------------------- 1 | 7 | * 8 | * This source file is subject to the MIT license that is bundled 9 | * with this source code in the file LICENSE. 10 | */ 11 | 12 | namespace Mongator\Type; 13 | 14 | use MongoDB\Model\BSONArray; 15 | use MongoDB\Model\BSONDocument; 16 | 17 | 18 | /** 19 | * ArrayObjectType. 20 | * 21 | * Parent class for array and object types 22 | * 23 | * @author Adam.Balint 24 | * 25 | * @api 26 | */ 27 | abstract class ArrayObjectType extends Type 28 | { 29 | 30 | /** 31 | * Convert BSONDocument and BSONArray to array recursively 32 | * 33 | * @param mixed $value 34 | * @return mixed 35 | */ 36 | static function BSONToArrayRecursive($value){ 37 | if($value instanceof BSONDocument || $value instanceof BSONArray) { 38 | $value = $value->getArrayCopy(); 39 | } 40 | if(is_array($value)){ 41 | foreach($value as $key => $item){ 42 | if(is_array($item) || $item instanceof BSONDocument || $item instanceof BSONArray){ 43 | $value[$key] = self::BSONToArrayRecursive($item); 44 | } 45 | } 46 | } 47 | return $value; 48 | } 49 | } -------------------------------------------------------------------------------- /src/Mongator/Type/BinDataType.php: -------------------------------------------------------------------------------- 1 | 7 | * 8 | * This source file is subject to the MIT license that is bundled 9 | * with this source code in the file LICENSE. 10 | */ 11 | 12 | namespace Mongator\Type; 13 | 14 | use MongoDB\BSON\Binary; 15 | 16 | /** 17 | * BinDataType. 18 | * 19 | * @author Pablo Díez 20 | * 21 | * @api 22 | */ 23 | class BinDataType extends Type 24 | { 25 | /** 26 | * {@inheritdoc} 27 | */ 28 | public function toMongo($value) 29 | { 30 | if (is_file($value)) { 31 | $value = file_get_contents($value); 32 | } 33 | 34 | return new Binary($value, Binary::TYPE_GENERIC); 35 | } 36 | 37 | /** 38 | * {@inheritdoc} 39 | */ 40 | public function toPHP($value) 41 | { 42 | return $value->bin; 43 | } 44 | 45 | /** 46 | * {@inheritdoc} 47 | */ 48 | public function toMongoInString() 49 | { 50 | return 'if (is_file(%from%)) { %from% = file_get_contents(%from%); } %to% = new \MongoDB\BSON\Binary(%from%, \MongoDB\BSON\Binary::TYPE_GENERIC);'; 51 | } 52 | 53 | /** 54 | * {@inheritdoc} 55 | */ 56 | public function toPHPInString() 57 | { 58 | return '%to% = %from%->bin;'; 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /src/Mongator/Extension/templates/DocumentArrayAccess.php.twig: -------------------------------------------------------------------------------- 1 | set($name, $value); 24 | } 25 | 26 | /** 27 | * Returns data of the document. 28 | * 29 | * @param string $name The data name. 30 | * 31 | * @return mixed Some data. 32 | * 33 | * @throws \InvalidArgumentException If the data name does not exists. 34 | */ 35 | public function offsetGet($name) 36 | { 37 | return $this->get($name); 38 | } 39 | 40 | /** 41 | * Throws a \LogicException because you cannot unset data through ArrayAccess. 42 | * 43 | * @throws \LogicException 44 | */ 45 | public function offsetUnset($name) 46 | { 47 | throw new \LogicException('You cannot unset data.'); 48 | } 49 | -------------------------------------------------------------------------------- /tests/Mongator/Tests/Type/BooleanTypeTest.php: -------------------------------------------------------------------------------- 1 | 7 | * 8 | * This source file is subject to the MIT license that is bundled 9 | * with this source code in the file LICENSE. 10 | */ 11 | 12 | namespace Mongator\Tests\Type; 13 | 14 | use Mongator\Type\BooleanType; 15 | 16 | class BooleanTypeTest extends TestCase 17 | { 18 | public function testToMongo() 19 | { 20 | $type = new BooleanType(); 21 | $this->assertTrue($type->toMongo(1)); 22 | $this->assertFalse($type->toMongo(0)); 23 | } 24 | 25 | public function testToPHP() 26 | { 27 | $type = new BooleanType(); 28 | $this->assertTrue($type->toPHP(1)); 29 | $this->assertFalse($type->toPHP(0)); 30 | } 31 | 32 | public function testToMongoInString() 33 | { 34 | $type = new BooleanType(); 35 | $function = $this->getTypeFunction($type->toMongoInString()); 36 | 37 | $this->assertTrue($function(1)); 38 | $this->assertFalse($function(0)); 39 | } 40 | 41 | public function testToPHPInString() 42 | { 43 | $type = new BooleanType(); 44 | $function = $this->getTypeFunction($type->toPHPInString()); 45 | 46 | $this->assertTrue($function(1)); 47 | $this->assertFalse($function(0)); 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /tests/Mongator/Tests/Extension/DocumentPropertyOverloadingTest.php: -------------------------------------------------------------------------------- 1 | 7 | * 8 | * This source file is subject to the MIT license that is bundled 9 | * with this source code in the file LICENSE. 10 | */ 11 | 12 | namespace Mongator\Tests\Extension; 13 | 14 | use Mongator\Tests\TestCase; 15 | 16 | class DocumentPropertyOverloadingTest extends TestCase 17 | { 18 | public function test__set() 19 | { 20 | $article = $this->mongator->create('Model\Article'); 21 | $article->title = 'foo'; 22 | $this->assertSame('foo', $article->getTitle()); 23 | } 24 | 25 | /** 26 | * @expectedException \InvalidArgumentException 27 | */ 28 | public function test__setNameNotExists() 29 | { 30 | $article = $this->mongator->create('Model\Article'); 31 | $article->no = 'foo'; 32 | } 33 | 34 | public function test__get() 35 | { 36 | $article = $this->mongator->create('Model\Article'); 37 | $article->setTitle('foo'); 38 | $this->assertSame('foo', $article->title); 39 | } 40 | 41 | /** 42 | * @expectedException \InvalidArgumentException 43 | */ 44 | public function test__getNameNotExists() 45 | { 46 | $article = $this->mongator->create('Model\Article'); 47 | $article->no; 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /tests/Mongator/Tests/Type/SerializedTypeTest.php: -------------------------------------------------------------------------------- 1 | 7 | * 8 | * This source file is subject to the MIT license that is bundled 9 | * with this source code in the file LICENSE. 10 | */ 11 | 12 | namespace Mongator\Tests\Type; 13 | 14 | use Mongator\Type\SerializedType; 15 | 16 | class SerializedTypeTest extends TestCase 17 | { 18 | protected $array = array('foo' => 'bar'); 19 | 20 | public function testToMongo() 21 | { 22 | $type = new SerializedType(); 23 | $this->assertSame(serialize($this->array), $type->toMongo($this->array)); 24 | } 25 | 26 | public function testToPHP() 27 | { 28 | $type = new SerializedType(); 29 | $this->assertSame($this->array, $type->toPHP(serialize($this->array))); 30 | } 31 | 32 | public function testToMongoInString() 33 | { 34 | $type = new SerializedType(); 35 | $function = $this->getTypeFunction($type->toMongoInString()); 36 | 37 | $this->assertSame(serialize($this->array), $function($this->array)); 38 | } 39 | 40 | public function testToPHPInString() 41 | { 42 | $type = new SerializedType(); 43 | $function = $this->getTypeFunction($type->toPHPInString()); 44 | 45 | $this->assertSame($this->array, $function(serialize($this->array))); 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /src/Mongator/Type/Type.php: -------------------------------------------------------------------------------- 1 | 7 | * 8 | * This source file is subject to the MIT license that is bundled 9 | * with this source code in the file LICENSE. 10 | */ 11 | 12 | namespace Mongator\Type; 13 | 14 | /** 15 | * Base class for Mongator types. 16 | * 17 | * @author Pablo Díez 18 | * 19 | * @api 20 | */ 21 | abstract class Type 22 | { 23 | /** 24 | * Convert a PHP value to a Mongo value. 25 | * 26 | * @param mixed $value The PHP value. 27 | * 28 | * @return mixed The Mongo value. 29 | * 30 | * @api 31 | */ 32 | abstract public function toMongo($value); 33 | 34 | /** 35 | * Convert a Mongo value to a PHP value. 36 | * 37 | * @param mixed $value The Mongo value. 38 | * 39 | * @return mixed The PHP value. 40 | * 41 | * @api 42 | */ 43 | abstract public function toPHP($value); 44 | 45 | /** 46 | * Convert a PHP value to a Mongo value (in string). 47 | * 48 | * @return string Code to convert the value. 49 | * 50 | * @api 51 | */ 52 | abstract public function toMongoInString(); 53 | 54 | /** 55 | * Convert a Mongo value to a PHP value (in string). 56 | * 57 | * @return mixed Code to conver the value. 58 | * 59 | * @api 60 | */ 61 | abstract public function toPHPInString(); 62 | } 63 | -------------------------------------------------------------------------------- /src/Mongator/Type/ObjectType.php: -------------------------------------------------------------------------------- 1 | 7 | * 8 | * This source file is subject to the MIT license that is bundled 9 | * with this source code in the file LICENSE. 10 | */ 11 | 12 | namespace Mongator\Type; 13 | use MongoDB\Model\BSONDocument; 14 | 15 | /** 16 | * ObjectType. 17 | * 18 | * @author Adam.Balint 19 | * 20 | * @api 21 | */ 22 | class ObjectType extends ArrayObjectType 23 | { 24 | /** 25 | * {@inheritdoc} 26 | */ 27 | public function toMongo($value) 28 | { 29 | if(empty($value)) $value = []; 30 | else if(!is_array($value)) $value = [$value]; 31 | 32 | return new BSONDocument($value); 33 | } 34 | 35 | /** 36 | * {@inheritdoc} 37 | */ 38 | public function toPHP($value) 39 | { 40 | /** 41 | * @var $value BSONDocument 42 | */ 43 | return ArrayObjectType::BSONToArrayRecursive($value); 44 | } 45 | 46 | /** 47 | * {@inheritdoc} 48 | */ 49 | public function toMongoInString() 50 | { 51 | return '%to% = %from%; if (empty(%to%)) { %to% = []; } elseif (!is_array(%to%)) { %to% = [%to%]; } %to% = new \MongoDB\Model\BSONDocument(%to%);'; 52 | } 53 | 54 | /** 55 | * {@inheritdoc} 56 | */ 57 | public function toPHPInString() 58 | { 59 | return '%to% = \Mongator\Type\ArrayObjectType::BSONToArrayRecursive(%from%);'; 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /src/Mongator/Type/ArrayType.php: -------------------------------------------------------------------------------- 1 | 7 | * 8 | * This source file is subject to the MIT license that is bundled 9 | * with this source code in the file LICENSE. 10 | */ 11 | 12 | namespace Mongator\Type; 13 | use MongoDB\Model\BSONArray; 14 | 15 | /** 16 | * ArrayType. 17 | * 18 | * @author Adam.Balint 19 | * 20 | * @api 21 | */ 22 | class ArrayType extends ArrayObjectType 23 | { 24 | /** 25 | * {@inheritdoc} 26 | */ 27 | public function toMongo($value) 28 | { 29 | if(empty($value)) $value = []; 30 | else if(!is_array($value)) $value = [$value]; 31 | 32 | return new BSONArray(array_values($value)); 33 | } 34 | 35 | /** 36 | * {@inheritdoc} 37 | */ 38 | public function toPHP($value) 39 | { 40 | /** 41 | * @var $value BSONArray 42 | */ 43 | return ArrayObjectType::BSONToArrayRecursive($value); 44 | } 45 | 46 | /** 47 | * {@inheritdoc} 48 | */ 49 | public function toMongoInString() 50 | { 51 | return '%to% = %from%; if (empty(%to%)) { %to% = []; } elseif (!is_array(%to%)) { %to% = [%to%]; } %to% = new \MongoDB\Model\BSONArray(array_values(%to%));'; 52 | } 53 | 54 | /** 55 | * {@inheritdoc} 56 | */ 57 | public function toPHPInString() 58 | { 59 | return '%to% = \Mongator\Type\ArrayObjectType::BSONToArrayRecursive(%from%);'; 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /src/Mongator/Type/DateType.php: -------------------------------------------------------------------------------- 1 | 7 | * 8 | * This source file is subject to the MIT license that is bundled 9 | * with this source code in the file LICENSE. 10 | */ 11 | 12 | namespace Mongator\Type; 13 | 14 | 15 | /** 16 | * DateType. 17 | * 18 | * @author Pablo Díez 19 | * 20 | * @api 21 | */ 22 | class DateType extends Type 23 | { 24 | /** 25 | * {@inheritdoc} 26 | */ 27 | public function toMongo($value) 28 | { 29 | if (is_string($value)) { 30 | $value = new \DateTime($value); 31 | } 32 | 33 | return new UTCDateTime($value); 34 | } 35 | 36 | /** 37 | * {@inheritdoc} 38 | */ 39 | public function toPHP($value) 40 | { 41 | $date = new \DateTime(); 42 | $date->setTimestamp($value->sec)->setTimeZone(new \DateTimeZone( date_default_timezone_get())); 43 | 44 | return $date; 45 | } 46 | 47 | /** 48 | * {@inheritdoc} 49 | */ 50 | public function toMongoInString() 51 | { 52 | return "%to% = %from%; if (is_string(%from%)) { %to% = new \\DateTime(%from% ?: date('r',0)); } %to% = new \\MongoDB\\BSON\\UTCDateTime(%to%); "; 53 | } 54 | 55 | /** 56 | * {@inheritdoc} 57 | */ 58 | public function toPHPInString() 59 | { 60 | return '%to% = %from%->toDateTime()->setTimeZone(new \DateTimeZone( date_default_timezone_get()));'; 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /composer.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "mongator/mongator", 3 | "type": "library", 4 | "description": "Mongator is a easy, powerful and ultrafast ODM for PHP and MongoDB. (forked from Mandango project)", 5 | "keywords": [ 6 | "odm", 7 | "mongodb" 8 | ], 9 | "homepage": "http://mongator.com", 10 | "license": "MIT", 11 | "authors": [ 12 | { 13 | "name": "Máximo Cuadros", 14 | "email": "mcuadros@gmail.com" 15 | }, 16 | { 17 | "name": "Daniel Ripollés", 18 | "email": "daniel@yunait.com" 19 | }, 20 | { 21 | "name": "Pablo Díez", 22 | "email": "pablodip@gmail.com" 23 | } 24 | ], 25 | "repositories": [ 26 | { 27 | "type": "git", 28 | "url": "https://github.com/Blazemeter/mondator.git" 29 | } 30 | ], 31 | "require": { 32 | "php": "^8.1", 33 | "mongator/mondator": "dev-master", 34 | "symfony/event-dispatcher": "^5.4", 35 | "mongodb/mongodb": "^1.1" 36 | }, 37 | "require-dev": { 38 | "phpunit/phpunit": "^10.5" 39 | }, 40 | "suggest": { 41 | "ext-apc": "Allow caching on APC", 42 | "ext-redis": "Allow caching on Redis", 43 | "ext-memcached": "Allow caching on Memcached" 44 | }, 45 | "autoload": { 46 | "psr-0": { 47 | "Mongator\\": "src/" 48 | } 49 | }, 50 | "extra": { 51 | "branch-alias": { 52 | "dev-master": "3.x-dev" 53 | } 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /tests/Model/Element.php: -------------------------------------------------------------------------------- 1 | events; 16 | } 17 | 18 | public function clearEvents() 19 | { 20 | $this->events = array(); 21 | 22 | return $this; 23 | } 24 | 25 | public function setEventPrefix($prefix) 26 | { 27 | $this->eventPrefix = $prefix; 28 | 29 | return $this; 30 | } 31 | 32 | public function getEventPrefix() 33 | { 34 | return $this->eventPrefix; 35 | } 36 | 37 | protected function elementPreInsert() 38 | { 39 | $this->events[] = $this->eventPrefix.'ElementPreInserting'; 40 | } 41 | 42 | protected function elementPostInsert() 43 | { 44 | $this->events[] = $this->eventPrefix.'ElementPostInserting'; 45 | } 46 | 47 | protected function elementPreUpdate() 48 | { 49 | $this->events[] = $this->eventPrefix.'ElementPreUpdating'; 50 | } 51 | 52 | protected function elementPostUpdate() 53 | { 54 | $this->events[] = $this->eventPrefix.'ElementPostUpdating'; 55 | } 56 | 57 | protected function elementPreDelete() 58 | { 59 | $this->events[] = $this->eventPrefix.'ElementPreDeleting'; 60 | } 61 | 62 | protected function elementPostDelete() 63 | { 64 | $this->events[] = $this->eventPrefix.'ElementPostDeleting'; 65 | } 66 | } 67 | -------------------------------------------------------------------------------- /tests/Model/Events.php: -------------------------------------------------------------------------------- 1 | events; 16 | } 17 | 18 | public function clearEvents() 19 | { 20 | $this->events = array(); 21 | 22 | return $this; 23 | } 24 | 25 | public function setMyEventPrefix($prefix) 26 | { 27 | $this->myEventPrefix = $prefix; 28 | 29 | return $this; 30 | } 31 | 32 | public function getMyEventPrefix() 33 | { 34 | return $this->myEventPrefix; 35 | } 36 | 37 | public function addEvent($id) 38 | { 39 | $this->events[] = $this->myEventPrefix.$id.(int)$this->isNew().(int)$this->isModified(); 40 | } 41 | 42 | protected function myPreInsert() 43 | { 44 | $this->addEvent('PreInserting'); 45 | } 46 | 47 | protected function myPostInsert() 48 | { 49 | $this->addEvent('PostInserting'); 50 | } 51 | 52 | protected function myPreUpdate() 53 | { 54 | $this->addEvent('PreUpdating'); 55 | $this->setName('preUpdating'); 56 | } 57 | 58 | protected function myPostUpdate() 59 | { 60 | $this->addEvent('PostUpdating'); 61 | } 62 | 63 | protected function myPreDelete() 64 | { 65 | $this->addEvent('PreDeleting'); 66 | } 67 | 68 | protected function myPostDelete() 69 | { 70 | $this->addEvent('PostDeleting'); 71 | } 72 | } 73 | 74 | -------------------------------------------------------------------------------- /tests/Mongator/Tests/Type/RawTypeTest.php: -------------------------------------------------------------------------------- 1 | 7 | * 8 | * This source file is subject to the MIT license that is bundled 9 | * with this source code in the file LICENSE. 10 | */ 11 | 12 | namespace Mongator\Tests\Type; 13 | 14 | use Mongator\Type\RawType; 15 | 16 | class RawTypeTest extends TestCase 17 | { 18 | /** 19 | * @dataProvider provider 20 | */ 21 | public function testToMongo($value) 22 | { 23 | $type = new RawType(); 24 | $this->assertSame($value, $type->toMongo($value)); 25 | } 26 | 27 | /** 28 | * @dataProvider provider 29 | */ 30 | public function testToPHP($value) 31 | { 32 | $type = new RawType(); 33 | $this->assertSame($value, $type->toPHP($value)); 34 | } 35 | 36 | /** 37 | * @dataProvider provider 38 | */ 39 | public function testToMongoInString($value) 40 | { 41 | $type = new RawType(); 42 | $function = $this->getTypeFunction($type->toMongoInString()); 43 | 44 | $this->assertSame($value, $function($value)); 45 | } 46 | 47 | /** 48 | * @dataProvider provider 49 | */ 50 | public function testToPHPInString($value) 51 | { 52 | $type = new RawType(); 53 | $function = $this->getTypeFunction($type->toPHPInString()); 54 | 55 | $this->assertSame($value, $function($value)); 56 | } 57 | 58 | public function provider() 59 | { 60 | return array( 61 | array(array('foo' => 'bar')), 62 | array(new \DateTime()), 63 | ); 64 | } 65 | } 66 | -------------------------------------------------------------------------------- /src/Mongator/Extension/templates/Core/DocumentResetGroups.php.twig: -------------------------------------------------------------------------------- 1 | data['referencesMany']['{{ name }}'])) { 11 | $this->data['referencesMany']['{{ name }}']->reset(); 12 | } 13 | {% endfor %} 14 | {# embeddeds one #} 15 | {% for name, embedded in config_class.embeddedsOne %} 16 | {% if config_classes[embedded.class]['_has_groups'] %} 17 | if (isset($this->data['embeddedsOne']['{{ name }}'])) { 18 | $this->data['embeddedsOne']['{{ name }}']->resetGroups(); 19 | } 20 | {% endif %} 21 | {% endfor %} 22 | {# embeddeds many #} 23 | {% for name, embedded in config_class.embeddedsMany %} 24 | {% if config_classes[embedded.class]['_has_groups'] %} 25 | if (isset($this->data['embeddedsMany']['{{ name }}'])) { 26 | $group = $this->data['embeddedsMany']['{{ name }}']; 27 | foreach (array_merge($group->getAdd(), $group->getRemove()) as $document) { 28 | $document->resetGroups(); 29 | } 30 | if ($group->isSavedInitialized()) { 31 | foreach ($group->getSaved() as $document) { 32 | $document->resetGroups(); 33 | } 34 | } 35 | $group->reset(); 36 | } 37 | {% else %} 38 | if (isset($this->data['embeddedsMany']['{{ name }}'])) { 39 | $this->data['embeddedsMany']['{{ name }}']->reset(); 40 | } 41 | {% endif %} 42 | {% endfor %} 43 | } 44 | -------------------------------------------------------------------------------- /tests/Mongator/Tests/Type/BinDataTypeTest.php: -------------------------------------------------------------------------------- 1 | 7 | * 8 | * This source file is subject to the MIT license that is bundled 9 | * with this source code in the file LICENSE. 10 | */ 11 | 12 | namespace Mongator\Tests\Type; 13 | 14 | use Mongator\Type\BinDataType; 15 | 16 | class BinDataTypeTest extends TestCase 17 | { 18 | public function testToMongo() 19 | { 20 | $type = new BinDataType(); 21 | $this->assertEquals(new \MongoBinData('123', \MongoBinData::BYTE_ARRAY), $type->toMongo('123')); 22 | $this->assertEquals(new \MongoBinData(file_get_contents(__FILE__), \MongoBinData::BYTE_ARRAY), $type->toMongo(__FILE__)); 23 | } 24 | 25 | public function testToPHP() 26 | { 27 | $type = new BinDataType(); 28 | $this->assertSame('123', $type->toPHP(new \MongoBinData('123', \MongoBinData::BYTE_ARRAY))); 29 | } 30 | 31 | public function testToMongoInString() 32 | { 33 | $type = new BinDataType(); 34 | $function = $this->getTypeFunction($type->toMongoInString()); 35 | 36 | $this->assertEquals(new \MongoBinData('123', \MongoBinData::BYTE_ARRAY), $function('123')); 37 | $this->assertEquals(new \MongoBinData(file_get_contents(__FILE__), \MongoBinData::BYTE_ARRAY), $function(__FILE__)); 38 | } 39 | 40 | public function testToPHPInString() 41 | { 42 | $type = new BinDataType(); 43 | $function = $this->getTypeFunction($type->toPHPInString()); 44 | 45 | $this->assertSame('123', $function(new \MongoBinData('123', \MongoBinData::BYTE_ARRAY))); 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /src/Mongator/Query/CachedQuery.php: -------------------------------------------------------------------------------- 1 | 7 | * 8 | * This source file is subject to the MIT license that is bundled 9 | * with this source code in the file LICENSE. 10 | */ 11 | 12 | namespace Mongator\Query; 13 | 14 | abstract class CachedQuery extends Query 15 | { 16 | protected $count; 17 | 18 | /** 19 | * Returns the data in cache. 20 | * 21 | * @return array|null The fields in cache, or null if there is not. 22 | */ 23 | public function getDataCache() 24 | { 25 | $key = $this->generateKey(); 26 | 27 | return $this->getRepository()->getMongator()->getDataCache()->get($key); 28 | } 29 | 30 | public function setDataCache($data) 31 | { 32 | $repository = $this->getRepository(); 33 | $key = $this->generateKey(); 34 | $metadata = $repository->getMetadata(); 35 | 36 | return $repository->getMongator()->getDataCache()->set($key, $data, (int) $metadata['cache']['ttl']); 37 | } 38 | 39 | public function execute() 40 | { 41 | $this->count = false; 42 | 43 | if ( $cache = $this->getDataCache() ) { 44 | return $cache; 45 | } 46 | 47 | $result = parent::execute(); 48 | $this->setDataCache($result); 49 | 50 | return $result; 51 | } 52 | 53 | public function count() 54 | { 55 | $this->count = true; 56 | 57 | if ( $count = $this->getDataCache() ) { 58 | return $count; 59 | } 60 | 61 | $count = parent::execute()->count(); 62 | $this->setDataCache($count); 63 | 64 | return $count; 65 | } 66 | 67 | } 68 | -------------------------------------------------------------------------------- /src/Mongator/Query/Chunk.php: -------------------------------------------------------------------------------- 1 | set($sortFields, $page, $pageSize); 14 | } 15 | 16 | public function set($sortFields, $page, $pageSize) 17 | { 18 | if (($sortFields !== null) && !is_array($sortFields)) 19 | $sortFields = array($sortFields => 1); 20 | 21 | $this->sortFields = $sortFields; 22 | $this->page = $page; 23 | $this->pageSize = $pageSize; 24 | 25 | return $this; 26 | } 27 | 28 | public function getResult(Query $query) 29 | { 30 | $this->applyTo($query); 31 | 32 | $result = $this->createChunkResult($query->all()); 33 | $result->setTotal(function() use ($query) { 34 | return $query->count(); 35 | }); 36 | 37 | return $result; 38 | } 39 | 40 | private function applyTo(Query $query) 41 | { 42 | if ($this->sortFields !== null) 43 | $query->sort($this->sortFields); 44 | 45 | if ($this->page !== null) 46 | $query 47 | ->skip($this->pageSize * $this->page) 48 | ->limit($this->pageSize); 49 | 50 | return $query; 51 | } 52 | 53 | protected function createChunkResult($data) 54 | { 55 | return new ChunkResult($data); 56 | } 57 | 58 | private function applySort($query) 59 | { 60 | if ($this->sortFields === null) return $query; 61 | return $query->sort($this->sortFields); 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /tests/Mongator/Tests/Logger/LoggableMongoCursorTest.php: -------------------------------------------------------------------------------- 1 | 7 | * 8 | * This source file is subject to the MIT license that is bundled 9 | * with this source code in the file LICENSE. 10 | */ 11 | 12 | namespace Mongator\Tests\Logger; 13 | 14 | use Mongator\Tests\TestCase; 15 | use Mongator\Logger\LoggableMongo; 16 | use Mongator\Logger\LoggableMongoCursor; 17 | 18 | class LoggableMongoCursorTest extends TestCase 19 | { 20 | protected $log; 21 | 22 | protected function setUp(): void 23 | { 24 | if (!class_exists('Mongo')) { 25 | $this->markTestSkipped('Mongo is not available.'); 26 | } 27 | } 28 | 29 | public function testConstructorAndGetCollection() 30 | { 31 | $mongo = new LoggableMongo(); 32 | $db = $mongo->selectDB('Mongator_logger'); 33 | $collection = $db->selectCollection('Mongator_logger_collection'); 34 | 35 | $cursor = new LoggableMongoCursor($collection); 36 | 37 | $this->assertSame($collection, $cursor->getCollection()); 38 | } 39 | 40 | public function testLog() 41 | { 42 | $mongo = new LoggableMongo(); 43 | $mongo->setLoggerCallable(array($this, 'log')); 44 | $db = $mongo->selectDB('Mongator_logger'); 45 | $collection = $db->selectCollection('Mongator_logger_collection'); 46 | $cursor = $collection->find(); 47 | 48 | $cursor->log($log = array('foo' => 'bar')); 49 | 50 | $this->assertSame(array_merge(array( 51 | 'database' => 'Mongator_logger', 52 | 'collection' => 'Mongator_logger_collection', 53 | ), $log), $this->log); 54 | } 55 | 56 | public function log(array $log) 57 | { 58 | $this->log = $log; 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /tests/Mongator/Tests/Logger/LoggableMongoGridFSCursorTest.php: -------------------------------------------------------------------------------- 1 | 7 | * 8 | * This source file is subject to the MIT license that is bundled 9 | * with this source code in the file LICENSE. 10 | */ 11 | 12 | namespace Mongator\Tests\Logger; 13 | 14 | use Mongator\Tests\TestCase; 15 | use Mongator\Logger\LoggableMongo; 16 | use Mongator\Logger\LoggableMongoGridFSCursor; 17 | 18 | class LoggableMongoGridFSCursorTest extends TestCase 19 | { 20 | protected $log; 21 | 22 | protected function setUp(): void 23 | { 24 | if (!class_exists('Mongo')) { 25 | $this->markTestSkipped('Mongo is not available.'); 26 | } 27 | } 28 | 29 | public function testConstructorAndGetCollection() 30 | { 31 | $mongo = new LoggableMongo(); 32 | $db = $mongo->selectDB('Mongator_logger'); 33 | $grid = $db->getGridFS('Mongator_logger_grid'); 34 | 35 | $cursor = new LoggableMongoGridFSCursor($grid); 36 | 37 | $this->assertSame($grid, $cursor->getGrid()); 38 | } 39 | 40 | public function testLog() 41 | { 42 | $mongo = new LoggableMongo(); 43 | $mongo->setLoggerCallable(array($this, 'log')); 44 | $db = $mongo->selectDB('Mongator_logger'); 45 | $grid = $db->getGridFS('Mongator_logger_grid'); 46 | $cursor = $grid->find(); 47 | 48 | $cursor->log($log = array('foo' => 'bar')); 49 | 50 | $this->assertSame(array_merge(array( 51 | 'database' => 'Mongator_logger', 52 | 'collection' => 'Mongator_logger_grid.files', 53 | 'gridfs' => 1, 54 | ), $log), $this->log); 55 | } 56 | 57 | public function log(array $log) 58 | { 59 | $this->log = $log; 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /tests/Mongator/Tests/Extension/DocumentArrayAccessTest.php: -------------------------------------------------------------------------------- 1 | 7 | * 8 | * This source file is subject to the MIT license that is bundled 9 | * with this source code in the file LICENSE. 10 | */ 11 | 12 | namespace Mongator\Tests\Extension; 13 | 14 | use Mongator\Tests\TestCase; 15 | 16 | class DocumentArrayAccessTest extends TestCase 17 | { 18 | /** 19 | * @expectedException \LogicException 20 | */ 21 | public function testOffsetExists() 22 | { 23 | $article = $this->mongator->create('Model\Article'); 24 | isset($article['title']); 25 | } 26 | 27 | public function testOffsetSet() 28 | { 29 | $article = $this->mongator->create('Model\Article'); 30 | $article['title'] = 'foo'; 31 | $this->assertSame('foo', $article->getTitle()); 32 | } 33 | 34 | /** 35 | * @expectedException \InvalidArgumentException 36 | */ 37 | public function testOffsetSetNameNotExists() 38 | { 39 | $article = $this->mongator->create('Model\Article'); 40 | $article['no'] = 'foo'; 41 | } 42 | 43 | public function testOffsetGet() 44 | { 45 | $article = $this->mongator->create('Model\Article'); 46 | $article->setTitle('bar'); 47 | $this->assertSame('bar', $article['title']); 48 | } 49 | 50 | /** 51 | * @expectedException \InvalidArgumentException 52 | */ 53 | public function testOffsetGetNameNotExists() 54 | { 55 | $article = $this->mongator->create('Model\Article'); 56 | $article['no']; 57 | } 58 | 59 | /** 60 | * @expectedException \LogicException 61 | */ 62 | public function testOffsetUnset() 63 | { 64 | $article = $this->mongator->create('Model\Article'); 65 | unset($article['title']); 66 | } 67 | } 68 | -------------------------------------------------------------------------------- /tests/Mongator/Benchmarks/UpdatingEvent.php: -------------------------------------------------------------------------------- 1 | 7 | * 8 | * This source file is subject to the MIT license that is bundled 9 | * with this source code in the file LICENSE. 10 | */ 11 | 12 | namespace Mongator\Benchmarks; 13 | 14 | use MongoClient; 15 | use MongoDB\BSON\ObjectID; 16 | 17 | class UpdatingEvent extends AthleticEvent 18 | { 19 | private $simpleDocument; 20 | 21 | protected function classSetUp() 22 | { 23 | parent::classSetUp(); 24 | $this->simpleDocument = $this->buildSimpleDocument()->save(); 25 | $this->complexDocument = $this->buildComplexDocument()->save(); 26 | } 27 | 28 | /** 29 | * @iterations 500 30 | */ 31 | public function simpleDocument() 32 | { 33 | $this->setBasicSimpleFields($this->simpleDocument); 34 | $this->simpleDocument->save(); 35 | } 36 | 37 | /** 38 | * @iterations 500 39 | */ 40 | public function simpleNestedDocument() 41 | { 42 | for ($i=0; $i < 50; $i++) { 43 | $embeddeds[] = $this->buildSimpleEmbedded(); 44 | } 45 | 46 | $this->simpleDocument->getNested()->replace($embeddeds); 47 | $this->simpleDocument->save(); 48 | } 49 | 50 | /** 51 | * @iterations 500 52 | */ 53 | public function complexDocument() 54 | { 55 | $this->setBasicComplexFields($this->complexDocument); 56 | $this->complexDocument->save(); 57 | } 58 | 59 | /** 60 | * @iterations 500 61 | */ 62 | public function complexNestedDocument() 63 | { 64 | for ($i=0; $i < 50; $i++) { 65 | $embeddeds[] = $this->buildComplexEmbedded(); 66 | } 67 | 68 | $this->complexDocument->getNested()->replace($embeddeds); 69 | $this->complexDocument->save(); 70 | } 71 | } -------------------------------------------------------------------------------- /src/Mongator/IdentityMapInterface.php: -------------------------------------------------------------------------------- 1 | 7 | * 8 | * This source file is subject to the MIT license that is bundled 9 | * with this source code in the file LICENSE. 10 | */ 11 | 12 | namespace Mongator; 13 | 14 | use Mongator\Document\Document; 15 | 16 | /** 17 | * IdentityMapInterface. 18 | * 19 | * @author Pablo Díez 20 | * 21 | * @api 22 | */ 23 | interface IdentityMapInterface 24 | { 25 | /** 26 | * Set a document. 27 | * 28 | * @param mixed $id The document Id. 29 | * @param Document $document The document. 30 | * 31 | * @api 32 | */ 33 | public function set($id, Document $document); 34 | 35 | /** 36 | * Returns if exists a document. 37 | * 38 | * @param mixed $id The document id. 39 | * 40 | * @return boolean If exists or not the document. 41 | * 42 | * @api 43 | */ 44 | public function has($id); 45 | 46 | /** 47 | * Returns a document. 48 | * 49 | * @param mixed $id The document Id. 50 | * 51 | * @return Document The document. 52 | * 53 | * @api 54 | */ 55 | public function get($id); 56 | 57 | /** 58 | * Returns all documents. 59 | * 60 | * @return array The documents. 61 | * 62 | * @api 63 | */ 64 | public function all(); 65 | 66 | /** 67 | * Returns all the documents by reference. 68 | * 69 | * @return array The documents by reference. 70 | * 71 | * @api 72 | */ 73 | function &allByReference(); 74 | 75 | /** 76 | * Remove a document. 77 | * 78 | * @param mixed $id The document Id. 79 | * 80 | * @api 81 | */ 82 | public function remove($id); 83 | 84 | /** 85 | * Clear the documents. 86 | * 87 | * @api 88 | */ 89 | public function clear(); 90 | } 91 | -------------------------------------------------------------------------------- /src/Mongator/Extension/templates/Core/DocumentEmbeddedsMany.php.twig: -------------------------------------------------------------------------------- 1 | data['embeddedsMany']['{{ name }}'])) { 14 | $this->data['embeddedsMany']['{{ name }}'] = $embedded = new \Mongator\Group\EmbeddedGroup('{{ embedded.class }}'); 15 | {# not embedded #} 16 | {% if not config_class.isEmbedded %} 17 | $embedded->setRootAndPath($this, '{{ name }}'); 18 | {# embedded #} 19 | {% else %} 20 | if ($rap = $this->getRootAndPath()) { 21 | $embedded->setRootAndPath($rap['root'], $rap['path'].'.{{ name }}'); 22 | } 23 | {% endif %} 24 | } 25 | 26 | return $this->data['embeddedsMany']['{{ name }}']; 27 | } 28 | 29 | /** 30 | * Adds documents to the "{{ name }}" embeddeds many. 31 | * 32 | * @param mixed $documents A document or an array or documents. 33 | * 34 | * @return \{{ class }} The document (fluent interface). 35 | */ 36 | public function add{{ name|ucfirst }}($documents) 37 | { 38 | $this->get{{ name|ucfirst }}()->add($documents); 39 | 40 | return $this; 41 | } 42 | 43 | /** 44 | * Removes documents to the "{{ name }}" embeddeds many. 45 | * 46 | * @param mixed $documents A document or an array or documents. 47 | * 48 | * @return \{{ class }} The document (fluent interface). 49 | */ 50 | public function remove{{ name|ucfirst }}($documents) 51 | { 52 | $this->get{{ name|ucfirst }}()->remove($documents); 53 | 54 | return $this; 55 | } 56 | {% endif %} 57 | {% endfor %} 58 | -------------------------------------------------------------------------------- /src/Mongator/Cache/MemcachedCache.php: -------------------------------------------------------------------------------- 1 | 7 | * 8 | * This source file is subject to the MIT license that is bundled 9 | * with this source code in the file LICENSE. 10 | */ 11 | 12 | namespace Mongator\Cache; 13 | 14 | /** 15 | * AbstractCache. 16 | * 17 | * @author Máximo Cuadros 18 | */ 19 | class MemcachedCache extends AbstractCache 20 | { 21 | private $memcached; 22 | private $keys = array(); 23 | 24 | /** 25 | * Constructor. 26 | * 27 | * @param Memcache $memcache the memcache instance 28 | */ 29 | public function __construct(\Memcached $memcached) 30 | { 31 | $this->memcached = $memcached; 32 | } 33 | 34 | /** 35 | * {@inheritdoc} 36 | */ 37 | public function has($key) 38 | { 39 | return (boolean) $this->memcached->get($key); 40 | } 41 | 42 | /** 43 | * {@inheritdoc} 44 | */ 45 | public function set($key, $value, $ttl = 0) 46 | { 47 | $this->keys[] = $key; 48 | $content = $this->pack($key, $value, $ttl); 49 | 50 | $string = serialize($content); 51 | 52 | if ( (int) $ttl != 0 ) $ttl = time() + $ttl; 53 | $this->memcached->set($key, $string, (int) $ttl); 54 | } 55 | 56 | /** 57 | * {@inheritdoc} 58 | */ 59 | public function remove($key) 60 | { 61 | return (boolean) $this->memcached->delete($key); 62 | } 63 | 64 | /** 65 | * {@inheritdoc} 66 | */ 67 | public function clear() 68 | { 69 | foreach ($this->keys as $key) { 70 | $this->memcached->delete($key); 71 | } 72 | } 73 | 74 | /** 75 | * {@inheritdoc} 76 | */ 77 | public function info($key) 78 | { 79 | if ( !$content = $this->memcached->get($key) ) { 80 | return false; 81 | } 82 | 83 | return unserialize($content); 84 | } 85 | } 86 | -------------------------------------------------------------------------------- /tests/Mongator/Tests/ArchiveTest.php: -------------------------------------------------------------------------------- 1 | 7 | * 8 | * This source file is subject to the MIT license that is bundled 9 | * with this source code in the file LICENSE. 10 | */ 11 | 12 | namespace Mongator\Tests; 13 | 14 | use Mongator\Archive; 15 | 16 | class ArchiveTest extends TestCase 17 | { 18 | public function testHasGetSet() 19 | { 20 | $archive = new Archive(); 21 | 22 | $this->assertFalse($archive->has('field1')); 23 | $this->assertFalse($archive->has('field2')); 24 | $this->assertFalse($archive->has('field3')); 25 | 26 | $archive->set('field1', 'foo'); 27 | $archive->set('field3', 'bar'); 28 | $archive->set('field2', 'ups'); 29 | 30 | $this->assertTrue($archive->has('field1')); 31 | $this->assertTrue($archive->has('field3')); 32 | $this->assertTrue($archive->has('field2')); 33 | 34 | $this->assertSame('foo', $archive->get('field1')); 35 | $this->assertSame('bar', $archive->get('field3')); 36 | $this->assertSame('ups', $archive->get('field2')); 37 | 38 | $archive->remove('field1'); 39 | $this->assertFalse($archive->has('field1')); 40 | $this->assertTrue($archive->has('field3')); 41 | $this->assertTrue($archive->has('field2')); 42 | } 43 | 44 | public function testGetByRef() 45 | { 46 | $archive = new Archive(); 47 | 48 | $fieldKey =& $archive->getByRef('field1', array()); 49 | $this->assertSame(array(), $fieldKey); 50 | 51 | $fieldKey['foo'] = 'bar'; 52 | $this->assertSame($fieldKey, $archive->get('field1')); 53 | } 54 | 55 | public function testGetOrDefault() 56 | { 57 | $archive = new Archive(); 58 | 59 | $this->assertSame('foobar', $archive->getOrDefault('field1', 'foobar')); 60 | 61 | $archive->set('field2', 'ups'); 62 | $this->assertSame('ups', $archive->getOrDefault('field2', 'foobar')); 63 | } 64 | } 65 | -------------------------------------------------------------------------------- /src/Mongator/IdentityMap.php: -------------------------------------------------------------------------------- 1 | 7 | * 8 | * This source file is subject to the MIT license that is bundled 9 | * with this source code in the file LICENSE. 10 | */ 11 | 12 | namespace Mongator; 13 | 14 | use Mongator\Document\Document; 15 | 16 | /** 17 | * The identity map class. 18 | * 19 | * @author Pablo Díez 20 | * 21 | * @api 22 | */ 23 | class IdentityMap implements IdentityMapInterface 24 | { 25 | private $documents; 26 | 27 | /** 28 | * Constructor. 29 | * 30 | * @api 31 | */ 32 | public function __construct() { 33 | $this->documents = []; 34 | } 35 | 36 | /** 37 | * {@inheritdoc} 38 | */ 39 | public function set($id, Document $document) { 40 | $this->documents[$this->serialize($id)] = $document; 41 | } 42 | 43 | /** 44 | * {@inheritdoc} 45 | */ 46 | public function has($id) { 47 | return isset($this->documents[$this->serialize($id)]); 48 | } 49 | 50 | /** 51 | * {@inheritdoc} 52 | */ 53 | public function get($id) { 54 | return $this->documents[$this->serialize($id)]; 55 | } 56 | 57 | /** 58 | * {@inheritdoc} 59 | */ 60 | public function all() { 61 | return $this->documents; 62 | } 63 | 64 | /** 65 | * {@inheritdoc} 66 | */ 67 | public function &allByReference() { 68 | return $this->documents; 69 | } 70 | 71 | /** 72 | * {@inheritdoc} 73 | */ 74 | public function remove($id) { 75 | unset($this->documents[$this->serialize($id)]); 76 | } 77 | 78 | /** 79 | * {@inheritdoc} 80 | */ 81 | public function clear() { 82 | $this->documents = []; 83 | } 84 | 85 | /** 86 | * @param $id 87 | * 88 | * @return string 89 | */ 90 | public function serialize($id) { 91 | if (is_array($id) || (is_object($id) && !($id instanceof \MongoId))) { 92 | $id = md5(serialize($id)); 93 | } 94 | 95 | return (string) $id; 96 | } 97 | } 98 | -------------------------------------------------------------------------------- /tests/Mongator/Tests/Type/DateTypeTest.php: -------------------------------------------------------------------------------- 1 | 7 | * 8 | * This source file is subject to the MIT license that is bundled 9 | * with this source code in the file LICENSE. 10 | */ 11 | 12 | namespace Mongator\Tests\Type; 13 | 14 | use Mongator\Type\DateType; 15 | use MongoDB\BSON\UTCDateTime; 16 | 17 | class DateTypeTest extends TestCase 18 | { 19 | public function testToMongo() 20 | { 21 | $type = new DateType(); 22 | 23 | $time = time(); 24 | $this->assertEquals(new UTCDateTime($time), $type->toMongo($time)); 25 | 26 | $date = new \DateTime(); 27 | $date->setTimestamp($time); 28 | $this->assertEquals(new UTCDateTime($time), $type->toMongo($date)); 29 | 30 | $string = '2010-02-20'; 31 | $this->assertEquals(new UTCDateTime(strtotime($string)), $type->toMongo($string)); 32 | } 33 | 34 | public function testToPHP() 35 | { 36 | $type = new DateType(); 37 | 38 | $time = time(); 39 | $date = new \DateTime(); 40 | $date->setTimestamp($time); 41 | 42 | $this->assertEquals($date, $type->toPHP(new UTCDateTime($time))); 43 | } 44 | 45 | public function testToMongoInString() 46 | { 47 | $type = new DateType(); 48 | $function = $this->getTypeFunction($type->toMongoInString()); 49 | 50 | $time = time(); 51 | $this->assertEquals(new UTCDateTime($time), $function($time)); 52 | 53 | $date = new \DateTime(); 54 | $date->setTimestamp($time); 55 | $this->assertEquals(new UTCDateTime($time), $function($date)); 56 | 57 | $string = '2010-02-20'; 58 | $this->assertEquals(new UTCDateTime(strtotime($string)), $function($string)); 59 | } 60 | 61 | public function testToPHPInString() 62 | { 63 | $type = new DateType(); 64 | $function = $this->getTypeFunction($type->toPHPInString()); 65 | 66 | $time = time(); 67 | $date = new \DateTime(); 68 | $date->setTimestamp($time); 69 | 70 | $this->assertEquals($date, $function(new UTCDateTime($time))); 71 | } 72 | } 73 | -------------------------------------------------------------------------------- /src/Mongator/Extension/templates/Core/DocumentRelations.php.twig: -------------------------------------------------------------------------------- 1 | getMongator()->getRepository('{{ relation.class }}')->createQuery(array('{{ relation.reference }}' => $this->getId()))->one(); 12 | } 13 | {% endfor %} 14 | 15 | {% for name, relation in config_class.relationsManyOne %} 16 | /** 17 | * Returns the "{{ name }}" relation many-one. 18 | * 19 | * @return \Mongator\Query\Query The "{{ name }}" relation many-one. 20 | */ 21 | public function get{{ name|ucfirst }}() 22 | { 23 | return $this->getMongator()->getRepository('{{ relation.class }}')->createQuery(array('{{ relation.reference }}' => $this->getId())); 24 | } 25 | {% endfor %} 26 | 27 | {% for name, relation in config_class.relationsManyMany %} 28 | /** 29 | * Returns the "{{ name }}" relation many-many. 30 | * 31 | * @return \Mongator\Query\Query The "{{ name }}" relation many-many. 32 | */ 33 | public function get{{ name|ucfirst }}() 34 | { 35 | return $this->getMongator()->getRepository('{{ relation.class }}')->createQuery(array('{{ relation.reference }}' => $this->getId())); 36 | } 37 | {% endfor %} 38 | 39 | {% for name, relation in config_class.relationsManyThrough %} 40 | /** 41 | * Returns the "{{ name }}" relation many-through. 42 | * 43 | * @return \Mongator\Query\Query The "{{ name }}" relation many-through. 44 | */ 45 | public function get{{ name|ucfirst }}() 46 | { 47 | $ids = array(); 48 | foreach ($this->getMongator()->getRepository('{{ relation.through }}')->getCollection() 49 | ->find(array('{{ relation.local }}' => $this->getId()), array('{{ relation.foreign }}' => 1)) 50 | as $value) { 51 | $ids[] = $value['{{ relation.foreign }}']; 52 | } 53 | 54 | return $this->getMongator()->getRepository('{{ relation.class }}')->createQuery(array('_id' => array('$in' => $ids))); 55 | } 56 | {% endfor %} 57 | -------------------------------------------------------------------------------- /src/Mongator/Extension/templates/Core/DocumentSaveReferences.php.twig: -------------------------------------------------------------------------------- 1 | savingReferences) { 9 | return; 10 | } 11 | 12 | $this->savingReferences = true; 13 | {# references one #} 14 | {% for name, reference in config_class.referencesOne %} 15 | {# not inherited #} 16 | {% if reference.inherited is not defined or not reference.inherited %} 17 | {# not polymorphic #} 18 | {% if reference.class is defined %} 19 | if (isset($this->data['referencesOne']['{{ name }}'])) { 20 | $this->data['referencesOne']['{{ name }}']->save(); 21 | } 22 | {% endif %} 23 | {% endif %} 24 | {% endfor %} 25 | {# references many #} 26 | {% for name, reference in config_class.referencesMany %} 27 | {# not inherited #} 28 | {% if reference.inherited is not defined or not reference.inherited %} 29 | {# not polymorphic #} 30 | {% if reference.class is defined %} 31 | if (isset($this->data['referencesMany']['{{ name }}'])) { 32 | $group = $this->data['referencesMany']['{{ name }}']; 33 | $documents = array(); 34 | foreach ($group->getAdd() as $document) { 35 | $documents[] = $document; 36 | } 37 | if ($group->isSavedInitialized()) { 38 | foreach ($group->getSaved() as $document) { 39 | $documents[] = $document; 40 | } 41 | } 42 | if ($documents) { 43 | $this->getMongator()->getRepository('{{ reference.class }}')->save($documents); 44 | } 45 | } 46 | {% endif %} 47 | {% endif %} 48 | {% endfor %} 49 | {# embeddeds one #} 50 | {% for name, embedded in config_class.embeddedsOne %} 51 | {# not inherited #} 52 | {% if embedded.inherited is not defined or not embedded.inherited %} 53 | {# has references #} 54 | {% if config_classes[embedded.class]['_has_references'] %} 55 | if (isset($this->data['embeddedsOne']['{{ name }}'])) { 56 | $this->data['embeddedsOne']['{{ name }}']->saveReferences(); 57 | } 58 | {% endif %} 59 | {% endif %} 60 | {% endfor %} 61 | $this->savingReferences = false; 62 | } 63 | -------------------------------------------------------------------------------- /src/Mongator/Cache/RedisCache.php: -------------------------------------------------------------------------------- 1 | 7 | * 8 | * This source file is subject to the MIT license that is bundled 9 | * with this source code in the file LICENSE. 10 | */ 11 | 12 | namespace Mongator\Cache; 13 | 14 | /** 15 | * AbstractCache. 16 | * 17 | * @author Máximo Cuadros 18 | */ 19 | class RedisCache extends AbstractCache 20 | { 21 | private $redis; 22 | private $keyPattern; 23 | 24 | /** 25 | * Constructor. 26 | * 27 | * @param Redis $redis the redis instance 28 | * @param string $keyPattern (optional) redis format key, printf format 29 | */ 30 | public function __construct(\Redis $redis, $keyPattern = '{Mongator}{%s}') 31 | { 32 | $this->redis = $redis; 33 | $this->keyPattern = $keyPattern; 34 | } 35 | 36 | private function getRedisKey($key) 37 | { 38 | return sprintf($this->keyPattern, $key); 39 | } 40 | 41 | /** 42 | * {@inheritdoc} 43 | */ 44 | public function has($key) 45 | { 46 | $key = $this->getRedisKey($key); 47 | 48 | return (boolean) $this->redis->exists($key); 49 | } 50 | 51 | /** 52 | * {@inheritdoc} 53 | */ 54 | public function set($key, $value, $ttl = 0) 55 | { 56 | $content = $this->pack($key, $value, $ttl); 57 | $key = $this->getRedisKey($key); 58 | 59 | $string = serialize($content); 60 | if ( (int) $ttl == 0 ) $this->redis->set($key, $string); 61 | else $this->redis->setex($key, $ttl, $string); 62 | } 63 | 64 | /** 65 | * {@inheritdoc} 66 | */ 67 | public function remove($key) 68 | { 69 | $key = $this->getRedisKey($key); 70 | 71 | return (boolean) $this->redis->delete($key); 72 | } 73 | 74 | /** 75 | * {@inheritdoc} 76 | */ 77 | public function clear() 78 | { 79 | $pattern = $this->getRedisKey('*'); 80 | foreach ($this->redis->keys($pattern) as $key) { 81 | $this->redis->delete($key); 82 | } 83 | } 84 | 85 | /** 86 | * {@inheritdoc} 87 | */ 88 | public function info($key) 89 | { 90 | $key = $this->getRedisKey($key); 91 | if ( !$content = $this->redis->get($key) ) { 92 | return false; 93 | } 94 | 95 | return unserialize($content); 96 | } 97 | } 98 | -------------------------------------------------------------------------------- /tests/Mongator/Tests/Logger/LoggableMongoCollectionTest.php: -------------------------------------------------------------------------------- 1 | 7 | * 8 | * This source file is subject to the MIT license that is bundled 9 | * with this source code in the file LICENSE. 10 | */ 11 | 12 | namespace Mongator\Tests\Logger; 13 | 14 | use Mongator\Tests\TestCase; 15 | use Mongator\Logger\LoggableMongo; 16 | use Mongator\Logger\LoggableMongoCollection; 17 | 18 | class LoggableMongoCollectionTest extends TestCase 19 | { 20 | protected $log; 21 | 22 | protected function setUp(): void 23 | { 24 | if (!class_exists('Mongo')) { 25 | $this->markTestSkipped('Mongo is not available.'); 26 | } 27 | } 28 | 29 | public function testConstructorAndGetDB() 30 | { 31 | $mongo = new LoggableMongo(); 32 | $db = $mongo->selectDB('Mongator_logger'); 33 | 34 | $collection = new LoggableMongoCollection($db, 'Mongator_logger_collection'); 35 | 36 | $this->assertSame('Mongator_logger_collection', $collection->getName()); 37 | $this->assertSame($db, $collection->getDB()); 38 | } 39 | 40 | public function testLog() 41 | { 42 | $mongo = new LoggableMongo(); 43 | $mongo->setLoggerCallable(array($this, 'log')); 44 | $db = $mongo->selectDB('Mongator_logger'); 45 | $collection = $db->selectCollection('Mongator_logger_collection'); 46 | 47 | $collection->log($log = array('foo' => 'bar')); 48 | 49 | $this->assertSame(array_merge(array( 50 | 'database' => 'Mongator_logger', 51 | 'collection' => 'Mongator_logger_collection', 52 | ), $log), $this->log); 53 | } 54 | 55 | public function log(array $log) 56 | { 57 | $this->log = $log; 58 | } 59 | 60 | public function testFind() 61 | { 62 | $mongo = new LoggableMongo(); 63 | $db = $mongo->selectDB('Mongator_logger'); 64 | $collection = $db->selectCollection('Mongator_logger_collection'); 65 | 66 | $cursor = $collection->find(); 67 | $this->assertInstanceOf('\Mongator\Logger\LoggableMongoCursor', $cursor); 68 | 69 | $cursor = $collection->find($query = array('foo' => 'bar'), $fields = array('foobar' => 1, 'barfoo' => 1)); 70 | $info = $cursor->info(); 71 | $this->assertSame($query, $info['query']); 72 | $this->assertSame($fields, $info['fields']); 73 | } 74 | } 75 | -------------------------------------------------------------------------------- /tests/Mongator/Tests/Logger/LoggableMongoGridFSTest.php: -------------------------------------------------------------------------------- 1 | 7 | * 8 | * This source file is subject to the MIT license that is bundled 9 | * with this source code in the file LICENSE. 10 | */ 11 | 12 | namespace Mongator\Tests\Logger; 13 | 14 | use Mongator\Tests\TestCase; 15 | use Mongator\Logger\LoggableMongo; 16 | use Mongator\Logger\LoggableMongoGridFS; 17 | 18 | class LoggableMongoGridFSTest extends TestCase 19 | { 20 | protected $log; 21 | 22 | protected function setUp(): void 23 | { 24 | if (!class_exists('Mongo')) { 25 | $this->markTestSkipped('Mongo is not available.'); 26 | } 27 | } 28 | 29 | public function testConstructorAndGetDB() 30 | { 31 | $mongo = new LoggableMongo(); 32 | $db = $mongo->selectDB('Mongator_logger'); 33 | 34 | $grid = new LoggableMongoGridFS($db, 'Mongator_logger_grid'); 35 | 36 | $this->assertSame('Mongator_logger_grid.files', $grid->getName()); 37 | $this->assertSame($db, $grid->getDB()); 38 | } 39 | 40 | public function testLog() 41 | { 42 | $mongo = new LoggableMongo(); 43 | $mongo->setLoggerCallable(array($this, 'log')); 44 | $db = $mongo->selectDB('Mongator_logger'); 45 | $grid = $db->getGridFS('Mongator_logger_grid'); 46 | 47 | $grid->log($log = array('foo' => 'bar')); 48 | 49 | $this->assertSame(array_merge(array( 50 | 'database' => 'Mongator_logger', 51 | 'collection' => 'Mongator_logger_grid.files', 52 | 'gridfs' => 1 53 | ), $log), $this->log); 54 | } 55 | 56 | public function log(array $log) 57 | { 58 | $this->log = $log; 59 | } 60 | 61 | public function testFind() 62 | { 63 | $mongo = new LoggableMongo(); 64 | $mongo->setLoggerCallable(array($this, 'log')); 65 | $db = $mongo->selectDB('Mongator_logger'); 66 | $grid = $db->getGridFS('Mongator_logger_grid'); 67 | 68 | $cursor = $grid->find(); 69 | $this->assertInstanceOf('\Mongator\Logger\LoggableMongoGridFSCursor', $cursor); 70 | 71 | $cursor = $grid->find($query = array('foo' => 'bar'), $fields = array('foobar' => 1, 'barfoo' => 1)); 72 | $info = $cursor->info(); 73 | $this->assertSame($query, $info['query']); 74 | $this->assertSame($fields, $info['fields']); 75 | } 76 | } 77 | -------------------------------------------------------------------------------- /src/Mongator/Group/ReferenceGroup.php: -------------------------------------------------------------------------------- 1 | 7 | * 8 | * This source file is subject to the MIT license that is bundled 9 | * with this source code in the file LICENSE. 10 | */ 11 | 12 | namespace Mongator\Group; 13 | 14 | 15 | /** 16 | * ReferenceGroup. 17 | * 18 | * @author Pablo Díez 19 | * 20 | * @api 21 | */ 22 | class ReferenceGroup extends Group 23 | { 24 | /** 25 | * Constructor. 26 | * 27 | * @param string $documentClass The document class. 28 | * @param \Mongator\Document\AbstractDocument $parent The parent document. 29 | * @param string $field The reference field. 30 | * 31 | * @api 32 | */ 33 | public function __construct($documentClass, $parent, $field) 34 | { 35 | parent::__construct($documentClass); 36 | 37 | $this->getArchive()->set('parent', $parent); 38 | $this->getArchive()->set('field', $field); 39 | } 40 | 41 | /** 42 | * Returns the parent document. 43 | * 44 | * @return \Mongator\Document\AbstractDocument The parent document. 45 | * 46 | * @api 47 | */ 48 | public function getParent() 49 | { 50 | return $this->getArchive()->get('parent'); 51 | } 52 | 53 | /** 54 | * Returns the reference field. 55 | * 56 | * @return string The reference field. 57 | * 58 | * @api 59 | */ 60 | public function getField() 61 | { 62 | return $this->getArchive()->get('field'); 63 | } 64 | 65 | /** 66 | * {@inheritdoc} 67 | */ 68 | protected function doInitializeSavedData() 69 | { 70 | return (array) $this->getParent()->{'get'.ucfirst($this->getField())}(); 71 | } 72 | 73 | /** 74 | * {@inheritdoc} 75 | */ 76 | protected function doInitializeSaved($data) 77 | { 78 | return $this->getParent()->getMongator()->getRepository($this->getDocumentClass())->findById($data); 79 | } 80 | 81 | /** 82 | * Creates and returns a query to query the referenced elements. 83 | * 84 | * @api 85 | */ 86 | public function createQuery() 87 | { 88 | return $this->getParent()->getMongator()->getRepository($this->getDocumentClass())->createQuery(array( 89 | '_id' => array('$in' => $this->doInitializeSavedData()), 90 | )); 91 | } 92 | } 93 | -------------------------------------------------------------------------------- /tests/Mongator/Tests/IdentityMapTest.php: -------------------------------------------------------------------------------- 1 | 7 | * 8 | * This source file is subject to the MIT license that is bundled 9 | * with this source code in the file LICENSE. 10 | */ 11 | 12 | namespace Mongator\Tests; 13 | 14 | use Mongator\IdentityMap; 15 | use MongoDB\BSON\ObjectID; 16 | 17 | class IdentityMapTest extends TestCase 18 | { 19 | public function testGeneral() 20 | { 21 | $articles = array(); 22 | for ($i = 1; $i <= 10; $i ++) { 23 | $articles[$i] = $this->mongator->create('Model\Article')->setId(new ObjectID()); 24 | } 25 | 26 | $identityMap = new IdentityMap(); 27 | 28 | // set 29 | $identityMap->set($articles[1]->getId(), $articles[1]); 30 | $identityMap->set($articles[2]->getId(), $articles[2]); 31 | 32 | // has 33 | $this->assertTrue($identityMap->has($articles[1]->getId())); 34 | $this->assertTrue($identityMap->has($articles[2]->getId())); 35 | $this->assertFalse($identityMap->has($articles[3]->getId())); 36 | $this->assertFalse($identityMap->has($articles[4]->getId())); 37 | 38 | // get 39 | $this->assertSame($articles[1], $identityMap->get($articles[1]->getId())); 40 | $this->assertSame($articles[2], $identityMap->get($articles[2]->getId())); 41 | 42 | // set overwriting 43 | $identityMap->set($articles[2]->getId(), $articles[3]); 44 | $this->assertSame($articles[3], $identityMap->get($articles[2]->getId())); 45 | $identityMap->set($articles[2]->getId(), $articles[2]); 46 | 47 | // all 48 | $this->assertSame(array( 49 | $articles[1]->getId()->__toString() => $articles[1], 50 | $articles[2]->getId()->__toString() => $articles[2], 51 | ), $identityMap->all()); 52 | 53 | // remove 54 | $identityMap->set($articles[4]->getId(), $articles[4]); 55 | $identityMap->set($articles[5]->getId(), $articles[5]); 56 | $identityMap->remove($articles[4]->getId()); 57 | $this->assertSame(array( 58 | $articles[1]->getId()->__toString() => $articles[1], 59 | $articles[2]->getId()->__toString() => $articles[2], 60 | $articles[5]->getId()->__toString() => $articles[5], 61 | ), $identityMap->all()); 62 | 63 | // clear 64 | $identityMap->clear(); 65 | $this->assertSame(array(), $identityMap->all()); 66 | } 67 | } 68 | -------------------------------------------------------------------------------- /src/Mongator/Id/SequenceIdGenerator.php: -------------------------------------------------------------------------------- 1 | 7 | * 8 | * This source file is subject to the MIT license that is bundled 9 | * with this source code in the file LICENSE. 10 | */ 11 | 12 | namespace Mongator\Id; 13 | 14 | /** 15 | * Generates a sequence. 16 | * 17 | * @author Pablo Díez 18 | */ 19 | class SequenceIdGenerator extends BaseIdGenerator 20 | { 21 | /** 22 | * {@inheritdoc} 23 | */ 24 | public function getCode(array $options) 25 | { 26 | $increment = isset($options['increment']) ? $options['increment'] : 1; 27 | $start = isset($options['start']) ? $options['start'] : null; 28 | 29 | // increment 30 | if (!is_int($increment) || 0 === $increment) { 31 | throw new \InvalidArgumentException('The option "increment" must be an integer distinct of 0.'); 32 | } 33 | 34 | // start 35 | if (null === $start) { 36 | $start = $increment > 0 ? 1 : -1; 37 | } elseif (!is_int($start) || 0 === $start) { 38 | throw new \InvalidArgumentException('The option "start" must be an integer distinct of 0.'); 39 | } 40 | 41 | return <<getConnection()->getMongo()->selectDB('admin')->command(array('buildinfo' => true)); 43 | \$mongoVersion = \$serverInfo['version']; 44 | 45 | \$commandResult = \$repository->getConnection()->getMongoDB()->command(array( 46 | 'findandmodify' => 'Mongator_sequence_id_generator', 47 | 'query' => array('_id' => \$repository->getCollectionName()), 48 | 'update' => array('\$inc' => array('sequence' => $increment)), 49 | 'new' => true, 50 | )); 51 | if ( 52 | (version_compare(\$mongoVersion, '2.0', '<') && \$commandResult['ok']) 53 | || 54 | (version_compare(\$mongoVersion, '2.0', '>=') && null !== \$commandResult['value']) 55 | ) { 56 | %id% = \$commandResult['value']['sequence']; 57 | } else { 58 | \$id = array('_id' => \$repository->getCollectionName(), 'sequence' => $start); 59 | \$repository 60 | ->getConnection() 61 | ->getMongoDB() 62 | ->selectCollection('Mongator_sequence_id_generator') 63 | ->insert(\$id); 64 | %id% = $start; 65 | } 66 | EOF; 67 | } 68 | 69 | /** 70 | * {@inheritdoc} 71 | */ 72 | public function getToMongoCode() 73 | { 74 | return <<data['referencesMany']['{{ name }}'])) { 14 | {% if not config_class.isEmbedded %} 15 | if (!$this->isNew()) { 16 | $this->addReferenceCache('{{ name }}'); 17 | } 18 | {% endif %} 19 | $this->data['referencesMany']['{{ name }}'] = new \Mongator\Group\ReferenceGroup('{{ referenceMany.class }}', $this, '{{ referenceMany.field }}'); 20 | } 21 | 22 | return $this->data['referencesMany']['{{ name }}']; 23 | } 24 | {# polymorphic #} 25 | {% else %} 26 | /** 27 | * Returns the "{{ name }}" polymorphic reference. 28 | * 29 | * @return \Mongator\Group\PolymorphicReferenceGroup The reference. 30 | */ 31 | public function get{{ name|ucfirst }}() 32 | { 33 | if (!isset($this->data['referencesMany']['{{ name }}'])) { 34 | $this->data['referencesMany']['{{ name }}'] = new \Mongator\Group\PolymorphicReferenceGroup('{{ referenceMany.discriminatorField }}', $this, '{{ referenceMany.field }}', {{ referenceMany.discriminatorMap ? referenceMany.discriminatorMap|var_export : 'false' }}); 35 | } 36 | 37 | return $this->data['referencesMany']['{{ name }}']; 38 | } 39 | {% endif %} 40 | 41 | {# add #} 42 | /** 43 | * Adds documents to the "{{ name }}" reference many. 44 | * 45 | * @param mixed $documents A document or an array or documents. 46 | * 47 | * @return \{{ class }} The document (fluent interface). 48 | */ 49 | public function add{{ name|ucfirst }}($documents) 50 | { 51 | $this->get{{ name|ucfirst }}()->add($documents); 52 | 53 | return $this; 54 | } 55 | 56 | {# remove #} 57 | /** 58 | * Removes documents to the "{{ name }}" reference many. 59 | * 60 | * @param mixed $documents A document or an array or documents. 61 | * 62 | * @return \{{ class }} The document (fluent interface). 63 | */ 64 | public function remove{{ name|ucfirst }}($documents) 65 | { 66 | $this->get{{ name|ucfirst }}()->remove($documents); 67 | 68 | return $this; 69 | } 70 | {% endfor %} 71 | -------------------------------------------------------------------------------- /tests/Mongator/Tests/Query/CachedQueryTest.php: -------------------------------------------------------------------------------- 1 | 7 | * 8 | * This source file is subject to the MIT license that is bundled 9 | * with this source code in the file LICENSE. 10 | */ 11 | 12 | namespace Mongator\Tests; 13 | 14 | class CachedQueryTest extends TestCase 15 | { 16 | protected $identityMap; 17 | protected $query; 18 | 19 | protected function setUp(): void 20 | { 21 | parent::setUp(); 22 | 23 | $this->identityMap = $this->mongator->getRepository('Model\Cached')->getIdentityMap(); 24 | $this->query = new \Model\CachedQuery($this->mongator->getRepository('Model\Cached')); 25 | } 26 | 27 | public function testConstructor() 28 | { 29 | $query = new \Model\CategoryQuery($repository = $this->mongator->getRepository('Model\Cached')); 30 | $this->assertSame($repository, $query->getRepository()); 31 | $hash = $query->getHash(); 32 | $this->assertInternalType('string', $hash); 33 | $this->assertSame($hash, $query->getHash()); 34 | } 35 | 36 | public function testExecute() 37 | { 38 | $messages = $this->createCachedRaw(10); 39 | $this->mongator->getRepository('Model\Cached')->ensureIndexes(); 40 | 41 | $query = new \Model\CachedQuery($this->mongator->getRepository('Model\Cached')); 42 | $query 43 | ->limit(5) 44 | ->fields(array('author' => 1)); 45 | 46 | $result = $query->execute(); 47 | $this->assertInstanceOf('Mongator\Query\Result', $result); 48 | 49 | $this->assertSame(10, $query->count()); 50 | $this->assertSame(10, $result->count()); 51 | 52 | $messages = $this->createCachedRaw(10); 53 | $result = $query->execute(); 54 | $this->assertInstanceOf('Mongator\Query\Result', $result); 55 | 56 | $this->assertSame(10, $query->count()); 57 | $this->assertSame(10, $query->count()); 58 | $this->assertSame(10, $result->count()); 59 | 60 | foreach ($query->all() as $key => $document) { 61 | $this->assertSame($key, (string) $document->getId()); 62 | $this->assertInstanceOf('Model\Cached', $document); 63 | } 64 | 65 | usleep(1200000); 66 | $result = $query->execute(); 67 | $this->assertInstanceOf('Mongator\Query\Result', $result); 68 | 69 | $this->assertSame(20, $query->count()); 70 | $this->assertSame(20, $query->count()); 71 | $this->assertSame(20, $result->count()); 72 | 73 | } 74 | } 75 | -------------------------------------------------------------------------------- /tests/Mongator/Tests/Extension/CoreRepositoryFixMissingReferencesTest.php: -------------------------------------------------------------------------------- 1 | 7 | * 8 | * This source file is subject to the MIT license that is bundled 9 | * with this source code in the file LICENSE. 10 | */ 11 | 12 | namespace Mongator\Tests\Extension; 13 | 14 | use Mongator\Tests\TestCase; 15 | 16 | class CoreRepositoryFixMissingReferencesTest extends TestCase 17 | { 18 | /** 19 | * @dataProvider fixMissingReferencesDataProvider 20 | */ 21 | public function testReferencesOne($documentsPerBatch) 22 | { 23 | $author1 = $this->mongator->create('Model\Author')->setName('foo')->save(); 24 | $author2 = $this->mongator->create('Model\Author')->setName('foo')->save(); 25 | 26 | $article1 = $this->createArticle()->setAuthor($author1)->save(); 27 | $article2 = $this->createArticle()->setAuthor($author2)->save(); 28 | $article3 = $this->createArticle()->setAuthor($author1)->save(); 29 | 30 | $this->removeFromCollection($author1); 31 | 32 | $article1->getRepository()->fixMissingReferences($documentsPerBatch); 33 | 34 | $this->assertFalse($this->documentExists($article1)); 35 | $this->assertTrue($this->documentExists($article2)); 36 | $this->assertFalse($this->documentExists($article3)); 37 | } 38 | 39 | /** 40 | * @dataProvider fixMissingReferencesDataProvider 41 | */ 42 | public function testReferencesMany($documentsPerBatch) 43 | { 44 | $category1 = $this->mongator->create('Model\Category')->setName('foo')->save(); 45 | $category2 = $this->mongator->create('Model\Category')->setName('foo')->save(); 46 | $category3 = $this->mongator->create('Model\Category')->setName('foo')->save(); 47 | 48 | $article1 = $this->createArticle()->addCategories(array($category1, $category3))->save(); 49 | $article2 = $this->createArticle()->addCategories($category2)->save(); 50 | $article3 = $this->createArticle()->addCategories($category1)->save(); 51 | 52 | $this->removeFromCollection($category1); 53 | 54 | $article1->getRepository()->fixMissingReferences($documentsPerBatch); 55 | 56 | $article1->refresh(); 57 | $article2->refresh(); 58 | $article3->refresh(); 59 | 60 | $this->assertEquals(array($category3->getId()), $article1->getCategoryIds()); 61 | $this->assertEquals(array($category2->getId()), $article2->getCategoryIds()); 62 | $this->assertEquals(array(), $article3->getCategoryIds()); 63 | } 64 | } 65 | -------------------------------------------------------------------------------- /tests/Mongator/Tests/Logger/LoggableMongoTest.php: -------------------------------------------------------------------------------- 1 | 7 | * 8 | * This source file is subject to the MIT license that is bundled 9 | * with this source code in the file LICENSE. 10 | */ 11 | 12 | namespace Mongator\Tests\Logger; 13 | 14 | use Mongator\Logger\LoggableMongo; 15 | 16 | class LoggableMongoTest extends \PHPUnit\Framework\TestCase 17 | { 18 | protected $log; 19 | 20 | protected function setUp(): void 21 | { 22 | if (!class_exists('Mongo')) { 23 | $this->markTestSkipped('Mongo is not available.'); 24 | } 25 | } 26 | 27 | public function testLoggerCallable() 28 | { 29 | $mongo = new LoggableMongo(); 30 | 31 | $mongo->setLoggerCallable($loggerCallable = function() {}); 32 | 33 | $this->assertSame($loggerCallable, $mongo->getLoggerCallable()); 34 | } 35 | 36 | public function testLogDefault() 37 | { 38 | $mongo = new LoggableMongo(); 39 | 40 | $mongo->setLogDefault($logDefault = array('connection' => 'default')); 41 | 42 | $this->assertSame($logDefault, $mongo->getLogDefault()); 43 | } 44 | 45 | public function testLog() 46 | { 47 | $mongo = new LoggableMongo(); 48 | $mongo->setLoggerCallable(array($this, 'log')); 49 | 50 | $mongo->log($log = array('foo' => 'bar')); 51 | 52 | $this->assertSame($log, $this->log); 53 | } 54 | 55 | public function testLogWithLogDefault() 56 | { 57 | $mongo = new LoggableMongo(); 58 | $mongo->setLoggerCallable(array($this, 'log')); 59 | $mongo->setLogDefault($logDefault = array('connection' => 'default', 'foo' => 'foobar')); 60 | 61 | $mongo->log($log = array('foo' => 'bar')); 62 | 63 | $this->assertSame(array_merge($logDefault, $log), $this->log); 64 | } 65 | 66 | public function log(array $log) 67 | { 68 | $this->log = $log; 69 | } 70 | 71 | public function testSelectDB() 72 | { 73 | $mongo = new LoggableMongo(); 74 | $db = $mongo->selectDB('mongator_logger'); 75 | 76 | $this->assertInstanceOf('\Mongator\Logger\LoggableMongoDB', $db); 77 | $this->assertSame('mongator_logger', $db->__toString()); 78 | } 79 | 80 | public function test__get() 81 | { 82 | $mongo = new LoggableMongo(); 83 | $db = $mongo->mongator_logger; 84 | 85 | $this->assertInstanceOf('\Mongator\Logger\LoggableMongoDB', $db); 86 | $this->assertSame('mongator_logger', $db->__toString()); 87 | } 88 | } 89 | -------------------------------------------------------------------------------- /tests/Mongator/Tests/IndexManagerTest.php: -------------------------------------------------------------------------------- 1 | 7 | * 8 | * This source file is subject to the MIT license that is bundled 9 | * with this source code in the file LICENSE. 10 | */ 11 | 12 | namespace Mongator\Tests; 13 | 14 | use Mongator\IndexManager; 15 | 16 | class IndexManagerTest extends TestCase 17 | { 18 | private $repository; 19 | 20 | protected function setUp(): void 21 | { 22 | parent::setUp(); 23 | $this->repository = $this->mongator->getRepository('Model\Article'); 24 | $this->indexManager = new IndexManager($this->repository); 25 | } 26 | 27 | public function testConstructAndGetRepository() 28 | { 29 | $this->assertSame($this->repository, $this->indexManager->getRepository()); 30 | } 31 | 32 | public function testGetConfig() 33 | { 34 | $config = $this->repository->getMongator()->getMetadataFactory()->getClass('Model\Article'); 35 | 36 | $this->assertSame($config['_indexes'], $this->indexManager->getConfig()); 37 | } 38 | 39 | public function testDiff() 40 | { 41 | $present = array('keys' => array('slug' => 1), 'options' => array('unique' => true)); 42 | $unknown = array('keys' => array('loc' => '2d')); 43 | $missing = array('keys' => array('authorId' => 1, 'isActive' => 1), 'options' => array()); 44 | 45 | $this->repository->getCollection()->ensureIndex($present['keys'], $present['options']); 46 | $this->repository->getCollection()->ensureIndex($unknown['keys']); 47 | 48 | $diff = $this->indexManager->getDiff(); 49 | $this->assertCount(9, $diff['missing']); 50 | $this->assertCount(1, $diff['present']); 51 | $this->assertCount(1, $diff['unknown']); 52 | 53 | $this->assertSame($missing, $diff['missing']['authorId_1_isActive_1']); 54 | $this->assertSame($present, $diff['present']['slug_1_unique_1']); 55 | } 56 | 57 | public function testCommit() 58 | { 59 | $present = array('keys' => array('slug' => 1), 'options' => array('unique' => true)); 60 | $unknown = array('keys' => array('loc' => '2d')); 61 | $missing = array('keys' => array('authorId' => 1, 'isActive' => 1), 'options' => array()); 62 | 63 | $this->repository->getCollection()->ensureIndex($present['keys'], $present['options']); 64 | $this->repository->getCollection()->ensureIndex($unknown['keys']); 65 | 66 | $this->assertTrue($this->indexManager->commit()); 67 | $this->assertCount(11, $this->repository->getCollection()->getIndexInfo()); 68 | } 69 | } 70 | -------------------------------------------------------------------------------- /tests/Mongator/Tests/Logger/LoggableMongoDBTest.php: -------------------------------------------------------------------------------- 1 | 7 | * 8 | * This source file is subject to the MIT license that is bundled 9 | * with this source code in the file LICENSE. 10 | */ 11 | 12 | namespace Mongator\Tests\Logger; 13 | 14 | use Mongator\Logger\LoggableMongo; 15 | use Mongator\Logger\LoggableMongoDB; 16 | 17 | class LoggableMongoDBTest extends \PHPUnit\Framework\TestCase 18 | { 19 | protected $log; 20 | 21 | protected function setUp(): void 22 | { 23 | if (!class_exists('Mongo')) { 24 | $this->markTestSkipped('Mongo is not available.'); 25 | } 26 | } 27 | 28 | public function testConstructorAndGetMongo() 29 | { 30 | $mongo = new LoggableMongo(); 31 | 32 | $db = new LoggableMongoDB($mongo, 'mongator_logger'); 33 | 34 | $this->assertSame('mongator_logger', $db->__toString()); 35 | $this->assertSame($mongo, $db->getMongo()); 36 | } 37 | 38 | public function testLog() 39 | { 40 | $mongo = new LoggableMongo(); 41 | $mongo->setLoggerCallable(array($this, 'log')); 42 | $db = $mongo->selectDB('mongator_logger'); 43 | 44 | $db->log($log = array('foo' => 'bar')); 45 | 46 | $this->assertSame(array_merge(array( 47 | 'database' => 'mongator_logger' 48 | ), $log), $this->log); 49 | } 50 | 51 | public function log(array $log) 52 | { 53 | $this->log = $log; 54 | } 55 | 56 | public function testSelectCollection() 57 | { 58 | $mongo = new LoggableMongo(); 59 | $db = $mongo->selectDB('mongator_logger'); 60 | 61 | $collection = $db->selectCollection('mongator_logger_collection'); 62 | 63 | $this->assertInstanceOf('\Mongator\Logger\LoggableMongoCollection', $collection); 64 | $this->assertSame('mongator_logger_collection', $collection->getName()); 65 | } 66 | 67 | public function test__get() 68 | { 69 | $mongo = new LoggableMongo(); 70 | $db = $mongo->selectDB('mongator_logger'); 71 | 72 | $collection = $db->mongator_logger_collection; 73 | 74 | $this->assertInstanceOf('\Mongator\Logger\LoggableMongoCollection', $collection); 75 | $this->assertSame('mongator_logger_collection', $collection->getName()); 76 | } 77 | 78 | public function testGetGridFS() 79 | { 80 | $mongo = new LoggableMongo(); 81 | $db = $mongo->selectDB('mongator_logger'); 82 | 83 | $grid = $db->getGridFS('mongator_logger_grid'); 84 | 85 | $this->assertInstanceOf('\Mongator\Logger\LoggableMongoGridFS', $grid); 86 | $this->assertSame('mongator_logger_grid.files', $grid->getName()); 87 | } 88 | } 89 | -------------------------------------------------------------------------------- /tests/Mongator/Tests/Type/ContainerTest.php: -------------------------------------------------------------------------------- 1 | 7 | * 8 | * This source file is subject to the MIT license that is bundled 9 | * with this source code in the file LICENSE. 10 | */ 11 | 12 | namespace Mongator\Tests\Type; 13 | 14 | use Mongator\Type\Container; 15 | use Mongator\Type\Type; 16 | 17 | class TestingType extends Type 18 | { 19 | public function toMongo($value) 20 | { 21 | } 22 | 23 | public function toPHP($value) 24 | { 25 | } 26 | 27 | public function toMongoInString() 28 | { 29 | } 30 | 31 | public function toPHPInString() 32 | { 33 | } 34 | } 35 | 36 | class ContainerTest extends TestCase 37 | { 38 | public function testHas() 39 | { 40 | $this->assertTrue(Container::has('string')); 41 | $this->assertFalse(Container::has('no')); 42 | } 43 | 44 | public function testAdd() 45 | { 46 | Container::add('testing', 'Mongator\Tests\Type\TestingType'); 47 | $this->assertTrue(Container::has('testing')); 48 | 49 | $this->assertInstanceOf('Mongator\Tests\Type\TestingType', Container::get('testing')); 50 | } 51 | 52 | /** 53 | * @expectedException \InvalidArgumentException 54 | */ 55 | public function testAddAlreadyExists() 56 | { 57 | Container::add('string', 'Mongator\Tests\Type\TestingType'); 58 | } 59 | 60 | /** 61 | * @expectedException \InvalidArgumentException 62 | */ 63 | public function testAddClassNotSubclassType() 64 | { 65 | Container::add('testing', '\DateTime'); 66 | } 67 | 68 | public function testGet() 69 | { 70 | $string = Container::get('string'); 71 | $float = Container::get('float'); 72 | 73 | $this->assertInstanceOf('Mongator\Type\StringType', $string); 74 | $this->assertInstanceOf('Mongator\Type\FloatType', $float); 75 | } 76 | 77 | /** 78 | * @expectedException \InvalidArgumentException 79 | */ 80 | public function testGetNotExists() 81 | { 82 | Container::get('no'); 83 | } 84 | 85 | public function testRemove() 86 | { 87 | Container::remove('string'); 88 | $this->assertFalse(Container::has('string')); 89 | } 90 | 91 | /** 92 | * @expectedException \InvalidArgumentException 93 | */ 94 | public function testRemoveNotExists() 95 | { 96 | Container::remove('no'); 97 | } 98 | 99 | public function testResetTypes() 100 | { 101 | Container::add('testing', 'Mongator\Tests\Type\TestingType'); 102 | Container::reset(); 103 | 104 | $this->assertTrue(Container::has('string')); 105 | $this->assertFalse(Container::has('testing')); 106 | } 107 | } 108 | -------------------------------------------------------------------------------- /src/Mongator/Cache/FilesystemCache.php: -------------------------------------------------------------------------------- 1 | 7 | * 8 | * This source file is subject to the MIT license that is bundled 9 | * with this source code in the file LICENSE. 10 | */ 11 | 12 | namespace Mongator\Cache; 13 | 14 | /** 15 | * FilesystemCache. 16 | * 17 | * @author Pablo Díez 18 | */ 19 | class FilesystemCache extends AbstractCache 20 | { 21 | private $dir; 22 | private $data = array(); 23 | 24 | /** 25 | * Constructor. 26 | * 27 | * @param string $dir The directory. 28 | */ 29 | public function __construct($dir) 30 | { 31 | $this->dir = $dir; 32 | if (!is_dir($dir) && false === @mkdir($dir, 0777, true)) { 33 | throw new \RuntimeException(sprintf('Unable to create the "%s" directory.', $dir)); 34 | } 35 | 36 | } 37 | 38 | /** 39 | * {@inheritdoc} 40 | */ 41 | public function set($key, $value, $ttl = 0) 42 | { 43 | $content = $this->pack($key, $value, $ttl); 44 | $file = $this->dir.'/'.$key.'.php'; 45 | 46 | $valueExport = var_export($content , true); 47 | 48 | $php = sprintf("data[$key] = $content; 55 | } 56 | 57 | /** 58 | * {@inheritdoc} 59 | */ 60 | public function remove($key) 61 | { 62 | $file = $this->dir.'/'.$key.'.php'; 63 | if (file_exists($file) && false === @unlink($file)) { 64 | throw new \RuntimeException(sprintf('Unable to remove the "%s" file.', $file)); 65 | } 66 | 67 | if ( isset($this->data[$key]) ) unset($this->data[$key]); 68 | } 69 | 70 | /** 71 | * {@inheritdoc} 72 | */ 73 | public function clear() 74 | { 75 | $this->data = array(); 76 | 77 | if (is_dir($this->dir)) { 78 | foreach (new \DirectoryIterator($this->dir) as $file) { 79 | if ($file->isFile()) { 80 | if (false === @unlink($file->getRealPath())) { 81 | throw new \RuntimeException(sprintf('Unable to remove the "%s" file.', $file->getRealPath())); 82 | } 83 | } 84 | } 85 | } 86 | } 87 | 88 | /** 89 | * {@inheritdoc} 90 | */ 91 | public function info($key) 92 | { 93 | if ( isset($this->data[$key]) ) return $this->data[$key]; 94 | 95 | $file = $this->dir.'/'.$key.'.php'; 96 | if ( !file_exists($file) ) return null; 97 | return $this->data[$key] = require($file); 98 | } 99 | } 100 | -------------------------------------------------------------------------------- /tests/Mongator/Tests/Query/ResultTest.php: -------------------------------------------------------------------------------- 1 | 7 | * 8 | * This source file is subject to the MIT license that is bundled 9 | * with this source code in the file LICENSE. 10 | */ 11 | 12 | namespace Mongator\Tests; 13 | 14 | use Mongator\Query\Result; 15 | 16 | class ResultTest extends TestCase 17 | { 18 | public function testConstructFromArrayObject() 19 | { 20 | $ao = new \ArrayObject(range(0,19)); 21 | $result = new Result($ao); 22 | 23 | $valid = range(0,19); 24 | foreach ($result as $key => $value) { 25 | $this->assertSame($key, $value); 26 | $this->assertSame($valid[$key], $value); 27 | } 28 | 29 | $result->rewind(); 30 | $this->assertSame(0, $result->current()); 31 | $this->assertSame(0, $result->key()); 32 | 33 | $this->assertSame(20, $result->count()); 34 | } 35 | 36 | public function testConstructFromMongoCursor() 37 | { 38 | $articles = $this->createArticlesRaw(10); 39 | 40 | $query = new \Model\ArticleQuery($this->mongator->getRepository('Model\Article')); 41 | 42 | $result = $query->limit(2)->createCursor(); 43 | $this->assertInstanceOf('MongoCursor', $result->getIterator()); 44 | 45 | $i = 0; 46 | foreach ($result as $key => $value) { 47 | $this->assertSame('Article' . $i++, $value['title']); 48 | $this->assertSame($key, (string) $value['_id']); 49 | } 50 | 51 | $this->assertSame(10, $result->count()); 52 | } 53 | 54 | public function testSetCountInteger() 55 | { 56 | $ao = new \ArrayObject(range(0,19)); 57 | $result = new Result($ao); 58 | 59 | $result->setCount(50); 60 | $this->assertSame(50, $result->count()); 61 | } 62 | 63 | public function testSetCountClosure() 64 | { 65 | $ao = new \ArrayObject(range(0,19)); 66 | $result = new Result($ao); 67 | 68 | $result->setCount(function() { return 100; }); 69 | $this->assertSame(100, $result->count()); 70 | } 71 | 72 | public function testSerialize() 73 | { 74 | $ao = new \ArrayObject(range(0,2)); 75 | $result = new Result($ao); 76 | 77 | $result->setCount(50); 78 | 79 | $expected = 'C:21:"Mongator\Query\Result":64:{a:2:{s:5:"count";i:50;s:4:"data";a:3:{i:0;i:0;i:1;i:1;i:2;i:2;}}}'; 80 | $this->assertSame($expected, serialize($result)); 81 | } 82 | 83 | public function testUnSerialize() 84 | { 85 | $ao = new \ArrayObject(range(0,2)); 86 | $expected = new Result($ao); 87 | 88 | $expected->setCount(50); 89 | 90 | $string = 'C:21:"Mongator\Query\Result":64:{a:2:{s:5:"count";i:50;s:4:"data";a:3:{i:0;i:0;i:1;i:1;i:2;i:2;}}}'; 91 | $this->assertEquals($expected, unserialize($string)); 92 | } 93 | } 94 | -------------------------------------------------------------------------------- /tests/Mongator/Tests/Id/IdGeneratorContainerTest.php: -------------------------------------------------------------------------------- 1 | 7 | * 8 | * This source file is subject to the MIT license that is bundled 9 | * with this source code in the file LICENSE. 10 | */ 11 | 12 | namespace Mongator\Tests\Id; 13 | 14 | use Mongator\Tests\TestCase; 15 | use Mongator\Id\BaseIdGenerator; 16 | use Mongator\Id\IdGeneratorContainer; 17 | 18 | class TestingIdGenerator extends BaseIdGenerator 19 | { 20 | public function getCode(array $options) 21 | { 22 | } 23 | 24 | public function getToMongoCode() 25 | { 26 | } 27 | } 28 | 29 | class IdGeneratorContainerTest extends TestCase 30 | { 31 | public function testHas() 32 | { 33 | $this->assertTrue(IdGeneratorContainer::has('native')); 34 | $this->assertFalse(IdGeneratorContainer::has('no')); 35 | } 36 | 37 | public function testAdd() 38 | { 39 | IdGeneratorContainer::add('testing', 'Mongator\Tests\Id\TestingIdGenerator'); 40 | $this->assertTrue(IdGeneratorContainer::has('testing')); 41 | 42 | $this->assertInstanceOf('Mongator\Tests\Id\TestingIdGenerator', IdGeneratorContainer::get('testing')); 43 | } 44 | 45 | /** 46 | * @expectedException \InvalidArgumentException 47 | */ 48 | public function testAddAlreadyExists() 49 | { 50 | IdGeneratorContainer::add('native', 'Mongator\Tests\Id\TestingIdGenerator'); 51 | } 52 | 53 | /** 54 | * @expectedException \InvalidArgumentException 55 | */ 56 | public function testAddClassNotSubclassType() 57 | { 58 | IdGeneratorContainer::add('testing', '\DateTime'); 59 | } 60 | 61 | public function testGet() 62 | { 63 | $native = IdGeneratorContainer::get('native'); 64 | $sequence = IdGeneratorContainer::get('sequence'); 65 | 66 | $this->assertInstanceOf('Mongator\Id\NativeIdGenerator', $native); 67 | $this->assertInstanceOf('Mongator\Id\SequenceIdGenerator', $sequence); 68 | } 69 | 70 | /** 71 | * @expectedException \InvalidArgumentException 72 | */ 73 | public function testGetNotExists() 74 | { 75 | IdGeneratorContainer::get('no'); 76 | } 77 | 78 | public function testRemove() 79 | { 80 | IdGeneratorContainer::remove('native'); 81 | $this->assertFalse(IdGeneratorContainer::has('native')); 82 | } 83 | 84 | /** 85 | * @expectedException \InvalidArgumentException 86 | */ 87 | public function testRemoveNotExists() 88 | { 89 | IdGeneratorContainer::remove('no'); 90 | } 91 | 92 | public function testResetTypes() 93 | { 94 | IdGeneratorContainer::add('testing', 'Mongator\Tests\Id\TestingIdGenerator'); 95 | IdGeneratorContainer::reset(); 96 | 97 | $this->assertTrue(IdGeneratorContainer::has('native')); 98 | $this->assertFalse(IdGeneratorContainer::has('testing')); 99 | } 100 | } 101 | -------------------------------------------------------------------------------- /src/Mongator/Extension/templates/Core/DocumentSetDocumentData.php.twig: -------------------------------------------------------------------------------- 1 | data = array(); 20 | $this->fieldsModified = array(); 21 | } 22 | 23 | {% endif %} 24 | {# query hash #} 25 | {% if not config_class.isEmbedded %} 26 | if (isset($data['_query_hash'])) { 27 | $this->addQueryHash($data['_query_hash']); 28 | } 29 | if (isset($data['_query_fields'])) { 30 | $this->setQueryFields($data['_query_fields']); 31 | } 32 | {% endif %} 33 | {# id #} 34 | {% if not config_class.isEmbedded %} 35 | if (isset($data['_id'])) { 36 | $this->setId($data['_id']); 37 | $this->setIsNew(false); 38 | } 39 | {% endif %} 40 | {# fields #} 41 | {% for name, field in config_class.fields %} 42 | if (isset($data['{{ field.dbName }}'])) { 43 | {{ Mongator_type_to_php(field.type, "$data['" ~ field.dbName ~ "']", "$this->data['fields']['" ~ name ~ "']") }} 44 | } 45 | {% endfor %} 46 | {# embeddeds one #} 47 | {% for name, embedded_one in config_class.embeddedsOne %} 48 | {% if embedded_one.inherited is not defined or not embedded_one.inherited %} 49 | if (isset($data['{{ name }}'])) { 50 | $embedded = $this->getMongator()->create('{{ embedded_one.class }}'); 51 | {% if config_class.isEmbedded %} 52 | if ($rap = $this->getRootAndPath()) { 53 | $embedded->setRootAndPath($rap['root'], $rap['path'].'.{{ name }}'); 54 | } 55 | {% else %} 56 | $embedded->setRootAndPath($this, '{{ name }}'); 57 | {% endif %} 58 | $embedded->setDocumentData($data['{{ name }}']); 59 | $this->data['embeddedsOne']['{{ name }}'] = $embedded; 60 | } 61 | {% endif %} 62 | {% endfor %} 63 | {# embeddeds many #} 64 | {% for name, embedded_many in config_class.embeddedsMany %} 65 | {% if embedded_many.inherited is not defined or not embedded_many.inherited %} 66 | if (isset($data['{{ name }}'])) { 67 | $embedded = new \Mongator\Group\EmbeddedGroup('{{ embedded_many.class }}'); 68 | {% if config_class.isEmbedded %} 69 | if ($rap = $this->getRootAndPath()) { 70 | $embedded->setRootAndPath($rap['root'], $rap['path'].'.{{ name }}'); 71 | } 72 | {% else %} 73 | $embedded->setRootAndPath($this, '{{ name }}'); 74 | {% endif %} 75 | $embedded->setSavedData($data['{{ name }}']); 76 | $this->data['embeddedsMany']['{{ name }}'] = $embedded; 77 | } 78 | {% endif %} 79 | {% endfor %} 80 | 81 | return $this; 82 | } 83 | -------------------------------------------------------------------------------- /src/Mongator/Cache/AbstractCache.php: -------------------------------------------------------------------------------- 1 | 7 | * 8 | * This source file is subject to the MIT license that is bundled 9 | * with this source code in the file LICENSE. 10 | */ 11 | 12 | namespace Mongator\Cache; 13 | 14 | /** 15 | * AbstractCache. 16 | * 17 | * @author Máximo Cuadros 18 | */ 19 | abstract class AbstractCache 20 | { 21 | /** 22 | * Checks if the cache has a value for a key. 23 | * 24 | * @param string $key A unique key. 25 | * 26 | * @return bool Whether the cache has a key. 27 | */ 28 | public function has($key) 29 | { 30 | return (boolean) $this->get($key); 31 | } 32 | 33 | /** 34 | * Returns the value for a key. 35 | * 36 | * @param string $key A unique key. 37 | * 38 | * @return mixed The value for a key. 39 | */ 40 | public function get($key) 41 | { 42 | if ( !$content = $this->info($key) ) { 43 | return null; 44 | } 45 | 46 | return $this->unpack($content); 47 | } 48 | 49 | /** 50 | * Sets a value for a key. 51 | * 52 | * @param string $key A unique key. 53 | * @param mixed $value The value. 54 | */ 55 | abstract public function set($key, $value, $ttl = 0); 56 | 57 | /** 58 | * Removes a value from the cache. 59 | * 60 | * @param string $key A unique key. 61 | */ 62 | abstract public function remove($key); 63 | 64 | /** 65 | * Clears the cache. 66 | */ 67 | abstract public function clear(); 68 | 69 | /** 70 | * Returns metadata info about given key 71 | * 72 | * @param string $key A unique key. 73 | * 74 | * @return array 75 | */ 76 | abstract public function info($key); 77 | 78 | /** 79 | * Pack the value in array with metadata 80 | * 81 | * @param string $key A unique key. 82 | * @param mixed $value The value to be cached. 83 | * @param integer $ttl (optional) time to life in seconds. 84 | * 85 | * @return bool Whether the cache has a key. 86 | */ 87 | protected function pack($key, $value, $ttl = 0) 88 | { 89 | $content = array( 90 | 'key' => $key, 91 | 'time' => time(), 92 | 'ttl' => $ttl, 93 | 'value' => $value 94 | ); 95 | 96 | return $content; 97 | } 98 | 99 | /** 100 | * Unpack the data from cache, and unserialize the value. If ttl is ussed and is expired false is return 101 | * 102 | * @param array $content Data from cache. 103 | * 104 | * @return mixed 105 | */ 106 | protected function unpack($content) 107 | { 108 | if ( !is_array($content) ) return null; 109 | 110 | if ( $content['ttl'] > 0 && time() >= $content['time'] + $content['ttl'] ) { 111 | $this->remove($content['key']); 112 | 113 | return null; 114 | } 115 | 116 | return $content['value']; 117 | } 118 | } 119 | -------------------------------------------------------------------------------- /tests/Mongator/Benchmarks/FindingEvent.php: -------------------------------------------------------------------------------- 1 | 7 | * 8 | * This source file is subject to the MIT license that is bundled 9 | * with this source code in the file LICENSE. 10 | */ 11 | 12 | namespace Mongator\Benchmarks; 13 | 14 | use Exception; 15 | 16 | class FindingEvent extends AthleticEvent 17 | { 18 | protected $recordCount = 100; 19 | 20 | protected function classSetUp() 21 | { 22 | parent::classSetUp(); 23 | 24 | for ($i=0; $i < $this->recordCount; $i++) { 25 | $this->buildSimpleDocument()->setString(__CLASS__)->save(); 26 | $this->buildSimpleNestedDocument()->setString(__CLASS__)->save(); 27 | $this->buildComplexDocument()->setString(__CLASS__)->save(); 28 | $this->buildComplexNestedDocument()->setString(__CLASS__)->save(); 29 | } 30 | } 31 | 32 | /** 33 | * @iterations 100 34 | */ 35 | public function simpleDocument() 36 | { 37 | $result = $this 38 | ->getRepository(self::SIMPLE_DOCUMENT_CLASS) 39 | ->createQuery(array( 40 | 'nested' => array('$exists' => 0), 41 | 'string' => __CLASS__ 42 | )) 43 | ->all(); 44 | 45 | $this->throwExceptionIfCountNotMatch($result); 46 | } 47 | 48 | /** 49 | * @iterations 100 50 | */ 51 | public function simpleNestedDocument() 52 | { 53 | $result = $this 54 | ->getRepository(self::SIMPLE_DOCUMENT_CLASS) 55 | ->createQuery(array( 56 | 'nested' => array('$exists' => 1), 57 | 'string' => __CLASS__ 58 | )) ->all(); 59 | 60 | $this->throwExceptionIfCountNotMatch($result); 61 | } 62 | 63 | /** 64 | * @iterations 100 65 | */ 66 | public function complexDocument() 67 | { 68 | $result = $this 69 | ->getRepository(self::COMPLEX_DOCUMENT_CLASS) 70 | ->createQuery(array( 71 | 'nested' => array('$exists' => 0), 72 | 'string' => __CLASS__ 73 | )) 74 | ->all(); 75 | 76 | $this->throwExceptionIfCountNotMatch($result); 77 | } 78 | 79 | /** 80 | * @iterations 100 81 | */ 82 | public function complexNestedDocument() 83 | { 84 | $result = $this 85 | ->getRepository(self::COMPLEX_DOCUMENT_CLASS) 86 | ->createQuery(array( 87 | 'nested' => array('$exists' => 1), 88 | 'string' => __CLASS__ 89 | )) 90 | ->all(); 91 | 92 | $this->throwExceptionIfCountNotMatch($result); 93 | } 94 | 95 | private function throwExceptionIfCountNotMatch(array $result) 96 | { 97 | 98 | if (count($result) != $this->recordCount) { 99 | throw new Exception(sprintf( 100 | 'missmatch result find %d, expected %d records', 101 | count($result), 102 | $this->recordCount 103 | )); 104 | } 105 | } 106 | } -------------------------------------------------------------------------------- /src/Mongator/Extension/templates/Core/DocumentProcessOnDelete.php.twig: -------------------------------------------------------------------------------- 1 | processOnDeleteCascade('{{ onDelete.class }}', array('{{ onDelete.referenceName }}' => array('{{ onDelete.discriminatorField }}' => $discriminatorValue, 'id' => $this->getId()))); 20 | {% else %} 21 | $this->processOnDeleteCascade('{{ onDelete.class }}', array('{{ onDelete.referenceName }}' => $this->getId())); 22 | {% endif %} 23 | {% elseif onDelete.type == 'unset' %} 24 | {% if onDelete.polymorphic %} 25 | {% if onDelete.discriminatorMap %} 26 | if (false === $discriminatorValue = array_search(get_class($this), {{ onDelete.discriminatorMap|var_export }})) { 27 | throw new \InvalidArgumentException(sprintf('The class "%s" is not a possible reference in the reference "{{ onDelete.referenceName }}" of the class "{{ onDelete.class }}".', get_class($this))); 28 | } 29 | {% else %} 30 | $discriminatorValue = get_class($this); 31 | {% endif %} 32 | {% endif %} 33 | {% if onDelete.polymorphic %} 34 | {% if onDelete.referenceType == 'one' %} 35 | $criteria = array('{{ onDelete.referenceName }}' => array('{{ onDelete.discriminatorField }}' => $discriminatorValue, 'id' => $this->getId())); 36 | $update = array('$unset' => array('{{ onDelete.referenceName }}' => 1)); 37 | {% else %} 38 | $criteria = array(); 39 | $update = array('$pull' => array('{{ onDelete.referenceName }}' => array('{{ onDelete.discriminatorField }}' => $discriminatorValue, 'id' => $this->getId()))); 40 | {% endif %} 41 | {% else %} 42 | {% if onDelete.referenceType == 'one' %} 43 | $criteria = array('{{ onDelete.referenceName }}' => $this->getId()); 44 | $update = array('$unset' => array('{{ onDelete.referenceName }}' => 1)); 45 | {% else %} 46 | $criteria = array(); 47 | $update = array('$pull' => array('{{ onDelete.referenceName }}' => $this->getId())); 48 | {% endif %} 49 | {% endif %} 50 | $this->processOnDeleteUnset('{{ onDelete.class }}', $criteria, $update); 51 | {% endif %} 52 | 53 | {% endfor %} 54 | } 55 | 56 | private function processOnDeleteCascade($class, array $criteria) 57 | { 58 | $repository = $this->getMongator()->getRepository($class); 59 | $documents = $repository->createQuery($criteria)->all(); 60 | if (count($documents)) { 61 | $repository->delete($documents); 62 | } 63 | } 64 | 65 | private function processOnDeleteUnset($class, array $criteria, array $update) 66 | { 67 | $this->getMongator()->getRepository($class)->update($criteria, $update, array('multiple' => true)); 68 | } 69 | -------------------------------------------------------------------------------- /src/Mongator/Archive.php: -------------------------------------------------------------------------------- 1 | 7 | * 8 | * This source file is subject to the MIT license that is bundled 9 | * with this source code in the file LICENSE. 10 | */ 11 | 12 | namespace Mongator; 13 | 14 | /** 15 | * Archive to save things related to objects. 16 | * 17 | * @author Máximo Cuadros 18 | */ 19 | class Archive 20 | { 21 | private $archive = array(); 22 | private $keys = array(); 23 | 24 | /** 25 | * Returns if has a key in the archive. 26 | * 27 | * @param string $key The key. 28 | * 29 | * @return bool If key in the archive. 30 | */ 31 | public function has($key) 32 | { 33 | return isset($this->keys[$key]); 34 | } 35 | 36 | /** 37 | * Returns the value of a key. 38 | * 39 | * It does not check if the object key exists, if you want to check it, do by yourself. 40 | * 41 | * @param string $key The key. 42 | * 43 | * @return mixed The value of the key. 44 | */ 45 | public function get($key) 46 | { 47 | return $this->archive[$key]; 48 | } 49 | 50 | /** 51 | * Set a key value. 52 | * 53 | * @param string $key The key. 54 | * @param mixed $value The value. 55 | */ 56 | public function set($key, $value) 57 | { 58 | $this->keys[$key] = true; 59 | $this->archive[$key] = $value; 60 | } 61 | 62 | /** 63 | * Remove a key. 64 | * 65 | * @param string $key The key. 66 | */ 67 | public function remove($key) 68 | { 69 | if (!$this->has($key)) { 70 | return; 71 | } 72 | 73 | unset($this->archive[$key]); 74 | unset($this->keys[$key]); 75 | 76 | } 77 | 78 | /** 79 | * Returns a key by reference. It creates the key if the key does not exist. 80 | * 81 | * @param string $key The key. 82 | * @param mixed $default The default value, used to create the key if it does not exist (null by default). 83 | * 84 | * @return mixed The object key value. 85 | */ 86 | public function &getByRef($key, $default = null) 87 | { 88 | if (!$this->has($key)) { 89 | $this->set($key, $default); 90 | } 91 | 92 | return $this->archive[$key]; 93 | } 94 | 95 | /** 96 | * Returns an object key or returns a default value otherwise. 97 | * 98 | * @param string $key The key. 99 | * @param mixed $default The value to return if the object key does not exist. 100 | * 101 | * @return mixed The object key value or the default value. 102 | */ 103 | public function getOrDefault($key, $default) 104 | { 105 | if ($this->has($key)) { 106 | return $this->get($key); 107 | } 108 | 109 | return $default; 110 | } 111 | 112 | /** 113 | * Returns all objects data. 114 | * 115 | * @return array All objects data. 116 | */ 117 | public function all() 118 | { 119 | return $this->archive; 120 | } 121 | 122 | /** 123 | * Clear all objects data. 124 | */ 125 | public function clear() 126 | { 127 | $this->archive = array(); 128 | } 129 | } 130 | -------------------------------------------------------------------------------- /src/Mongator/Group/EmbeddedGroup.php: -------------------------------------------------------------------------------- 1 | 7 | * 8 | * This source file is subject to the MIT license that is bundled 9 | * with this source code in the file LICENSE. 10 | */ 11 | 12 | namespace Mongator\Group; 13 | 14 | use Mongator\Document\Document; 15 | 16 | /** 17 | * EmbeddedGroup. 18 | * 19 | * @author Pablo Díez 20 | * 21 | * @api 22 | */ 23 | class EmbeddedGroup extends Group 24 | { 25 | /** 26 | * Set the root and path of the embedded group. 27 | * 28 | * @param \Mongator\Document\Document $root The root document. 29 | * @param string $path The path. 30 | * 31 | * @api 32 | */ 33 | public function setRootAndPath(Document $root, $path) 34 | { 35 | $this->getArchive()->set('root_and_path', array('root' => $root, 'path' => $path)); 36 | 37 | foreach ($this->getAdd() as $key => $document) { 38 | $document->setRootAndPath($root, $path.'._add'.$key); 39 | } 40 | } 41 | 42 | /** 43 | * Returns the root and the path. 44 | * 45 | * @api 46 | */ 47 | public function getRootAndPath() 48 | { 49 | return $this->getArchive()->getOrDefault('root_and_path', null); 50 | } 51 | 52 | /** 53 | * {@inheritdoc} 54 | */ 55 | public function add($documents) 56 | { 57 | parent::add($documents); 58 | 59 | if ($rap = $this->getRootAndPath()) { 60 | foreach ($this->getAdd() as $key => $document) { 61 | $document->setRootAndPath($rap['root'], $rap['path'].'._add'.$key); 62 | } 63 | } 64 | } 65 | 66 | /** 67 | * Set the saved data. 68 | * 69 | * @param array $data The saved data. 70 | */ 71 | public function setSavedData($data) 72 | { 73 | $this->getArchive()->set('saved_data', $data); 74 | } 75 | 76 | /** 77 | * Returns the saved data. 78 | * 79 | * @return array|null The saved data or null if it does not exist. 80 | */ 81 | public function getSavedData() 82 | { 83 | return $this->getArchive()->getOrDefault('saved_data', null); 84 | } 85 | 86 | /** 87 | * {@inheritdoc} 88 | */ 89 | protected function doInitializeSavedData() 90 | { 91 | $rap = $this->getRootAndPath(); 92 | $rap['root']->addFieldCache($rap['path']); 93 | 94 | $data = $this->getSavedData(); 95 | if ($data !== null) { 96 | return $data; 97 | } 98 | 99 | return array(); 100 | } 101 | 102 | /** 103 | * {@inheritdoc} 104 | */ 105 | protected function doInitializeSaved($data) 106 | { 107 | $documentClass = $this->getDocumentClass(); 108 | $rap = $this->getRootAndPath(); 109 | $mongator = $rap['root']->getMongator(); 110 | 111 | $saved = array(); 112 | foreach ($data as $key => $datum) { 113 | if ( $datum === null ) continue; 114 | 115 | $saved[] = $document = $mongator->create($documentClass); 116 | $document->setDocumentData($datum); 117 | $document->setRootAndPath($rap['root'], $rap['path'].'.'.$key); 118 | } 119 | 120 | return $saved; 121 | } 122 | } 123 | -------------------------------------------------------------------------------- /src/Mongator/Extension/templates/Core/DocumentFields.php.twig: -------------------------------------------------------------------------------- 1 | data['fields']['{{ name }}'])) { 14 | {% if config_class.isEmbedded %} 15 | if (($rap = $this->getRootAndPath()) && !$rap['root']->isNew()) { 16 | {% else %} 17 | if (!$this->isNew()) { 18 | {% endif %} 19 | $this->get{{ name | ucfirst }}(); 20 | if ( 21 | ( is_object($value) && $value == $this->data['fields']['{{ name }}'] ) || 22 | ( !is_object($value) && $value === ($this->data['fields']['{{ name }}'] ?? null) ) 23 | ) { 24 | return $this; 25 | } 26 | } else { 27 | if (null === $value) { 28 | return $this; 29 | } 30 | $this->fieldsModified['{{ name }}'] = null; 31 | $this->data['fields']['{{ name }}'] = $value; 32 | return $this; 33 | } 34 | } elseif ( 35 | ( is_object($value) && $value == $this->data['fields']['{{ name }}'] ) || 36 | ( !is_object($value) && $value === ($this->data['fields']['{{ name }}'] ?? null)) 37 | ) { 38 | return $this; 39 | } 40 | 41 | if (!isset($this->fieldsModified['{{ name }}']) && !array_key_exists('{{ name }}', $this->fieldsModified)) { 42 | $this->fieldsModified['{{ name }}'] = $this->data['fields']['{{ name }}'] ?? null; 43 | } elseif ( 44 | ( is_object($value) && $value == $this->fieldsModified['{{ name }}'] ) || 45 | ( !is_object($value) && $value === $this->fieldsModified['{{ name }}'] ) 46 | ) { 47 | unset($this->fieldsModified['{{ name }}']); 48 | } 49 | 50 | $this->data['fields']['{{ name }}'] = $value; 51 | 52 | return $this; 53 | } 54 | 55 | /** 56 | * Returns the "{{ name }}" field. 57 | * 58 | * @return mixed The $name field. 59 | */ 60 | public function get{{ name|ucfirst }}() 61 | { 62 | {% if config_class.isEmbedded %} 63 | $rap = $this->getRootAndPath(); 64 | $new = $this->isEmbeddedManyNew(); 65 | if ( $rap && !$new ) { 66 | $field = $rap['path'].'.{{ field.dbName }}'; 67 | $rap['root']->addFieldCache($field); 68 | } 69 | {% else %} 70 | $this->addFieldCache('{{ field.dbName }}'); 71 | {% endif %} 72 | 73 | if (!isset($this->data['fields']['{{ name }}']) && 74 | !$this->isFieldInQuery('{{ name }}')) 75 | { 76 | $this->loadFull(); 77 | } 78 | // Still not set? It can only be null 79 | if (!isset($this->data['fields']['{{ name }}'])) { 80 | $this->data['fields']['{{ name }}'] = null; 81 | } 82 | {% if (config_class.translateFields is defined) and (name in config_class.translateFields) %} 83 | if(\Mongator\Mongator::$doTranslate && in_array('{{ name }}', $this->translateFields)){ 84 | return $this->getTranslationFor('{{ name }}'); 85 | } 86 | {% endif %} 87 | 88 | return $this->data['fields']['{{ name }}']; 89 | } 90 | {% endfor %} 91 | -------------------------------------------------------------------------------- /tests/Mongator/Tests/Extension/CoreMetadataTest.php: -------------------------------------------------------------------------------- 1 | 7 | * 8 | * This source file is subject to the MIT license that is bundled 9 | * with this source code in the file LICENSE. 10 | */ 11 | 12 | namespace Mongator\Tests\Extension; 13 | 14 | use Mongator\Tests\TestCase; 15 | 16 | class CoreMetadataTest extends TestCase 17 | { 18 | public function testMetadata() 19 | { 20 | $this->assertSame($this->metadataFactory->getClass('Model\Article'), $this->mongator->getRepository('Model\Article')->getMetadata()); 21 | $this->assertSame($this->metadataFactory->getClass('Model\Source'), $this->mongator->getMetadataFactory()->getClass('Model\Source')); 22 | } 23 | 24 | public function testInherited() 25 | { 26 | $metadata = $this->metadataFactory->getClass('Model\RadioFormElement'); 27 | 28 | // fields 29 | $this->assertTrue(isset($metadata['fields']['label'])); 30 | $this->assertTrue(isset($metadata['fields']['label']['inherited'])); 31 | $this->assertTrue($metadata['fields']['label']['inherited']); 32 | $this->assertTrue(isset($metadata['fields']['options'])); 33 | $this->assertTrue(isset($metadata['fields']['options']['inherited'])); 34 | $this->assertFalse($metadata['fields']['options']['inherited']); 35 | 36 | // referencesOne 37 | $this->assertTrue(isset($metadata['referencesOne']['author'])); 38 | $this->assertTrue(isset($metadata['referencesOne']['author']['inherited'])); 39 | $this->assertTrue($metadata['referencesOne']['author']['inherited']); 40 | $this->assertTrue(isset($metadata['referencesOne']['authorLocal'])); 41 | $this->assertTrue(isset($metadata['referencesOne']['authorLocal']['inherited'])); 42 | $this->assertFalse($metadata['referencesOne']['authorLocal']['inherited']); 43 | 44 | // referencesMany 45 | $this->assertTrue(isset($metadata['referencesMany']['categories'])); 46 | $this->assertTrue(isset($metadata['referencesMany']['categories'])); 47 | $this->assertTrue($metadata['referencesMany']['categories']['inherited']); 48 | $this->assertTrue(isset($metadata['referencesMany']['categoriesLocal'])); 49 | $this->assertTrue(isset($metadata['referencesMany']['categoriesLocal']['inherited'])); 50 | $this->assertFalse($metadata['referencesMany']['categoriesLocal']['inherited']); 51 | 52 | // embeddedsOne 53 | $this->assertTrue(isset($metadata['embeddedsOne']['source'])); 54 | $this->assertTrue(isset($metadata['embeddedsOne']['source']['inherited'])); 55 | $this->assertTrue($metadata['embeddedsOne']['source']['inherited']); 56 | $this->assertTrue(isset($metadata['embeddedsOne']['sourceLocal'])); 57 | $this->assertTrue(isset($metadata['embeddedsOne']['sourceLocal']['inherited'])); 58 | $this->assertFalse($metadata['embeddedsOne']['sourceLocal']['inherited']); 59 | 60 | // embeddedsMany 61 | $this->assertTrue(isset($metadata['embeddedsMany']['comments'])); 62 | $this->assertTrue(isset($metadata['embeddedsMany']['comments']['inherited'])); 63 | $this->assertTrue($metadata['embeddedsMany']['comments']['inherited']); 64 | $this->assertTrue(isset($metadata['embeddedsMany']['commentsLocal'])); 65 | $this->assertTrue(isset($metadata['embeddedsMany']['commentsLocal']['inherited'])); 66 | $this->assertFalse($metadata['embeddedsMany']['commentsLocal']['inherited']); 67 | } 68 | } 69 | -------------------------------------------------------------------------------- /src/Mongator/Extension/templates/Core/DocumentEmbeddedsOne.php.twig: -------------------------------------------------------------------------------- 1 | setRootAndPath($this, '{{ name }}'); 23 | } elseif ($rap = $this->getRootAndPath()) { 24 | $value->setRootAndPath($rap['root'], $rap['path'].'.{{ name }}'); 25 | } 26 | } 27 | 28 | if (!$this->getArchive()->has('embedded_one.{{ name }}')) { 29 | $originalValue = isset($this->data['embeddedsOne']['{{ name }}']) ? $this->data['embeddedsOne']['{{ name }}'] : null; 30 | $this->getArchive()->set('embedded_one.{{ name }}', $originalValue); 31 | } elseif ($this->getArchive()->get('embedded_one.{{ name }}') === $value) { 32 | $this->getArchive()->remove('embedded_one.{{ name }}'); 33 | } 34 | 35 | $this->data['embeddedsOne']['{{ name }}'] = $value; 36 | 37 | return $this; 38 | } 39 | 40 | /** 41 | * Returns the "{{ name }}" embedded one. 42 | * 43 | * @return \{{ embedded.class }}|null The "{{ name }}" embedded one. 44 | */ 45 | public function get{{ name|ucfirst }}() 46 | { 47 | if (!isset($this->data['embeddedsOne']['{{ name }}'])) { 48 | {# not embedded #} 49 | {% if not config_class.isEmbedded %} 50 | if ($this->isNew()) { 51 | $this->data['embeddedsOne']['{{ name }}'] = null; 52 | } elseif ( 53 | !isset($this->data['embeddedsOne']) || 54 | !array_key_exists('{{ name }}', $this->data['embeddedsOne'])) 55 | { 56 | if (!$this->isFieldInQuery('{{ name }}')) { 57 | $this->loadFull(); 58 | } 59 | 60 | if (!isset($this->data['embeddedsOne']['{{ name }}'])) { 61 | $this->data['embeddedsOne']['{{ name }}'] = null; 62 | } 63 | } 64 | {# embedded #} 65 | {% else %} 66 | if ( 67 | (!isset($this->data['embeddedsOne']) || 68 | !array_key_exists('{{ name }}', $this->data['embeddedsOne'])) 69 | && 70 | ($rap = $this->getRootAndPath()) 71 | && 72 | !$this->isEmbeddedOneChangedInParent() 73 | && 74 | false === strpos($rap['path'], '._add')) 75 | { 76 | if (!$this->isFieldInQuery('{{ name }}')) { 77 | $this->loadFull(); 78 | } 79 | } 80 | if (!isset($this->data['embeddedsOne']['{{ name }}'])) { 81 | $this->data['embeddedsOne']['{{ name }}'] = null; 82 | } 83 | {% endif %} 84 | } 85 | 86 | return $this->data['embeddedsOne']['{{ name }}']; 87 | } 88 | {% endif %} 89 | {% endfor %} 90 | -------------------------------------------------------------------------------- /src/Mongator/Group/PolymorphicReferenceGroup.php: -------------------------------------------------------------------------------- 1 | 7 | * 8 | * This source file is subject to the MIT license that is bundled 9 | * with this source code in the file LICENSE. 10 | */ 11 | 12 | namespace Mongator\Group; 13 | 14 | use Mongator\Archive; 15 | 16 | /** 17 | * PolymorphicReferenceGroup. 18 | * 19 | * @author Pablo Díez 20 | * 21 | * @api 22 | */ 23 | class PolymorphicReferenceGroup extends PolymorphicGroup 24 | { 25 | /** 26 | * Constructor. 27 | * 28 | * @param string $discriminatorField The discriminator field. 29 | * @param \Mongator\Document\AbstractDocument $parent The parent document. 30 | * @param string $field The reference field. 31 | * @param array|Boolean $discriminatorMap The discriminator map if exists, otherwise false. 32 | * 33 | * @api 34 | */ 35 | public function __construct($discriminatorField, $parent, $field, $discriminatorMap = false) 36 | { 37 | parent::__construct($discriminatorField); 38 | 39 | $this->getArchive()->set('parent', $parent); 40 | $this->getArchive()->set('field', $field); 41 | $this->getArchive()->set('discriminatorMap', $discriminatorMap); 42 | } 43 | 44 | /** 45 | * Returns the parent document. 46 | * 47 | * @return \Mongator\Document\AbstractDocument The parent document. 48 | * 49 | * @api 50 | */ 51 | public function getParent() 52 | { 53 | return $this->getArchive()->get('parent'); 54 | } 55 | 56 | /** 57 | * Returns the reference field. 58 | * 59 | * @return string The reference field. 60 | * 61 | * @api 62 | */ 63 | public function getField() 64 | { 65 | return $this->getArchive()->get('field'); 66 | } 67 | 68 | /** 69 | * Returns the discriminator map. 70 | * 71 | * @return array|Boolean The discriminator map. 72 | * 73 | * @api 74 | */ 75 | public function getDiscriminatorMap() 76 | { 77 | return $this->getArchive()->get( 'discriminatorMap'); 78 | } 79 | 80 | /** 81 | * {@inheritdoc} 82 | */ 83 | protected function doInitializeSavedData() 84 | { 85 | return (array) $this->getParent()->get($this->getField()); 86 | } 87 | 88 | /** 89 | * {@inheritdoc} 90 | */ 91 | protected function doInitializeSaved(array $data) 92 | { 93 | $parent = $this->getParent(); 94 | $mongator = $parent->getMongator(); 95 | 96 | $discriminatorField = $this->getDiscriminatorField(); 97 | $discriminatorMap = $this->getDiscriminatorMap(); 98 | 99 | $ids = array(); 100 | foreach ($data as $datum) { 101 | if ($discriminatorMap) { 102 | $documentClass = $discriminatorMap[$datum[$discriminatorField]]; 103 | } else { 104 | $documentClass = $datum[$discriminatorField]; 105 | } 106 | $ids[$documentClass][] = $datum['id']; 107 | } 108 | 109 | $documents = array(); 110 | foreach ($ids as $documentClass => $documentClassIds) { 111 | foreach ((array) $mongator->getRepository($documentClass)->findById($documentClassIds) as $document) { 112 | $documents[] = $document; 113 | } 114 | } 115 | 116 | return $documents; 117 | } 118 | } 119 | -------------------------------------------------------------------------------- /src/Mongator/Id/IdGeneratorContainer.php: -------------------------------------------------------------------------------- 1 | 7 | * 8 | * This source file is subject to the MIT license that is bundled 9 | * with this source code in the file LICENSE. 10 | */ 11 | 12 | namespace Mongator\Id; 13 | 14 | /** 15 | * Container of id generators. 16 | * 17 | * @author Pablo Díez 18 | */ 19 | class IdGeneratorContainer 20 | { 21 | private static $map = array( 22 | 'none' => 'Mongator\Id\NoneIdGenerator', 23 | 'native' => 'Mongator\Id\NativeIdGenerator', 24 | 'sequence' => 'Mongator\Id\SequenceIdGenerator', 25 | ); 26 | 27 | private static $idGenerators = array(); 28 | 29 | /** 30 | * Returns whether or not an id generator exists. 31 | * 32 | * @param string $name The name. 33 | * 34 | * @return Boolean Whether or not the id generator exists. 35 | */ 36 | public static function has($name) 37 | { 38 | return isset(static::$map[$name]); 39 | } 40 | 41 | /** 42 | * Add an id generator. 43 | * 44 | * @param string $name The name. 45 | * @param string $class The class. 46 | * 47 | * @throws \InvalidArgumentException If the id generator already exists. 48 | * @throws \InvalidArgumentException If the class is not a subclass of Mongator\Id\IdGenerator. 49 | */ 50 | public static function add($name, $class) 51 | { 52 | if (static::has($name)) { 53 | throw new \InvalidArgumentException(sprintf('The id generator "%s" already exists.', $name)); 54 | } 55 | 56 | $r = new \ReflectionClass($class); 57 | if (!$r->isSubclassOf('Mongator\Id\BaseIdGenerator')) { 58 | throw new \InvalidArgumentException(sprintf('The class "%s" is not a subclass of Mongator\Id\BaseIdGenerator.', $class)); 59 | } 60 | 61 | static::$map[$name] = $class; 62 | } 63 | 64 | /** 65 | * Returns an id generator. 66 | * 67 | * @param string $name The name. 68 | * 69 | * @return \Mongator\Id\BaseIdGenerator The id generator. 70 | * 71 | * @throws \InvalidArgumentException If the id generator does not exists. 72 | */ 73 | public static function get($name) 74 | { 75 | if (!isset(static::$idGenerators[$name])) { 76 | if (!static::has($name)) { 77 | throw new \InvalidArgumentException(sprintf('The id generator "%s" does not exists.', $name)); 78 | } 79 | 80 | static::$idGenerators[$name] = new static::$map[$name]; 81 | } 82 | 83 | return static::$idGenerators[$name]; 84 | } 85 | 86 | /** 87 | * Remove an id generator. 88 | * 89 | * @param string $name The name. 90 | * 91 | * @throws \InvalidArgumentException If the id generator does not exists. 92 | */ 93 | public static function remove($name) 94 | { 95 | if (!static::has($name)) { 96 | throw new \InvalidArgumentException(sprintf('The id generator "%s" does not exists.', $name)); 97 | } 98 | 99 | unset(static::$map[$name], static::$idGenerators[$name]); 100 | } 101 | 102 | /** 103 | * Reset the id generators. 104 | */ 105 | public static function reset() 106 | { 107 | static::$map = array( 108 | 'none' => 'Mongator\Id\NoneIdGenerator', 109 | 'native' => 'Mongator\Id\NativeIdGenerator', 110 | 'sequence' => 'Mongator\Id\SequenceIdGenerator', 111 | ); 112 | 113 | static::$idGenerators = array(); 114 | } 115 | } 116 | -------------------------------------------------------------------------------- /src/Mongator/Query/Result.php: -------------------------------------------------------------------------------- 1 | 7 | * 8 | * This source file is subject to the MIT license that is bundled 9 | * with this source code in the file LICENSE. 10 | */ 11 | 12 | namespace Mongator\Query; 13 | 14 | use MongoDB\Driver\Cursor; 15 | 16 | class Result implements \Iterator, \Countable, \Serializable 17 | { 18 | private $count; 19 | private $iterator; 20 | 21 | public function __construct($input) 22 | { 23 | if ( $input instanceof Cursor) return $this->iterator = new \IteratorIterator($input); 24 | if ( $input instanceOf \Iterator ) return $this->iterator = $input; 25 | if ( $input instanceOf \ArrayObject ) return $this->iterator = $input->getIterator(); 26 | 27 | throw new \InvalidArgumentException(sprintf( 28 | 'Invalid object, must be instance of Iterator or ArrayObject, instance of %s given', 29 | get_class($input) 30 | )); 31 | } 32 | 33 | /** 34 | * Return the iterator 35 | * 36 | * @return Iterator 37 | * 38 | * @api 39 | */ 40 | public function getIterator() 41 | { 42 | return $this->iterator; 43 | } 44 | 45 | /** 46 | * Return the current element 47 | * 48 | * @return mixed 49 | * 50 | * @api 51 | */ 52 | public function setCount($count) 53 | { 54 | $this->count = $count; 55 | } 56 | 57 | /** 58 | * Return the current element 59 | * 60 | * @return mixed 61 | * 62 | * @api 63 | */ 64 | public function count() 65 | { 66 | if ( !$this->count ) return $this->iterator->count(); 67 | 68 | if ($this->count instanceOf \Closure) { 69 | $this->count = $this->count->__invoke(); 70 | } 71 | 72 | return $this->count; 73 | } 74 | 75 | /** 76 | * Return the current element 77 | * 78 | * @return mixed 79 | * 80 | * @api 81 | */ 82 | public function current() 83 | { 84 | return $this->iterator->current(); 85 | } 86 | 87 | /** 88 | * Return the key of the current element 89 | * 90 | * @return string 91 | * 92 | * @api 93 | */ 94 | public function key() 95 | { 96 | return $this->iterator->key(); 97 | } 98 | 99 | /** 100 | * Move forward to next element 101 | * 102 | * @api 103 | */ 104 | public function next() 105 | { 106 | return $this->iterator->next(); 107 | } 108 | 109 | /** 110 | * Rewind the Iterator to the first elemen 111 | * 112 | * @api 113 | */ 114 | public function rewind() 115 | { 116 | return $this->iterator->rewind(); 117 | } 118 | 119 | /** 120 | * Checks if current position is valid 121 | * 122 | * @return boolean 123 | * 124 | * @api 125 | */ 126 | public function valid() 127 | { 128 | return $this->iterator->valid(); 129 | } 130 | 131 | /** 132 | * String representation of object 133 | * 134 | * @return string 135 | * 136 | * @api 137 | */ 138 | public function serialize() 139 | { 140 | $array = array( 141 | 'count' => $this->count(), 142 | 'data' => iterator_to_array($this->iterator) 143 | ); 144 | 145 | return serialize($array); 146 | } 147 | 148 | /** 149 | * Constructs the object 150 | * 151 | * @api 152 | */ 153 | public function unserialize($data) 154 | { 155 | $array = unserialize($data); 156 | $this->count = $array['count']; 157 | $this->iterator = new \ArrayIterator($array['data']); 158 | } 159 | } 160 | --------------------------------------------------------------------------------