/** * Register custom doctrine types */ public function __construct() { if (class_exists('\\Doctrine\\ODM\\MongoDB\\Types\\Type')) { \Doctrine\ODM\MongoDB\Types\Type::registerType(self::ODM_ENTITIES_TYPE, 'Akeneo\\Bundle\\StorageUtilsBundle\\Doctrine\\MongoDBODM\\Types\\Entities'); \Doctrine\ODM\MongoDB\Types\Type::registerType(self::ODM_ENTITY_TYPE, 'Akeneo\\Bundle\\StorageUtilsBundle\\Doctrine\\MongoDBODM\\Types\\Entity'); } }
/** * Register cuctom doctrine types */ public function __construct() { if (class_exists('\\Doctrine\\ODM\\MongoDB\\Types\\Type')) { \Doctrine\ODM\MongoDB\Types\Type::registerType(self::ODM_ENTITIES_TYPE, 'Pim\\Bundle\\CatalogBundle\\MongoDB\\Type\\Entities'); \Doctrine\ODM\MongoDB\Types\Type::registerType(self::ODM_ENTITY_TYPE, 'Pim\\Bundle\\CatalogBundle\\MongoDB\\Type\\Entity'); } }
/** * @dataProvider convertToPHPValueProvider * * @param array $ref reference as from mongo * @param string $routeId name of route that should get loaded * @param string $url url we expect to result from the conversion * * @return void */ public function testConvertToPHPValue($ref, $routeId, $url) { $this->doubles['router']->expects($this->once())->method('generate')->with($this->equalTo($routeId), $this->equalTo(array('id' => $ref['$id'])))->will($this->returnValue($url)); $sut = Type::getType('extref'); $sut->setRouter($this->doubles['router']); $this->assertEquals($url, $sut->convertToPHPValue($ref)); }
public function installTypes() { foreach ($this->types as $type => $class) { if (!MongoDBType::hasType($type)) { MongoDBType::addType($type, $class); } } }
/** * @param mixed|self $expression * @return mixed */ protected function ensureArray($expression) { // Convert field names in expressions if (is_string($expression) && substr($expression, 0, 1) === '$') { return '$' . $this->getDocumentPersister()->prepareFieldName(substr($expression, 1)); } // Convert PHP types to MongoDB types for everything else return Type::convertPHPToDatabaseValue(parent::ensureArray($expression)); }
/** * inject services into custom type * * @return void */ public function boot() { /* @var $router Router */ $router = $this->container->get('router'); /* @var $type \Graviton\DocumentBundle\Types\ExtReference */ $type = Type::getType('extref'); $type->setRouter($router); $type->setMapping($this->container->getParameter('graviton.document.type.extref.mapping')); }
/** * @dataProvider provideDatabaseToPHPValues */ public function testClosureToPHP($input, $output) { $type = Type::getType(Type::DATE); $return = null; call_user_func(function ($value) use($type, &$return) { eval($type->closureToPHP()); }, $input); $this->assertInstanceOf('DateTime', $return); $this->assertTimestampEquals($output, $return); }
/** * Sets up services on the bootstrap event. * * @internal * Creates the translation service and a ModuleRouteListener * * @param MvcEvent $e */ public function onBootstrap(MvcEvent $e) { // Register the TimezoneAwareDate type with DoctrineMongoODM // Use it in Annotions ( @Field(type="tz_date") ) if (!DoctrineType::hasType('tz_date')) { DoctrineType::addType('tz_date', '\\Core\\Repository\\DoctrineMongoODM\\Types\\TimezoneAwareDate'); } $sm = $e->getApplication()->getServiceManager(); $translator = $sm->get('translator'); // initialise translator! \Zend\Validator\AbstractValidator::setDefaultTranslator($translator); $eventManager = $e->getApplication()->getEventManager(); $sharedManager = $eventManager->getSharedManager(); # $LogListener = new LogListener(); # $LogListener->attach($eventManager); if (!\Zend\Console\Console::isConsole()) { $redirectCallback = function () use($e) { $routeMatch = $e->getRouteMatch(); $lang = $routeMatch ? $routeMatch->getParam('lang', 'en') : 'en'; $uri = $e->getRouter()->getBaseUrl() . '/' . $lang . '/error'; header('Location: ' . $uri); }; $errorHandlerListener = new ErrorHandlerListener($sm->get('ErrorLogger'), $redirectCallback); $errorHandlerListener->attach($eventManager); $languageRouteListener = new LanguageRouteListener(); $languageRouteListener->attach($eventManager); $ajaxRenderListener = new AjaxRenderListener(); $ajaxRenderListener->attach($eventManager); $enforceJsonResponseListener = new EnforceJsonResponseListener(); $enforceJsonResponseListener->attach($eventManager); $stringListener = new StringListener(); $stringListener->attach($eventManager); // $notificationlistener = $sm->get('Core/Listener/Notification'); $notificationlistener->attachShared($sharedManager); $notificationAjaxHandler = new NotificationAjaxHandler(); $eventManager->attach(MvcEvent::EVENT_DISPATCH, array($notificationAjaxHandler, 'injectView'), -20); $notificationlistener->attach(NotificationEvent::EVENT_NOTIFICATION_HTML, array($notificationAjaxHandler, 'render'), -20); } $persistenceListener = new PersistenceListener(); $persistenceListener->attach($eventManager); $eventManager->attach(MvcEvent::EVENT_DISPATCH_ERROR, function ($event) { $application = $event->getApplication(); if ($application::ERROR_EXCEPTION == $event->getError()) { $ex = $event->getParam('exception'); if (404 == $ex->getCode()) { $event->setError($application::ERROR_CONTROLLER_NOT_FOUND); } } }, 500); $eventManager->attach(MvcEvent::EVENT_DISPATCH, function ($event) use($eventManager) { $eventManager->trigger('postDispatch', $event); }, -150); }
/** * @param ClassMetadata $classMetadata */ protected function checkCoordinateType(ClassMetadata $classMetadata) { foreach ($classMetadata->fieldMappings as $fieldName => $mapping) { if (isset($mapping['cubiche:coordinate'])) { $type = 'Coordinate'; if (!Type::hasType($type)) { Type::registerType($type, CoordinateType::class); } $classMetadata->fieldMappings[$fieldName]['type'] = $type; } } }
public function convertToPHPValue($value) { if ($value === null) { return null; } if (!is_array($value)) { throw new CustomTypeException('Array expected.'); } $converter = Type::getType('date'); $value = array_map(function ($date) use($converter) { return $converter->convertToPHPValue($date); }, array_values($value)); return $value; }
/** * @param ClassMetadata $classMetadata * * @throws MappingException */ protected function checkIdType(ClassMetadata $classMetadata) { foreach ($classMetadata->fieldMappings as $fieldName => $mapping) { if (isset($mapping['cubiche:id'])) { $idMapping = $mapping['cubiche:id']; $type = str_replace('\\', '.', $idMapping['type']); if (!Type::hasType($type)) { Type::registerType($type, DynamicIdType::class); Type::getType($type)->setTargetClass($idMapping['type']); } $classMetadata->fieldMappings[$fieldName]['type'] = $type; } } }
/** * {@inheritdoc} */ public function convertToPHPValue($value) { if ($value === null) { return new ArrayList(); } if (is_array($value) || $value instanceof \Traversable) { $items = array(); $type = Type::getType($this->innerType); foreach ($value as $item) { $items[] = $type->convertToPHPValue($item); } return new ArrayList($items); } return parent::convertToPHPValue($value); }
public function testCreation() { $logger = $this->getMockForAbstractClass('DoctrineMongoODMModule\\Logging\\Logger'); $metadataCache = $this->getMockForAbstractClass('Doctrine\\Common\\Cache\\Cache'); $mappingDriver = $this->getMockForAbstractClass('Doctrine\\Common\\Persistence\\Mapping\\Driver\\MappingDriver'); $serviceLocator = $this->getMockForAbstractClass('Zend\\ServiceManager\\ServiceLocatorInterface'); $serviceLocator->expects($this->exactly(4))->method('get')->withConsecutive(array('Configuration'), array('stubbed_logger'), array('doctrine.cache.stubbed_metadatacache'), array('doctrine.driver.stubbed_driver'))->willReturnOnConsecutiveCalls(array('doctrine' => array('configuration' => array('odm_test' => array('logger' => 'stubbed_logger', 'metadata_cache' => 'stubbed_metadatacache', 'driver' => 'stubbed_driver', 'generate_proxies' => true, 'proxy_dir' => 'data/DoctrineMongoODMModule/Proxy', 'proxy_namespace' => 'DoctrineMongoODMModule\\Proxy', 'generate_hydrators' => true, 'hydrator_dir' => 'data/DoctrineMongoODMModule/Hydrator', 'hydrator_namespace' => 'DoctrineMongoODMModule\\Hydrator', 'default_db' => 'default_db', 'filters' => array(), 'types' => array('CustomType' => 'DoctrineMongoODMModuleTest\\Assets\\CustomType'), 'classMetadataFactoryName' => 'stdClass')))), $logger, $metadataCache, $mappingDriver); $factory = new ConfigurationFactory('odm_test'); $config = $factory->createService($serviceLocator); $this->assertInstanceOf('Doctrine\\ODM\\MongoDB\\Configuration', $config); $this->assertNotNull($config->getLoggerCallable()); $this->assertSame($metadataCache, $config->getMetadataCacheImpl()); $this->assertSame($mappingDriver, $config->getMetadataDriverImpl()); $this->assertInstanceOf('DoctrineMongoODMModuleTest\\Assets\\CustomType', \Doctrine\ODM\MongoDB\Types\Type::getType('CustomType')); }
/** * @param ClassMetadata $classMetadata */ protected function checkTypes(ClassMetadata $classMetadata) { $types = array_keys($this->typeMapping); foreach ($classMetadata->fieldMappings as $fieldName => $mapping) { foreach ($types as $type) { if (isset($mapping['cubiche:' . $type])) { $typeName = substr($this->typeMapping[$type], strrpos($this->typeMapping[$type], '\\') + 1); if (!Type::hasType($typeName)) { Type::registerType($typeName, $this->typeMapping[$type]); } $classMetadata->fieldMappings[$fieldName]['type'] = $typeName; break; } } } }
/** * @return \Doctrine\ODM\MongoDB\DocumentManager */ public function dm() { if ($this->dm === null) { $this->dm = $this->createTestDocumentManager(); $this->uow = $this->dm->getUnitOfWork(); Type::addType('Phonenumber', PhonenumberType::class); Type::addType('Role', RoleType::class); $this->dm->getEventManager()->addEventSubscriber(new MetadataEventSubscriber()); $this->dm->getEventManager()->addEventSubscriber(new CollectionsEventSubscriber()); $this->dm->getEventManager()->addEventSubscriber(new ModelEventSubscriber()); $this->dm->getEventManager()->addEventSubscriber(new IdentityEventSubscriber()); $this->dm->getEventManager()->addEventSubscriber(new GeolocationEventSubscriber()); $this->dm->getEventManager()->addEventSubscriber(new SystemEventSubscriber()); } return $this->dm; }
public function setUp() { Type::hasType('object') ? Type::overrideType('object', 'Payum\\Core\\Bridge\\Doctrine\\Types\\ObjectType') : Type::addType('object', 'Payum\\Core\\Bridge\\Doctrine\\Types\\ObjectType'); $config = new Configuration(); $config->setProxyDir(\sys_get_temp_dir()); $config->setProxyNamespace('PayumTestsProxies'); $config->setHydratorDir(\sys_get_temp_dir()); $config->setHydratorNamespace('PayumTestsHydrators'); $config->setMetadataDriverImpl($this->getMetadataDriverImpl($config)); $config->setMetadataCacheImpl(new ArrayCache()); $config->setDefaultDB('payum_tests'); $connection = new Connection(null, array(), $config); $this->dm = DocumentManager::create($connection, $config); foreach ($this->dm->getConnection()->selectDatabase('payum_tests')->listCollections() as $collection) { $collection->drop(); } }
/** * @param \Zend\ServiceManager\ServiceLocatorInterface $serviceLocator * @return \Doctrine\ODM\MongoDB\Configuration * @throws \Exception */ public function createService(ServiceLocatorInterface $serviceLocator) { /** @var $options \DoctrineMongoODMModule\Options\Configuration */ $options = $this->getOptions($serviceLocator, 'configuration'); $config = new Configuration(); // logger if ($options->getLogger()) { $logger = $serviceLocator->get($options->getLogger()); $config->setLoggerCallable(array($logger, 'log')); } // proxies $config->setAutoGenerateProxyClasses($options->getGenerateProxies()); $config->setProxyDir($options->getProxyDir()); $config->setProxyNamespace($options->getProxyNamespace()); // hydrators $config->setAutoGenerateHydratorClasses($options->getGenerateHydrators()); $config->setHydratorDir($options->getHydratorDir()); $config->setHydratorNamespace($options->getHydratorNamespace()); // default db $config->setDefaultDB($options->getDefaultDb()); // caching $config->setMetadataCacheImpl($serviceLocator->get($options->getMetadataCache())); // retries $config->setRetryConnect($options->getRetryConnect()); $config->setRetryQuery($options->getRetryQuery()); // Register filters foreach ($options->getFilters() as $alias => $class) { $config->addFilter($alias, $class); } // the driver $config->setMetadataDriverImpl($serviceLocator->get($options->getDriver())); // metadataFactory, if set if ($factoryName = $options->getClassMetadataFactoryName()) { $config->setClassMetadataFactoryName($factoryName); } // custom types foreach ($options->getTypes() as $name => $class) { if (Type::hasType($name)) { Type::overrideType($name, $class); } else { Type::addType($name, $class); } } return $config; }
public function setUp() { $this->skipTestsIfPhp7(); if (false == (class_exists(\MongoId::class) && class_exists(Connection::class))) { $this->markTestSkipped('Either mongo extension or\\and doctrine\\mongo-odm are not installed.'); } Type::hasType('object') ? Type::overrideType('object', 'Payum\\Core\\Bridge\\Doctrine\\Types\\ObjectType') : Type::addType('object', 'Payum\\Core\\Bridge\\Doctrine\\Types\\ObjectType'); $config = new Configuration(); $config->setProxyDir(\sys_get_temp_dir()); $config->setProxyNamespace('PayumTestsProxies'); $config->setHydratorDir(\sys_get_temp_dir()); $config->setHydratorNamespace('PayumTestsHydrators'); $config->setMetadataDriverImpl($this->getMetadataDriverImpl($config)); $config->setMetadataCacheImpl(new ArrayCache()); $config->setDefaultDB('payum_tests'); $connection = new Connection(null, array(), $config); $this->dm = DocumentManager::create($connection, $config); foreach ($this->dm->getConnection()->selectDatabase('payum_tests')->listCollections() as $collection) { $collection->drop(); } }
public function bootstrapDoctrine(MvcEvent $event) { $serviceManager = $event->getApplication()->getServiceManager(); /** @var Options\ModuleOptions $moduleOptions */ $moduleOptions = $serviceManager->get(__NAMESPACE__ . '\\Options\\ModuleOptions'); if ($moduleOptions->getDoctrine()->registerUuidType()) { if (!class_exists('Rhumsaa\\Uuid\\Uuid')) { throw new Exception\RuntimeException('Failed to register "uuid" Doctrine mapping type: ' . 'Missing required class Rhumsaa\\Uuid\\Uuid'); } if (class_exists(DoctrineOrmTypes\Type::CLASS)) { DoctrineOrmTypes\Type::addType(DoctrineUuidType::NAME, DoctrineUuidType::CLASS); } if (class_exists(DoctrineOdmTypes\Type::CLASS)) { DoctrineOdmTypes\Type::registerType(DoctrineOdmUuidType::NAME, DoctrineOdmUuidType::CLASS); } } if ($moduleOptions->getDoctrine()->registerDatetimeImmutableType()) { if (class_exists(DoctrineOdmTypes\Type::CLASS)) { DoctrineOdmTypes\Type::registerType(DoctrineOdmDateTimeImmutType::NAME, DoctrineOdmDateTimeImmutType::CLASS); } } if ($moduleOptions->getDoctrine()->registerDatetimeNoTzType()) { if (class_exists(DoctrineOdmTypes\Type::CLASS)) { DoctrineOdmTypes\Type::registerType(DoctrineOdmDateTimeNoTzType::NAME, DoctrineOdmDateTimeNoTzType::CLASS); } } if ($moduleOptions->getDoctrine()->registerDatetimeImmutableNoTzType()) { if (class_exists(DoctrineOdmTypes\Type::CLASS)) { DoctrineOdmTypes\Type::registerType(DoctrineOdmDateTimeImmutNoTzType::NAME, DoctrineOdmDateTimeImmutNoTzType::CLASS); } } // /** @var \Zend\ServiceManager\ServiceManager $serviceManager */ // $serviceManager = $event->getApplication()->getServiceManager(); // // /** @var \Doctrine\ORM\EntityManager $entityManager */ // $entityManager = $serviceManager->get('Doctrine\ORM\EntityManager'); // $entityManager->getConnection()->getDatabasePlatform()->registerDoctrineTypeMapping('db_mytype', 'mytype'); }
/** * {@inheritDoc} */ public function createStorage($modelClass, $idProperty, array $options) { if (false == Type::hasType('object')) { Type::addType('object', 'Payum\\Core\\Bridge\\Doctrine\\Types\\ObjectType'); } $driver = new MappingDriverChain(); // payum's basic models $coreRootDir = dirname((new \ReflectionClass(GatewayInterface::class))->getFileName()); $driver->addDriver(new XmlDriver(new SymfonyFileLocator(array($coreRootDir . '/Bridge/Doctrine/Resources/mapping' => 'Payum\\Core\\Model'), '.mongodb.xml'), '.mongodb.xml'), 'Payum\\Core\\Model'); // your models $sererRootDir = dirname((new \ReflectionClass(Application::class))->getFileName()); AnnotationDriver::registerAnnotationClasses(); $driver->addDriver(new AnnotationDriver(new AnnotationReader(), array($sererRootDir . '/Model')), 'Payum\\Server\\Model'); $config = new Configuration(); $config->setProxyDir(\sys_get_temp_dir() . '/PayumServer'); $config->setProxyNamespace('Proxies'); $config->setHydratorDir(\sys_get_temp_dir() . '/PayumServer'); $config->setHydratorNamespace('Hydrators'); $config->setMetadataDriverImpl($driver); $config->setMetadataCacheImpl(new ArrayCache()); $config->setDefaultDB($options['databaseName']); $connection = new Connection($options['host'], array(), $config); return new DoctrineStorage(DocumentManager::create($connection, $config), $modelClass); }
/** * @param ClassMetadata $class * @param string $hydratorClassName * @param string $fileName */ private function generateHydratorClass(ClassMetadata $class, $hydratorClassName, $fileName) { $code = ''; foreach ($class->fieldMappings as $fieldName => $mapping) { if (isset($mapping['alsoLoadFields'])) { foreach ($mapping['alsoLoadFields'] as $name) { $code .= sprintf(<<<EOF /** @AlsoLoad("{$name}") */ if (!array_key_exists('%1\$s', \$data) && array_key_exists('{$name}', \$data)) { \$data['%1\$s'] = \$data['{$name}']; } EOF , $mapping['name']); } } if ($mapping['type'] === 'date') { $code .= sprintf(<<<EOF /** @Field(type="date") */ if (isset(\$data['%1\$s'])) { \$value = \$data['%1\$s']; %3\$s \$this->class->reflFields['%2\$s']->setValue(\$document, clone \$return); \$hydratedData['%2\$s'] = \$return; } EOF , $mapping['name'], $mapping['fieldName'], Type::getType($mapping['type'])->closureToPHP()); } elseif (!isset($mapping['association'])) { $code .= sprintf(<<<EOF /** @Field(type="{$mapping['type']}") */ if (isset(\$data['%1\$s'])) { \$value = \$data['%1\$s']; %3\$s \$this->class->reflFields['%2\$s']->setValue(\$document, \$return); \$hydratedData['%2\$s'] = \$return; } EOF , $mapping['name'], $mapping['fieldName'], Type::getType($mapping['type'])->closureToPHP()); } elseif ($mapping['association'] === ClassMetadata::REFERENCE_ONE && $mapping['isOwningSide']) { $code .= sprintf(<<<EOF /** @ReferenceOne */ if (isset(\$data['%1\$s'])) { \$reference = \$data['%1\$s']; if (isset(\$this->class->fieldMappings['%2\$s']['simple']) && \$this->class->fieldMappings['%2\$s']['simple']) { \$className = \$this->class->fieldMappings['%2\$s']['targetDocument']; \$mongoId = \$reference; } else { \$className = \$this->unitOfWork->getClassNameForAssociation(\$this->class->fieldMappings['%2\$s'], \$reference); \$mongoId = \$reference['\$id']; } \$targetMetadata = \$this->dm->getClassMetadata(\$className); \$id = \$targetMetadata->getPHPIdentifierValue(\$mongoId); \$return = \$this->dm->getReference(\$className, \$id); \$this->class->reflFields['%2\$s']->setValue(\$document, \$return); \$hydratedData['%2\$s'] = \$return; } EOF , $mapping['name'], $mapping['fieldName']); } elseif ($mapping['association'] === ClassMetadata::REFERENCE_ONE && $mapping['isInverseSide']) { if (isset($mapping['repositoryMethod']) && $mapping['repositoryMethod']) { $code .= sprintf(<<<EOF \$className = \$this->class->fieldMappings['%2\$s']['targetDocument']; \$return = \$this->dm->getRepository(\$className)->%3\$s(\$document); \$this->class->reflFields['%2\$s']->setValue(\$document, \$return); \$hydratedData['%2\$s'] = \$return; EOF , $mapping['name'], $mapping['fieldName'], $mapping['repositoryMethod']); } else { $code .= sprintf(<<<EOF \$mapping = \$this->class->fieldMappings['%2\$s']; \$className = \$mapping['targetDocument']; \$targetClass = \$this->dm->getClassMetadata(\$mapping['targetDocument']); \$mappedByMapping = \$targetClass->fieldMappings[\$mapping['mappedBy']]; \$mappedByFieldName = isset(\$mappedByMapping['simple']) && \$mappedByMapping['simple'] ? \$mapping['mappedBy'] : \$mapping['mappedBy'].'.\$id'; \$criteria = array_merge( array(\$mappedByFieldName => \$data['_id']), isset(\$this->class->fieldMappings['%2\$s']['criteria']) ? \$this->class->fieldMappings['%2\$s']['criteria'] : array() ); \$sort = isset(\$this->class->fieldMappings['%2\$s']['sort']) ? \$this->class->fieldMappings['%2\$s']['sort'] : array(); \$return = \$this->unitOfWork->getDocumentPersister(\$className)->load(\$criteria, null, array(), 0, \$sort); \$this->class->reflFields['%2\$s']->setValue(\$document, \$return); \$hydratedData['%2\$s'] = \$return; EOF , $mapping['name'], $mapping['fieldName']); } } elseif ($mapping['association'] === ClassMetadata::REFERENCE_MANY || $mapping['association'] === ClassMetadata::EMBED_MANY) { $code .= sprintf(<<<EOF /** @Many */ \$mongoData = isset(\$data['%1\$s']) ? \$data['%1\$s'] : null; \$return = new \\Doctrine\\ODM\\MongoDB\\PersistentCollection(new \\Doctrine\\Common\\Collections\\ArrayCollection(), \$this->dm, \$this->unitOfWork); \$return->setHints(\$hints); \$return->setOwner(\$document, \$this->class->fieldMappings['%2\$s']); \$return->setInitialized(false); if (\$mongoData) { \$return->setMongoData(\$mongoData); } \$this->class->reflFields['%2\$s']->setValue(\$document, \$return); \$hydratedData['%2\$s'] = \$return; EOF , $mapping['name'], $mapping['fieldName']); } elseif ($mapping['association'] === ClassMetadata::EMBED_ONE) { $code .= sprintf(<<<EOF /** @EmbedOne */ if (isset(\$data['%1\$s'])) { \$embeddedDocument = \$data['%1\$s']; \$className = \$this->unitOfWork->getClassNameForAssociation(\$this->class->fieldMappings['%2\$s'], \$embeddedDocument); \$embeddedMetadata = \$this->dm->getClassMetadata(\$className); \$return = \$embeddedMetadata->newInstance(); \$this->unitOfWork->setParentAssociation(\$return, \$this->class->fieldMappings['%2\$s'], \$document, '%1\$s'); \$embeddedData = \$this->dm->getHydratorFactory()->hydrate(\$return, \$embeddedDocument, \$hints); \$embeddedId = \$embeddedMetadata->identifier && isset(\$embeddedData[\$embeddedMetadata->identifier]) ? \$embeddedData[\$embeddedMetadata->identifier] : null; \$this->unitOfWork->registerManaged(\$return, \$embeddedId, \$embeddedData); \$this->class->reflFields['%2\$s']->setValue(\$document, \$return); \$hydratedData['%2\$s'] = \$return; } EOF , $mapping['name'], $mapping['fieldName']); } } $namespace = $this->hydratorNamespace; $code = sprintf(<<<EOF <?php namespace {$namespace}; use Doctrine\\ODM\\MongoDB\\DocumentManager; use Doctrine\\ODM\\MongoDB\\Mapping\\ClassMetadata; use Doctrine\\ODM\\MongoDB\\Hydrator\\HydratorInterface; use Doctrine\\ODM\\MongoDB\\UnitOfWork; /** * THIS CLASS WAS GENERATED BY THE DOCTRINE ODM. DO NOT EDIT THIS FILE. */ class {$hydratorClassName} implements HydratorInterface { private \$dm; private \$unitOfWork; private \$class; public function __construct(DocumentManager \$dm, UnitOfWork \$uow, ClassMetadata \$class) { \$this->dm = \$dm; \$this->unitOfWork = \$uow; \$this->class = \$class; } public function hydrate(\$document, \$data, array \$hints = array()) { \$hydratedData = array(); %s return \$hydratedData; } } EOF , $code); if ($fileName === false) { if (!class_exists($namespace . '\\' . $hydratorClassName)) { eval(substr($code, 5)); } } else { $parentDirectory = dirname($fileName); if (!is_dir($parentDirectory) && false === @mkdir($parentDirectory, 0775, true)) { throw HydratorException::hydratorDirectoryNotWritable(); } if (!is_writable($parentDirectory)) { throw HydratorException::hydratorDirectoryNotWritable(); } $tmpFileName = $fileName . '.' . uniqid('', true); file_put_contents($tmpFileName, $code); rename($tmpFileName, $fileName); chmod($fileName, 0664); } }
public function testClosureToPHP() { $type = Type::getType('dough_money'); $this->assertSame('$return = new \\Dough\\Money\\Money($value);', $type->closureToPHP()); }
/** * Used to do the common work of computeChangeSet and recomputeSingleDocumentChangeSet * * @param \Doctrine\ODM\MongoDB\Mapping\ClassMetadata $class * @param object $document * @param boolean $recompute */ private function computeOrRecomputeChangeSet(ClassMetadata $class, $document, $recompute = false) { $oid = spl_object_hash($document); $actualData = $this->getDocumentActualData($document); $isNewDocument = !isset($this->originalDocumentData[$oid]); if ($isNewDocument) { // Document is either NEW or MANAGED but not yet fully persisted (only has an id). // These result in an INSERT. $this->originalDocumentData[$oid] = $actualData; $changeSet = array(); foreach ($actualData as $propName => $actualValue) { /* At this PersistentCollection shouldn't be here, probably it * was cloned and its ownership must be fixed */ if ($actualValue instanceof PersistentCollection && $actualValue->getOwner() !== $document) { $actualData[$propName] = $this->fixPersistentCollectionOwnership($actualValue, $document, $class, $propName); $actualValue = $actualData[$propName]; } $changeSet[$propName] = array(null, $actualValue); } $this->documentChangeSets[$oid] = $changeSet; } else { // Document is "fully" MANAGED: it was already fully persisted before // and we have a copy of the original data $originalData = $this->originalDocumentData[$oid]; $isChangeTrackingNotify = $class->isChangeTrackingNotify(); if ($isChangeTrackingNotify && !$recompute) { $changeSet = $this->documentChangeSets[$oid]; } else { $changeSet = array(); } foreach ($actualData as $propName => $actualValue) { // skip not saved fields if (isset($class->fieldMappings[$propName]['notSaved']) && $class->fieldMappings[$propName]['notSaved'] === true) { continue; } $orgValue = isset($originalData[$propName]) ? $originalData[$propName] : null; // skip if value has not changed if ($orgValue === $actualValue) { // but consider dirty GridFSFile instances as changed if (!(isset($class->fieldMappings[$propName]['file']) && $actualValue->isDirty())) { continue; } } // if relationship is a embed-one, schedule orphan removal to trigger cascade remove operations if (isset($class->fieldMappings[$propName]['embedded']) && $class->fieldMappings[$propName]['type'] === 'one') { if ($orgValue !== null) { $this->scheduleOrphanRemoval($orgValue); } $changeSet[$propName] = array($orgValue, $actualValue); continue; } // if owning side of reference-one relationship if (isset($class->fieldMappings[$propName]['reference']) && $class->fieldMappings[$propName]['type'] === 'one' && $class->fieldMappings[$propName]['isOwningSide']) { if ($orgValue !== null && $class->fieldMappings[$propName]['orphanRemoval']) { $this->scheduleOrphanRemoval($orgValue); } $changeSet[$propName] = array($orgValue, $actualValue); continue; } if ($isChangeTrackingNotify) { continue; } // ignore inverse side of reference-many relationship if (isset($class->fieldMappings[$propName]['reference']) && $class->fieldMappings[$propName]['type'] === 'many' && $class->fieldMappings[$propName]['isInverseSide']) { continue; } // Persistent collection was exchanged with the "originally" // created one. This can only mean it was cloned and replaced // on another document. if ($actualValue instanceof PersistentCollection && $actualValue->getOwner() !== $document) { $this->fixPersistentCollectionOwnership($actualValue, $document, $class, $propName); } // if embed-many or reference-many relationship if (isset($class->fieldMappings[$propName]['type']) && $class->fieldMappings[$propName]['type'] === 'many') { $changeSet[$propName] = array($orgValue, $actualValue); /* If original collection was exchanged with a non-empty value * and $set will be issued, there is no need to $unset it first */ if ($actualValue && $actualValue->isDirty() && CollectionHelper::usesSet($class->fieldMappings[$propName]['strategy'])) { continue; } if ($orgValue instanceof PersistentCollection) { $this->scheduleCollectionDeletion($orgValue); } continue; } // skip equivalent date values if (isset($class->fieldMappings[$propName]['type']) && $class->fieldMappings[$propName]['type'] === 'date') { $dateType = Type::getType('date'); $dbOrgValue = $dateType->convertToDatabaseValue($orgValue); $dbActualValue = $dateType->convertToDatabaseValue($actualValue); if ($dbOrgValue instanceof \MongoDate && $dbActualValue instanceof \MongoDate && $dbOrgValue == $dbActualValue) { continue; } } // regular field $changeSet[$propName] = array($orgValue, $actualValue); } if ($changeSet) { $this->documentChangeSets[$oid] = $recompute && isset($this->documentChangeSets[$oid]) ? $changeSet + $this->documentChangeSets[$oid] : $changeSet; $this->originalDocumentData[$oid] = $actualData; $this->scheduleForUpdate($document); } } // Look for changes in associations of the document $associationMappings = array_filter($class->associationMappings, function ($assoc) { return empty($assoc['notSaved']); }); foreach ($associationMappings as $mapping) { $value = $class->reflFields[$mapping['fieldName']]->getValue($document); if ($value === null) { continue; } $this->computeAssociationChanges($document, $mapping, $value); if (isset($mapping['reference'])) { continue; } $values = $mapping['type'] === ClassMetadata::ONE ? array($value) : $value->unwrap(); foreach ($values as $obj) { $oid2 = spl_object_hash($obj); if (isset($this->documentChangeSets[$oid2])) { $this->documentChangeSets[$oid][$mapping['fieldName']] = array($value, $value); if (!$isNewDocument) { $this->scheduleForUpdate($document); } break; } } } }
private function generateDocumentStubMethod(ClassMetadataInfo $metadata, $type, $fieldName, $typeHint = null, $defaultValue = null) { // Add/remove methods should use the singular form of the field name $formattedFieldName = in_array($type, array('add', 'remove')) ? Inflector::singularize($fieldName) : $fieldName; $methodName = $type . Inflector::classify($formattedFieldName); $variableName = Inflector::camelize($formattedFieldName); if ($this->hasMethod($methodName, $metadata)) { return; } $description = ucfirst($type) . ' ' . $variableName; $types = Type::getTypesMap(); $methodTypeHint = $typeHint && !isset($types[$typeHint]) ? '\\' . $typeHint . ' ' : null; $variableType = $typeHint ? $typeHint . ' ' : null; $replacements = array('<description>' => $description, '<methodTypeHint>' => $methodTypeHint, '<variableType>' => $variableType, '<variableName>' => $variableName, '<methodName>' => $methodName, '<fieldName>' => $fieldName, '<variableDefault>' => $defaultValue !== null ? ' = ' . $defaultValue : ''); $templateVar = sprintf('%sMethodTemplate', $type); $method = str_replace(array_keys($replacements), array_values($replacements), self::${$templateVar}); return $this->prefixCodeWithSpaces($method); }
public function test64bit1900Date() { if (PHP_INT_SIZE === 8) { $type = Type::getType(Type::DATE); $return = $type->convertToDatabaseValue('1900-01-01'); $this->assertInstanceOf('MongoDate', $return); $this->assertEquals(new \MongoDate(strtotime('1900-01-01')), $return); } else { $this->markTestSkipped("Platform is not 64-bit"); } }
/** * setup type we want to test * * @return void */ public function setUp() { Type::registerType('extref', ExtReferenceType::class); $this->type = Type::getType('extref'); }
/** * Casts the identifier to its database type. * * @param mixed $id * @return mixed $id */ public function getDatabaseIdentifierValue($id) { $idType = $this->fieldMappings[$this->identifier]['type']; return Type::getType($idType)->convertToDatabaseValue($id); }
/** * Returns the embedded document to be stored in MongoDB. * * The return value will usually be an associative array with string keys * corresponding to field names on the embedded document. An object may be * returned if the document is empty, to ensure that a BSON object will be * stored in lieu of an array. * * If $includeNestedCollections is true, nested collections will be included * in this prepared value and the option will cascade to all embedded * associations. If any nested PersistentCollections (embed or reference) * within this value were previously scheduled for deletion or update, they * will also be unscheduled. * * @param array $embeddedMapping * @param object $embeddedDocument * @param boolean $includeNestedCollections * @return array|object * @throws \UnexpectedValueException if an unsupported associating mapping is found */ public function prepareEmbeddedDocumentValue(array $embeddedMapping, $embeddedDocument, $includeNestedCollections = false) { $embeddedDocumentValue = array(); $class = $this->dm->getClassMetadata(get_class($embeddedDocument)); foreach ($class->fieldMappings as $mapping) { // Skip notSaved fields if (!empty($mapping['notSaved'])) { continue; } // Inline ClassMetadataInfo::getFieldValue() $rawValue = $class->reflFields[$mapping['fieldName']]->getValue($embeddedDocument); $value = null; if ($rawValue !== null) { switch (isset($mapping['association']) ? $mapping['association'] : null) { // @Field, @String, @Date, etc. case null: $value = Type::getType($mapping['type'])->convertToDatabaseValue($rawValue); break; case ClassMetadata::EMBED_ONE: case ClassMetadata::REFERENCE_ONE: // Nested collections should only be included for embedded relationships $value = $this->prepareAssociatedDocumentValue($mapping, $rawValue, $includeNestedCollections && isset($mapping['embedded'])); break; case ClassMetadata::EMBED_MANY: case ClassMetadata::REFERENCE_MANY: // Skip PersistentCollections already scheduled for deletion if (!$includeNestedCollections && $rawValue instanceof PersistentCollection && $this->uow->isCollectionScheduledForDeletion($rawValue)) { break; } // We're handling atomicSet or atomicSetArray collection if ($includeNestedCollections && $rawValue instanceof PersistentCollection) { $this->uow->unscheduleCollectionDeletion($rawValue); $this->uow->unscheduleCollectionUpdate($rawValue); } $pb = $this; $value = $rawValue->map(function ($v) use($pb, $mapping, $includeNestedCollections) { // Nested collections should only be included for embedded relationships return $pb->prepareAssociatedDocumentValue($mapping, $v, $includeNestedCollections && isset($mapping['embedded'])); })->toArray(); // Numerical reindexing may be necessary to ensure BSON array storage if (in_array($mapping['strategy'], array('atomicSetArray', 'setArray', 'pushAll', 'addToSet'))) { $value = array_values($value); } break; default: throw new \UnexpectedValueException('Unsupported mapping association: ' . $mapping['association']); } } // Omit non-nullable fields that would have a null value if ($value === null && $mapping['nullable'] === false) { continue; } $embeddedDocumentValue[$mapping['name']] = $value; } /* Add a discriminator value if the embedded document is not mapped * explicitly to a targetDocument class. */ if (!isset($embeddedMapping['targetDocument'])) { $discriminatorField = $embeddedMapping['discriminatorField']; $discriminatorValue = isset($embeddedMapping['discriminatorMap']) ? array_search($class->name, $embeddedMapping['discriminatorMap']) : $class->name; /* If the discriminator value was not found in the map, use the full * class name. In the future, it may be preferable to throw an * exception here (perhaps based on some strictness option). * * @see DocumentManager::createDBRef() */ if ($discriminatorValue === false) { $discriminatorValue = $class->name; } $embeddedDocumentValue[$discriminatorField] = $discriminatorValue; } /* If the class has a discriminator (field and value), use it. A child * class that is not defined in the discriminator map may only have a * discriminator field and no value, so default to the full class name. */ if (isset($class->discriminatorField)) { $embeddedDocumentValue[$class->discriminatorField] = isset($class->discriminatorValue) ? $class->discriminatorValue : $class->name; } // Ensure empty embedded documents are stored as BSON objects if (empty($embeddedDocumentValue)) { return (object) $embeddedDocumentValue; } /* @todo Consider always casting the return value to an object, or * building $embeddedDocumentValue as an object instead of an array, to * handle the edge case where all database field names are sequential, * numeric keys. */ return $embeddedDocumentValue; }
/** * Prepares the query criteria or new document object. * * PHP field names and types will be converted to those used by MongoDB. * * @param array $query * @return array */ public function prepareQueryOrNewObj(array $query) { $preparedQuery = array(); foreach ($query as $key => $value) { // Recursively prepare logical query clauses if (in_array($key, array('$and', '$or', '$nor')) && is_array($value)) { foreach ($value as $k2 => $v2) { $preparedQuery[$key][$k2] = $this->prepareQueryOrNewObj($v2); } continue; } if (isset($key[0]) && $key[0] === '$' && is_array($value)) { $preparedQuery[$key] = $this->prepareQueryOrNewObj($value); continue; } list($key, $value) = $this->prepareQueryElement($key, $value, null, true); $preparedQuery[$key] = is_array($value) ? array_map('\\Doctrine\\ODM\\MongoDB\\Types\\Type::convertPHPToDatabaseValue', $value) : Type::convertPHPToDatabaseValue($value); } return $preparedQuery; }
/** * Used to do the common work of computeChangeSet and recomputeSingleDocumentChangeSet * * @param \Doctrine\ODM\MongoDB\Mapping\ClassMetadata $class * @param object $document * @param boolean $recompute */ private function computeOrRecomputeChangeSet(ClassMetadata $class, $document, $recompute = false) { $oid = spl_object_hash($document); $actualData = $this->getDocumentActualData($document); $isNewDocument = !isset($this->originalDocumentData[$oid]); if ($isNewDocument) { // Document is either NEW or MANAGED but not yet fully persisted (only has an id). // These result in an INSERT. $this->originalDocumentData[$oid] = $actualData; $changeSet = array(); foreach ($actualData as $propName => $actualValue) { $changeSet[$propName] = array(null, $actualValue); } $this->documentChangeSets[$oid] = $changeSet; } else { // Document is "fully" MANAGED: it was already fully persisted before // and we have a copy of the original data $originalData = $this->originalDocumentData[$oid]; $isChangeTrackingNotify = $class->isChangeTrackingNotify(); if ($isChangeTrackingNotify && !$recompute) { $changeSet = $this->documentChangeSets[$oid]; } else { $changeSet = array(); } foreach ($actualData as $propName => $actualValue) { // skip not saved fields if (isset($class->fieldMappings[$propName]['notSaved']) && $class->fieldMappings[$propName]['notSaved'] === true) { continue; } $orgValue = isset($originalData[$propName]) ? $originalData[$propName] : null; // skip if value has not changed if ($orgValue === $actualValue) { // but consider dirty GridFSFile instances as changed if (!(isset($class->fieldMappings[$propName]['file']) && $actualValue->isDirty())) { continue; } } // if relationship is a embed-one, schedule orphan removal to trigger cascade remove operations if (isset($class->fieldMappings[$propName]['embedded']) && $class->fieldMappings[$propName]['type'] === 'one') { if ($orgValue !== null) { $this->scheduleOrphanRemoval($orgValue); } $changeSet[$propName] = array($orgValue, $actualValue); continue; } // if owning side of reference-one relationship if (isset($class->fieldMappings[$propName]['reference']) && $class->fieldMappings[$propName]['type'] === 'one' && $class->fieldMappings[$propName]['isOwningSide']) { if ($orgValue !== null && $class->fieldMappings[$propName]['orphanRemoval']) { $this->scheduleOrphanRemoval($orgValue); } $changeSet[$propName] = array($orgValue, $actualValue); continue; } if ($isChangeTrackingNotify) { continue; } // ignore inverse side of reference-many relationship if (isset($class->fieldMappings[$propName]['reference']) && $class->fieldMappings[$propName]['type'] === 'many' && $class->fieldMappings[$propName]['isInverseSide']) { continue; } // Persistent collection was exchanged with the "originally" // created one. This can only mean it was cloned and replaced // on another document. if ($actualValue instanceof PersistentCollection) { $owner = $actualValue->getOwner(); if ($owner === null) { // cloned $actualValue->setOwner($document, $class->fieldMappings[$propName]); } elseif ($owner !== $document) { // no clone, we have to fix if (!$actualValue->isInitialized()) { $actualValue->initialize(); // we have to do this otherwise the cols share state } $newValue = clone $actualValue; $newValue->setOwner($document, $class->fieldMappings[$propName]); $class->reflFields[$propName]->setValue($document, $newValue); } } // if embed-many or reference-many relationship if (isset($class->fieldMappings[$propName]['type']) && $class->fieldMappings[$propName]['type'] === 'many') { $changeSet[$propName] = array($orgValue, $actualValue); if ($orgValue instanceof PersistentCollection) { $this->scheduleCollectionDeletion($orgValue); } continue; } // skip equivalent date values if (isset($class->fieldMappings[$propName]['type']) && $class->fieldMappings[$propName]['type'] === 'date') { $dateType = Type::getType('date'); $dbOrgValue = $dateType->convertToDatabaseValue($orgValue); $dbActualValue = $dateType->convertToDatabaseValue($actualValue); if ($dbOrgValue instanceof \MongoDate && $dbActualValue instanceof \MongoDate && $dbOrgValue == $dbActualValue) { continue; } } // regular field $changeSet[$propName] = array($orgValue, $actualValue); } if ($changeSet) { $this->documentChangeSets[$oid] = $recompute && isset($this->documentChangeSets[$oid]) ? $changeSet + $this->documentChangeSets[$oid] : $changeSet; $this->originalDocumentData[$oid] = $actualData; $this->documentUpdates[$oid] = $document; } } // Look for changes in associations of the document foreach ($class->fieldMappings as $mapping) { // skip not saved fields if (isset($mapping['notSaved']) && $mapping['notSaved'] === true) { continue; } if (isset($mapping['reference']) || isset($mapping['embedded'])) { $value = $class->reflFields[$mapping['fieldName']]->getValue($document); if ($value !== null) { $this->computeAssociationChanges($document, $mapping, $value); if (isset($mapping['reference'])) { continue; } $values = $value; if (isset($mapping['type']) && $mapping['type'] === 'one') { $values = array($values); } elseif ($values instanceof PersistentCollection) { $values = $values->unwrap(); } foreach ($values as $obj) { $oid2 = spl_object_hash($obj); if (isset($this->documentChangeSets[$oid2])) { $this->documentChangeSets[$oid][$mapping['fieldName']] = array($value, $value); if (!$isNewDocument) { $this->documentUpdates[$oid] = $document; } break; } } } } } }