├── .gitignore ├── Tests ├── DependencyInjection │ ├── Fixtures │ │ ├── config │ │ │ └── yml │ │ │ │ └── client.yml │ │ └── Bundles │ │ │ └── YamlBundle │ │ │ ├── CouchDocument │ │ │ └── Test.php │ │ │ ├── Resources │ │ │ └── config │ │ │ │ └── doctrine │ │ │ │ └── Fixtures.Bundles.YamlBundle.CouchDocument.Test.couchdb.yml │ │ │ └── YamlBundle.php │ ├── XmlDoctrineExtensionTest.php │ ├── YamlDoctrineExtensionTest.php │ ├── AbstractDoctrineExtensionTest.php │ └── ConfigurationTest.php ├── bootstrap.php ├── TestCase.php ├── BundleTest.php └── ContainerTest.php ├── Form ├── DoctrineCouchDBExtension.php ├── ChoiceList │ └── CouchDBEntityLoader.php ├── Type │ └── DocumentType.php └── CouchDBTypeGuesser.php ├── Validator └── Constraints │ └── UniqueEntity.php ├── Mapping └── Driver │ ├── XmlDriver.php │ └── YamlDriver.php ├── composer.json ├── LICENSE ├── Resources ├── meta │ └── LICENSE ├── config │ ├── client.xml │ └── odm.xml └── views │ └── Collector │ └── couchdb.html.twig ├── phpunit.xml.dist ├── Command ├── MigrationCommand.php ├── CompactViewCommand.php ├── ViewCleanupCommand.php ├── ReplicationStartCommand.php ├── ReplicationCancelCommand.php ├── CompactDatabaseCommand.php ├── UpdateDesignDocCommand.php └── DoctrineCommandHelper.php ├── ManagerRegistry.php ├── CacheWarmer └── ProxyCacheWarmer.php ├── DataCollector └── CouchDBDataCollector.php ├── README.md ├── DependencyInjection ├── Compiler │ ├── RegisterEventListenersAndSubscribersPass.php │ └── DoctrineCouchDBMappingsPass.php ├── Configuration.php └── DoctrineCouchDBExtension.php └── DoctrineCouchDBBundle.php /.gitignore: -------------------------------------------------------------------------------- 1 | composer.lock 2 | vendor 3 | -------------------------------------------------------------------------------- /Tests/DependencyInjection/Fixtures/config/yml/client.yml: -------------------------------------------------------------------------------- 1 | doctrine_couchdb: 2 | client: 3 | dbname: foo -------------------------------------------------------------------------------- /Tests/DependencyInjection/Fixtures/Bundles/YamlBundle/CouchDocument/Test.php: -------------------------------------------------------------------------------- 1 | markTestSkipped('Doctrine Common is not available.'); 12 | } 13 | if (!class_exists('Doctrine\\CouchDB\\Version')) { 14 | $this->markTestSkipped('Doctrine CouchDB is not available.'); 15 | } 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /Tests/DependencyInjection/XmlDoctrineExtensionTest.php: -------------------------------------------------------------------------------- 1 | load($file.'.xml'); 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /Tests/DependencyInjection/YamlDoctrineExtensionTest.php: -------------------------------------------------------------------------------- 1 | load($file.'.yml'); 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /Form/DoctrineCouchDBExtension.php: -------------------------------------------------------------------------------- 1 | registry = $registry; 16 | } 17 | 18 | protected function loadTypes() 19 | { 20 | return array( 21 | new Type\DocumentType($this->registry), 22 | ); 23 | } 24 | 25 | protected function loadTypeGuesser() 26 | { 27 | return new CouchDBTypeGuesser($this->registry); 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /Validator/Constraints/UniqueEntity.php: -------------------------------------------------------------------------------- 1 | 7 | * 8 | * For the full copyright and license information, please view the LICENSE 9 | * file that was distributed with this source code. 10 | */ 11 | 12 | namespace Doctrine\Bundle\CouchDBBundle\Validator\Constraints; 13 | 14 | use Symfony\Bridge\Doctrine\Validator\Constraints\UniqueEntity as BaseConstraint; 15 | 16 | /** 17 | * Constraint for the Unique Entity validator 18 | * 19 | * @Annotation 20 | * @author Benjamin Eberlei 21 | */ 22 | class UniqueEntity extends BaseConstraint 23 | { 24 | public $service = 'doctrine_couchdb.odm.validator.unique'; 25 | } 26 | -------------------------------------------------------------------------------- /Mapping/Driver/XmlDriver.php: -------------------------------------------------------------------------------- 1 | 13 | * @author Benjamin Eberlei 14 | */ 15 | class XmlDriver extends BaseXmlDriver 16 | { 17 | const DEFAULT_FILE_EXTENSION = '.couchdb.xml'; 18 | 19 | /** 20 | * {@inheritdoc} 21 | */ 22 | public function __construct($prefixes, $fileExtension = self::DEFAULT_FILE_EXTENSION) 23 | { 24 | $locator = new SymfonyFileLocator((array) $prefixes, $fileExtension); 25 | parent::__construct($locator, $fileExtension); 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /Mapping/Driver/YamlDriver.php: -------------------------------------------------------------------------------- 1 | 13 | * @author Benjamin Eberlei 14 | */ 15 | class YamlDriver extends BaseYamlDriver 16 | { 17 | const DEFAULT_FILE_EXTENSION = '.couchdb.yml'; 18 | 19 | /** 20 | * {@inheritdoc} 21 | */ 22 | public function __construct($prefixes, $fileExtension = self::DEFAULT_FILE_EXTENSION) 23 | { 24 | $locator = new SymfonyFileLocator((array) $prefixes, $fileExtension); 25 | parent::__construct($locator, $fileExtension); 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /composer.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "doctrine/couchdb-odm-bundle", 3 | "type": "symfony-bundle", 4 | "description": "Symfony2 Doctrine CouchDB Bundle", 5 | "keywords": ["persistence", "couchdb", "symfony"], 6 | "homepage": "http://www.doctrine-project.org", 7 | "license": "LGPL", 8 | "authors": [ 9 | {"name": "Benjamin Eberlei", "email": "kontakt@beberlei.de"}, 10 | {"name": "Lukas Kahwe Smith", "email": "smith@pooteeweet.org"} 11 | ], 12 | "require": { 13 | "php": ">=5.3.2", 14 | "doctrine/couchdb-odm": "@dev", 15 | "doctrine/couchdb": "@dev", 16 | "symfony/doctrine-bridge": "~2.3|~3.0", 17 | "symfony/framework-bundle": "~2.3|~3.0" 18 | }, 19 | "require-dev": { 20 | }, 21 | "suggest": { 22 | }, 23 | "autoload": { 24 | "psr-0": { "Doctrine\\Bundle\\CouchDBBundle": "" } 25 | }, 26 | "target-dir": "Doctrine/Bundle/CouchDBBundle" 27 | } 28 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 2 | "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 3 | LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 4 | A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 5 | OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 6 | SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 7 | LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 8 | DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 9 | THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 10 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 11 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 12 | 13 | This software consists of voluntary contributions made by many individuals 14 | and is licensed under the LGPL. For more information, see 15 | . 16 | -------------------------------------------------------------------------------- /Resources/meta/LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2010-2012 Doctrine 2 | 3 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 4 | "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 5 | LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 6 | A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 7 | OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 8 | SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 9 | LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 10 | DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 11 | THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 12 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 13 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 14 | 15 | This software consists of voluntary contributions made by many individuals 16 | and is licensed under the LGPL. For more information, see 17 | . 18 | -------------------------------------------------------------------------------- /phpunit.xml.dist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 14 | 15 | 16 | ./Tests 17 | 18 | 19 | 20 | 21 | 22 | benchmark 23 | 24 | 25 | 26 | 27 | 28 | . 29 | 30 | ./Resources 31 | ./Tests 32 | 33 | 34 | 35 | 36 | -------------------------------------------------------------------------------- /Command/MigrationCommand.php: -------------------------------------------------------------------------------- 1 | setName('doctrine:couchdb:migrate') 20 | ->addOption('conn', null, InputOption::VALUE_OPTIONAL, 'The connection to use for this command'); 21 | } 22 | 23 | protected function execute(InputInterface $input, OutputInterface $output) 24 | { 25 | DoctrineCommandHelper::setApplicationCouchDBClient($this->getApplication(), $input->getOption('conn') ?: 'default'); 26 | 27 | return parent::execute($input, $output); 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /Command/CompactViewCommand.php: -------------------------------------------------------------------------------- 1 | setName('doctrine:couchdb:maintenance:compact-view') 19 | ->addOption('conn', null, InputOption::VALUE_OPTIONAL, 'The connection to use for this command'); 20 | } 21 | 22 | protected function execute(InputInterface $input, OutputInterface $output) 23 | { 24 | DoctrineCommandHelper::setApplicationCouchDBClient($this->getApplication(), $input->getOption('conn') ?: 'default'); 25 | 26 | return parent::execute($input, $output); 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /Command/ViewCleanupCommand.php: -------------------------------------------------------------------------------- 1 | setName('doctrine:couchdb:maintenance:view-cleanup') 19 | ->addOption('conn', null, InputOption::VALUE_OPTIONAL, 'The connection to use for this command'); 20 | } 21 | 22 | protected function execute(InputInterface $input, OutputInterface $output) 23 | { 24 | DoctrineCommandHelper::setApplicationCouchDBClient($this->getApplication(), $input->getOption('conn') ?: 'default'); 25 | 26 | return parent::execute($input, $output); 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /Command/ReplicationStartCommand.php: -------------------------------------------------------------------------------- 1 | setName('doctrine:couchdb:replication:start') 19 | ->addOption('conn', null, InputOption::VALUE_OPTIONAL, 'The connection to use for this command'); 20 | } 21 | 22 | protected function execute(InputInterface $input, OutputInterface $output) 23 | { 24 | DoctrineCommandHelper::setApplicationCouchDBClient($this->getApplication(), $input->getOption('conn') ?: 'default'); 25 | 26 | return parent::execute($input, $output); 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /Command/ReplicationCancelCommand.php: -------------------------------------------------------------------------------- 1 | setName('doctrine:couchdb:replication:cancel') 19 | ->addOption('conn', null, InputOption::VALUE_OPTIONAL, 'The connection to use for this command'); 20 | } 21 | 22 | protected function execute(InputInterface $input, OutputInterface $output) 23 | { 24 | DoctrineCommandHelper::setApplicationCouchDBClient($this->getApplication(), $input->getOption('conn') ?: 'default'); 25 | 26 | return parent::execute($input, $output); 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /Command/CompactDatabaseCommand.php: -------------------------------------------------------------------------------- 1 | setName('doctrine:couchdb:maintenance:compact-database') 19 | ->addOption('conn', null, InputOption::VALUE_OPTIONAL, 'The connection to use for this command'); 20 | 21 | } 22 | 23 | protected function execute(InputInterface $input, OutputInterface $output) 24 | { 25 | DoctrineCommandHelper::setApplicationCouchDBClient($this->getApplication(), $input->getOption('conn') ?: 'default'); 26 | 27 | return parent::execute($input, $output); 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /Command/UpdateDesignDocCommand.php: -------------------------------------------------------------------------------- 1 | setName('doctrine:couchdb:update-design-doc') 20 | ->addOption('dm', null, InputOption::VALUE_OPTIONAL, 'The document manager to use for this command', 'default'); 21 | } 22 | 23 | protected function execute(InputInterface $input, OutputInterface $output) 24 | { 25 | DoctrineCommandHelper::setApplicationDocumentManager($this->getApplication(), $input->getOption('dm') ?: 'default'); 26 | 27 | return parent::execute($input, $output); 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /Command/DoctrineCommandHelper.php: -------------------------------------------------------------------------------- 1 | 13 | */ 14 | abstract class DoctrineCommandHelper 15 | { 16 | static public function setApplicationCouchDBClient(Application $application, $connName) 17 | { 18 | $couchClient = $application->getKernel()->getContainer()->get('doctrine_couchdb.client.'.$connName.'_connection'); 19 | $helperSet = $application->getHelperSet(); 20 | $helperSet->set(new CouchDBHelper($couchClient)); 21 | } 22 | 23 | static public function setApplicationDocumentManager(Application $application, $dmName) 24 | { 25 | $documentManager = $application->getKernel()->getContainer()->get('doctrine_couchdb.odm.'.$dmName.'_document_manager'); 26 | $helperSet = $application->getHelperSet(); 27 | $helperSet->set(new CouchDBHelper(null, $documentManager)); 28 | } 29 | } -------------------------------------------------------------------------------- /ManagerRegistry.php: -------------------------------------------------------------------------------- 1 | getManagers()) as $name) { 32 | try { 33 | return $this->getManager($name)->getConfiguration()->getDocumentNamespace($alias); 34 | } catch (CouchDBException $e) { 35 | } 36 | } 37 | 38 | throw CouchDBException::unknownDocumentNamespace($alias); 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /Tests/BundleTest.php: -------------------------------------------------------------------------------- 1 | getMock('Symfony\Component\DependencyInjection\ContainerBuilder', array('hasExtension', 'addCompilerPass')); 15 | $builder->expects($this->at(0))->method('hasExtension')->will($this->returnValue(false)); 16 | 17 | $builder->expects($this->at(1)) 18 | ->method('addCompilerPass') 19 | ->with( 20 | $this->isInstanceOf('Doctrine\Bundle\CouchDBBundle\DependencyInjection\Compiler\RegisterEventListenersAndSubscribersPass'), 21 | $this->equalTo(PassConfig::TYPE_BEFORE_OPTIMIZATION) 22 | ); 23 | $builder->expects($this->at(2)) 24 | ->method('addCompilerPass') 25 | ->with( 26 | $this->isInstanceOf('Symfony\Bridge\Doctrine\DependencyInjection\CompilerPass\DoctrineValidationPass'), 27 | $this->equalTo(PassConfig::TYPE_BEFORE_OPTIMIZATION) 28 | ); 29 | 30 | $bundle->build($builder); 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /Form/ChoiceList/CouchDBEntityLoader.php: -------------------------------------------------------------------------------- 1 | 12 | */ 13 | class CouchDBEntityLoader implements EntityLoaderInterface 14 | { 15 | 16 | /** 17 | * @var string 18 | */ 19 | private $class; 20 | 21 | /** 22 | * @var ObjectManager 23 | */ 24 | private $dm; 25 | 26 | public function __construct(ObjectManager $dm, $class) 27 | { 28 | $this->dm = $dm; 29 | $this->class = $class; 30 | } 31 | 32 | 33 | /** 34 | * {@inheritDoc} 35 | */ 36 | public function getEntities() 37 | { 38 | return $this->dm->getRepository($this->class)->findAll(); 39 | } 40 | 41 | /** 42 | * {@inheritDoc} 43 | */ 44 | public function getEntitiesByIds($identifier, array $values) 45 | { 46 | $or = $this->dm->getRepository($this->class); 47 | if (!($or instanceof DocumentRepository)) { 48 | throw new UnexpectedTypeException($this->dm, 'Doctrine\ODM\CouchDB\DocumentRepository'); 49 | } 50 | 51 | return $or->findMany($values); 52 | } 53 | } -------------------------------------------------------------------------------- /Form/Type/DocumentType.php: -------------------------------------------------------------------------------- 1 | container = $container; 20 | } 21 | 22 | /** 23 | * This cache warmer is not optional, without proxies fatal error occurs! 24 | * 25 | * @return false 26 | */ 27 | public function isOptional() 28 | { 29 | return false; 30 | } 31 | 32 | public function warmUp($cacheDir) 33 | { 34 | foreach ($this->container->getParameter('doctrine_couchdb.document_managers') as $dmName) { 35 | $dm = $this->container->get($dmName); 36 | 37 | // we need the directory no matter the proxy cache generation strategy 38 | if (!file_exists($proxyCacheDir = $dm->getConfiguration()->getProxyDir())) { 39 | if (false === @mkdir($proxyCacheDir, 0777, true)) { 40 | throw new \RuntimeException(sprintf('Unable to create the Doctrine CouchDB Proxy directory "%s".', dirname($proxyCacheDir))); 41 | } 42 | } elseif (!is_writable($proxyCacheDir)) { 43 | throw new \RuntimeException(sprintf('The Doctrine CouchDB Proxy directory "%s" is not writeable for the current system user.', $proxyCacheDir)); 44 | } 45 | 46 | // if proxies are autogenerated we don't need to generate them in the cache warmer 47 | /*if ($dm->getConfiguration()->getAutoGenerateProxyClasses()) { 48 | continue; 49 | } 50 | 51 | $classes = $dm->getMetadataFactory()->getAllMetadata(); 52 | $dm->getProxyFactory()->generateProxyClasses($classes);*/ 53 | } 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /DataCollector/CouchDBDataCollector.php: -------------------------------------------------------------------------------- 1 | clients[$name] = $client; 28 | } 29 | 30 | public function collect(Request $request, Response $response, \Exception $exception = null) 31 | { 32 | $this->data = array('duration' => array(), 'requests' => array(), 'requestcount' => 0, 'total_duration' => 0); 33 | foreach ($this->clients AS $name => $client) { 34 | $this->data['duration'][$name] = $client->totalDuration; 35 | $this->data['requests'][$name] = $client->requests; 36 | $this->data['requestcount'] += count($client->requests); 37 | $this->data['total_duration'] += $client->totalDuration; 38 | } 39 | } 40 | 41 | public function getDuration() 42 | { 43 | return $this->data['duration']; 44 | } 45 | 46 | public function getRequests() 47 | { 48 | return $this->data['requests']; 49 | } 50 | 51 | public function getRequestCount() 52 | { 53 | return $this->data['requestcount']; 54 | } 55 | 56 | public function getTotalDuration() 57 | { 58 | return $this->data['total_duration']; 59 | } 60 | 61 | public function getName() 62 | { 63 | return 'couchdb'; 64 | } 65 | } -------------------------------------------------------------------------------- /Resources/config/client.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 6 | 7 | 8 | 9 | Doctrine\CouchDB\CouchDBClient 10 | Doctrine\Bundle\CouchDBBundle\DataCollector\CouchDBDataCollector 11 | Doctrine\Bundle\CouchDBBundle\ManagerRegistry 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | CouchDB 30 | %doctrine_couchdb.connections% 31 | %doctrine_couchdb.document_managers% 32 | %doctrine_couchdb.default_connection% 33 | %doctrine_couchdb.default_document_manager% 34 | Doctrine\ODM\CouchDB\Proxy\Proxy 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Doctrine CouchDB Bundle 2 | 3 | This bundle integrates Doctrine CouchDB ODM and Clients into Symfony2. 4 | 5 | STABILITY: Alpha 6 | 7 | ## Installation 8 | 9 | * ``composer require doctrine/couchdb-odm-bundle`` 10 | * Add `Doctrine\Bundle\CouchDBBundle\DoctrineCouchDBBundle` to your Kernel#registerBundles() method 11 | * If you do not use composer, do not forget to add autoloader for the Doctrine\CouchDB, 12 | Doctrine\ODM\CouchDB and Doctrine\Bundle namespaces 13 | 14 | To use the annotations, register them in your app/autoload.php file: 15 | 16 | use Doctrine\Common\Annotations\AnnotationRegistry; 17 | AnnotationRegistry::registerLoader(array($loader, 'loadClass')); 18 | 19 | ## Documentation 20 | 21 | See the [Doctrine CouchDB ODM](http://docs.doctrine-project.org/projects/doctrine-couchdb/en/latest/index.html) documentation for more information. 22 | 23 | ## Configuration 24 | 25 | The configuration is similar to Doctrine ORM and MongoDB configuration for Symfony2 as its based 26 | on the AbstractDoctrineBundle aswell: 27 | 28 | doctrine_couch_db: 29 | client: 30 | dbname: symfony 31 | odm: 32 | auto_mapping: true 33 | 34 | To dump the configuration reference of this bundle 35 | 36 | php app/console config:dump-reference doctrine_couch_db 37 | 38 | ## Annotations 39 | 40 | An example of how to use annotations with CouchDB and Symfony: 41 | 42 | container->get('doctrine_couchdb.client.default_connection'); 71 | $documentManager = $this->container->get('doctrine_couchdb.odm.default_document_manager'); 72 | } 73 | } 74 | 75 | ## View directories 76 | 77 | In `@YourBundle/Resources/couchdb/` you can add design documents and corresponding views and have Doctrine 78 | CouchDB register them up automatically. For example if you had a design doc "foo" and a view "bar" you could 79 | add the following files and directories: 80 | 81 | Resources/couchdb/ 82 | └── foo/ 83 | └── views/ 84 | └── bar/ 85 | ├── map.js 86 | └── reduce.js 87 | 88 | You can then update this design document from the CLI by calling: 89 | 90 | ./app/console doctrine:couchdb:update-design-doc foo 91 | 92 | Where `foo` is the name of the design document. 93 | -------------------------------------------------------------------------------- /Form/CouchDBTypeGuesser.php: -------------------------------------------------------------------------------- 1 | 16 | */ 17 | class CouchDBTypeGuesser implements FormTypeGuesserInterface 18 | { 19 | /** 20 | * @var ManagerRegistry 21 | */ 22 | private $registry; 23 | 24 | private $cache = array(); 25 | 26 | public function __construct(ManagerRegistry $registry) 27 | { 28 | $this->registry = $registry; 29 | } 30 | 31 | public function guessType($class, $property) 32 | { 33 | if (!$ret = $this->getMetadata($class)) { 34 | return new TypeGuess('text', array(), Guess::LOW_CONFIDENCE); 35 | } 36 | 37 | list($metadata, $documentManager) = $ret; 38 | 39 | if ($metadata->hasAssociation($property)) { 40 | $multiple = $metadata->isCollectionValuedAssociation($property); 41 | $mapping = $metadata->getAssociationMapping($property); 42 | 43 | return new TypeGuess('couchdb_document', array( 44 | 'dm' => $documentManager, 45 | 'class' => $mapping['targetDocument'], 46 | 'multiple' => $multiple 47 | ), 48 | Guess::HIGH_CONFIDENCE 49 | ); 50 | } 51 | 52 | switch ($metadata->getTypeOfField($property)) { 53 | case 'boolean': 54 | return new TypeGuess('checkbox', array(), Guess::HIGH_CONFIDENCE); 55 | case 'datetime': 56 | return new TypeGuess('datetime', array(), Guess::HIGH_CONFIDENCE); 57 | case 'integer': 58 | return new TypeGuess('integer', array(), Guess::MEDIUM_CONFIDENCE); 59 | case 'string': 60 | return new TypeGuess('text', array(), Guess::MEDIUM_CONFIDENCE); 61 | default: 62 | return new TypeGuess('text', array(), Guess::LOW_CONFIDENCE); 63 | } 64 | } 65 | 66 | /** 67 | * {@inheritDoc} 68 | */ 69 | public function guessMaxLength($class, $property) 70 | { 71 | } 72 | 73 | /** 74 | * {@inheritDoc} 75 | */ 76 | public function guessMinLength($class, $property) 77 | { 78 | } 79 | 80 | /** 81 | * {@inheritDoc} 82 | */ 83 | public function guessRequired($class, $property) 84 | { 85 | } 86 | 87 | /** 88 | * {@inheritDoc} 89 | */ 90 | public function guessPattern($class, $property) 91 | { 92 | } 93 | 94 | protected function getMetadata($class) 95 | { 96 | if (array_key_exists($class, $this->cache)) { 97 | return $this->cache[$class]; 98 | } 99 | 100 | $manager = $this->registry->getManagerForClass($class); 101 | if ($manager) { 102 | return $this->cache[$class] = array($manager->getClassMetadata($class), $manager); 103 | } 104 | return $this->cache[$class] = null; 105 | } 106 | } -------------------------------------------------------------------------------- /DependencyInjection/Compiler/RegisterEventListenersAndSubscribersPass.php: -------------------------------------------------------------------------------- 1 | hasParameter('doctrine_couchdb.default_connection')) { 20 | return; 21 | } 22 | 23 | $this->container = $container; 24 | $this->documentManagers = $container->getParameter('doctrine_couchdb.document_managers'); 25 | 26 | foreach ($container->findTaggedServiceIds('doctrine_couchdb.event_subscriber') as $subscriberId => $instances) { 27 | $this->registerSubscriber($subscriberId, $instances); 28 | } 29 | 30 | foreach ($container->findTaggedServiceIds('doctrine_couchdb.event_listener') as $listenerId => $instances) { 31 | $this->registerListener($listenerId, $instances); 32 | } 33 | } 34 | 35 | protected function registerSubscriber($subscriberId, $instances) 36 | { 37 | $connections = array(); 38 | foreach ($instances as $attributes) { 39 | if (isset($attributes['document_manager'])) { 40 | $connections[] = $attributes['document_manager']; 41 | } else { 42 | $connections = array_keys($this->documentManagers); 43 | break; 44 | } 45 | } 46 | 47 | foreach ($connections as $name) { 48 | $this->getEventManager($name, $subscriberId)->addMethodCall('addEventSubscriber', array(new Reference($subscriberId))); 49 | } 50 | } 51 | 52 | protected function registerListener($listenerId, $instances) 53 | { 54 | $connections = array(); 55 | foreach ($instances as $attributes) { 56 | if (!isset($attributes['event'])) { 57 | throw new \InvalidArgumentException(sprintf('Doctrine event listener "%s" must specify the "event" attribute.', $listenerId)); 58 | } 59 | 60 | if (isset($attributes['document_manager'])) { 61 | $cs = array($attributes['document_manager']); 62 | } else { 63 | $cs = array_keys($this->documentManagers); 64 | } 65 | 66 | foreach ($cs as $connection) { 67 | if (!isset($connections[$connection]) || !is_array($connections[$connection])) { 68 | $connections[$connection] = array(); 69 | } 70 | $connections[$connection][] = $attributes['event']; 71 | } 72 | } 73 | 74 | foreach ($connections as $name => $events) { 75 | $this->getEventManager($name, $listenerId)->addMethodCall('addEventListener', array( 76 | array_unique($events), 77 | new Reference($listenerId), 78 | )); 79 | } 80 | } 81 | 82 | private function getEventManager($name, $listenerId = null) 83 | { 84 | if (null === $this->eventManagers) { 85 | $this->eventManagers = array(); 86 | foreach ($this->documentManagers as $n => $id) { 87 | $arguments = $this->container->getDefinition($id)->getArguments(); 88 | $this->eventManagers[$n] = $this->container->getDefinition((string) $arguments[2]); 89 | } 90 | } 91 | 92 | if (!isset($this->eventManagers[$name])) { 93 | throw new \InvalidArgumentException(sprintf('Doctrine connection "%s" does not exist but is referenced in the "%s" event listener.', $name, $listenerId)); 94 | } 95 | 96 | return $this->eventManagers[$name]; 97 | } 98 | } 99 | -------------------------------------------------------------------------------- /Tests/ContainerTest.php: -------------------------------------------------------------------------------- 1 | createYamlBundleTestContainer(); 22 | $this->assertInstanceOf('Doctrine\CouchDB\CouchDBClient', $container->get('doctrine_couchdb.client.default_connection')); 23 | $this->assertInstanceOf('Doctrine\ODM\CouchDB\DocumentManager', $container->get('doctrine_couchdb.odm.test_document_manager')); 24 | } 25 | 26 | public function testDesignDocuments() 27 | { 28 | $container = $this->createYamlBundleTestContainer(); 29 | $dm = $container->get('doctrine_couchdb.odm.test_document_manager'); 30 | $config = $dm->getConfiguration(); 31 | 32 | $this->assertNotNull($config->getDesignDocument('mydoc')); 33 | 34 | } 35 | 36 | public function testAllOrNothingFlush() 37 | { 38 | $container = $this->createYamlBundleTestContainer(); 39 | $dm = $container->get('doctrine_couchdb.odm.test_document_manager'); 40 | 41 | $config = $dm->getConfiguration(); 42 | 43 | $this->assertFalse($config->getAllOrNothingFlush()); 44 | 45 | } 46 | 47 | public function createYamlBundleTestContainer() 48 | { 49 | $container = new ContainerBuilder(new ParameterBag(array( 50 | 'kernel.debug' => false, 51 | 'kernel.bundles' => array('YamlBundle' => 'Fixtures\Bundles\YamlBundle\YamlBundle'), 52 | 'kernel.cache_dir' => sys_get_temp_dir(), 53 | 'kernel.root_dir' => __DIR__ . "/../../../../" // src dir 54 | ))); 55 | 56 | require_once __DIR__.'/DependencyInjection/Fixtures/Bundles/YamlBundle/YamlBundle.php'; 57 | 58 | $container->set('annotation_reader', new AnnotationReader()); 59 | $loader = new DoctrineCouchDBExtension(); 60 | $container->registerExtension($loader); 61 | $loader->load(array( 62 | array( 63 | 'client' => array('dbname' => 'testdb'), 64 | 'odm' => array( 65 | 'default_document_manager' => 'test', 66 | 'document_managers' => array( 67 | 'test' => array( 68 | 'connection' => 'default', 69 | 'mappings' => array( 70 | 'YamlBundle' => array( 71 | 'type' => 'yml', 72 | 'dir' => __DIR__ . "/DependencyInjection/Fixtures/Bundles/YamlBundle/Resources/config/doctrine", 73 | 'prefix' => 'Fixtures\Bundles\YamlBundle\CouchDocument', 74 | ) 75 | ), 76 | 'all_or_nothing_flush' => false, 77 | 'design_documents' => array( 78 | 'mydoc' => array( 79 | 'className' => 'Doctrine\CouchDB\View\FolderDesignDocument', 80 | 'options' => array('test'), 81 | ) 82 | ) 83 | ) 84 | ) 85 | ) 86 | ) 87 | ), $container); 88 | 89 | $container->getCompilerPassConfig()->setOptimizationPasses(array(new ResolveDefinitionTemplatesPass())); 90 | $container->getCompilerPassConfig()->setRemovingPasses(array()); 91 | $container->compile(); 92 | 93 | return $container; 94 | } 95 | } 96 | -------------------------------------------------------------------------------- /DoctrineCouchDBBundle.php: -------------------------------------------------------------------------------- 1 | hasExtension('security')) { 37 | $container->getExtension('security')->addUserProviderFactory(new EntityFactory('couchdb', 'doctrine_couchdb.odm.security.user.provider')); 38 | } 39 | 40 | $container->addCompilerPass(new RegisterEventListenersAndSubscribersPass(), PassConfig::TYPE_BEFORE_OPTIMIZATION); 41 | $container->addCompilerPass(new DoctrineValidationPass('couchdb')); 42 | } 43 | 44 | public function boot() 45 | { 46 | // force Doctrine annotations to be loaded 47 | // should be removed when a better solution is found in Doctrine 48 | class_exists('Doctrine\ODM\CouchDB\Mapping\Driver\AnnotationDriver'); 49 | 50 | // Register an autoloader for proxies to avoid issues when unserializing them 51 | // when the ORM is used. 52 | if ($this->container->hasParameter('doctrine_couchdb.odm.proxy_namespace')) { 53 | $namespace = $this->container->getParameter('doctrine_couchdb.odm.proxy_namespace'); 54 | $dir = $this->container->getParameter('doctrine_couchdb.odm.proxy_dir'); 55 | $container = $this->container; 56 | 57 | $this->autoloader = function($class) use ($namespace, $dir, $container) { 58 | if (0 === strpos($class, $namespace)) { 59 | $className = substr($class, strlen($namespace) +1); 60 | $file = $dir.DIRECTORY_SEPARATOR . str_replace('\\', '', $className) . '.php'; 61 | 62 | if (!is_file($file) && $container->getParameter('doctrine_couchdb.odm.auto_generate_proxy_classes')) { 63 | $originalClassName = substr($className, 7); 64 | $registry = $container->get('doctrine_couchdb'); 65 | 66 | // Tries to auto-generate the proxy file 67 | foreach ($registry->getManagers() as $manager) { 68 | 69 | if ($manager->getConfiguration()->getAutoGenerateProxyClasses()) { 70 | $classes = $manager->getMetadataFactory()->getAllMetadata(); 71 | 72 | foreach ($classes as $class) { 73 | if ($class->name == $originalClassName) { 74 | $manager->getProxyFactory()->generateProxyClasses(array($class)); 75 | } 76 | } 77 | } 78 | } 79 | 80 | clearstatcache($file); 81 | 82 | if (!is_file($file)) { 83 | throw new \RuntimeException(sprintf('The proxy file "%s" does not exist. If you still have objects serialized in the session, you need to clear the session manually.', $file)); 84 | } 85 | } 86 | 87 | require $file; 88 | } 89 | }; 90 | spl_autoload_register($this->autoloader); 91 | } 92 | } 93 | 94 | public function shutdown() 95 | { 96 | spl_autoload_unregister($this->autoloader); 97 | } 98 | } 99 | -------------------------------------------------------------------------------- /Tests/DependencyInjection/AbstractDoctrineExtensionTest.php: -------------------------------------------------------------------------------- 1 | getContainer(); 23 | $loader = new DoctrineCouchDBExtension(); 24 | 25 | $loader->load(array(array(), array('client' => array('default_connection' => 'foo')), array()), $container); 26 | 27 | $this->assertEquals('foo', $container->getParameter('doctrine_couchdb.default_connection'), '->load() overrides existing configuration options'); 28 | $this->assertTrue($container->has('doctrine_couchdb.client.foo_connection')); 29 | } 30 | 31 | public function testClients() 32 | { 33 | $container = $this->getContainer(); 34 | $loader = new DoctrineCouchDBExtension(); 35 | 36 | $loader->load(array( 37 | array( 38 | 'client' => array('default_connection' => 'test', 'connections' => array( 39 | 'test' => array('port' => 4000), 40 | 'test2' => array('port' => 1984), 41 | )), 42 | ) 43 | ), $container); 44 | 45 | $this->assertTrue($container->has('doctrine_couchdb.client.test_connection')); 46 | $this->assertTrue($container->has('doctrine_couchdb.client.test2_connection')); 47 | } 48 | 49 | public function testDocumentManagers() 50 | { 51 | $container = $this->getContainer(); 52 | $loader = new DoctrineCouchDBExtension(); 53 | 54 | $loader->load(array( 55 | array( 56 | 'client' => array(), 57 | 'odm' => array( 58 | 'default_document_manager' => 'test', 59 | 'document_managers' => array( 60 | 'test' => array('connection' => 'default'), 61 | 'test2' => array('metadata_cache_driver' => array('type' => 'apc')) 62 | ) 63 | ) 64 | ) 65 | ), $container); 66 | 67 | $this->assertTrue($container->has('doctrine_couchdb.odm.test_document_manager')); 68 | $this->assertTrue($container->has('doctrine_couchdb.odm.test2_document_manager')); 69 | } 70 | 71 | public function testMappings() 72 | { 73 | $container = $this->getContainer(); 74 | $loader = new DoctrineCouchDBExtension(); 75 | 76 | $loader->load(array( 77 | array( 78 | 'client' => array(), 79 | 'odm' => array( 80 | 'default_document_manager' => 'test', 81 | 'document_managers' => array( 82 | 'test' => array('connection' => 'default', 'mappings' => array('YamlBundle' => array())) 83 | ) 84 | ) 85 | ) 86 | ), $container); 87 | 88 | $this->assertTrue($container->has('doctrine_couchdb.odm.test_metadata_driver')); 89 | 90 | $methodCalls = $container->getDefinition('doctrine_couchdb.odm.test_metadata_driver')->getMethodCalls(); 91 | $this->assertArrayHasKey(0, $methodCalls, "No method calls to define metadata driver found."); 92 | $this->assertEquals('addDriver', $methodCalls[0][0]); 93 | $this->assertEquals('Fixtures\Bundles\YamlBundle\CouchDocument', $methodCalls[0][1][1]); 94 | $this->assertEquals(new Reference('doctrine_couchdb.odm.test_yml_metadata_driver'), $methodCalls[0][1][0]); 95 | } 96 | 97 | protected function getContainer($bundles = 'YamlBundle', $vendor = null) 98 | { 99 | $bundles = (array) $bundles; 100 | 101 | $map = array(); 102 | foreach ($bundles as $bundle) { 103 | require_once __DIR__.'/Fixtures/Bundles/'.($vendor ? $vendor.'/' : '').$bundle.'/'.$bundle.'.php'; 104 | 105 | $map[$bundle] = 'Fixtures\\Bundles\\'.($vendor ? $vendor.'\\' : '').$bundle.'\\'.$bundle; 106 | } 107 | 108 | return new ContainerBuilder(new ParameterBag(array( 109 | 'kernel.debug' => false, 110 | 'kernel.bundles' => $map, 111 | 'kernel.cache_dir' => sys_get_temp_dir(), 112 | 'kernel.root_dir' => __DIR__ . "/../../../../../" // src dir 113 | ))); 114 | } 115 | } 116 | -------------------------------------------------------------------------------- /Resources/views/Collector/couchdb.html.twig: -------------------------------------------------------------------------------- 1 | {% extends 'WebProfilerBundle:Profiler:layout.html.twig' %} 2 | 3 | {% block toolbar %} 4 | {% set icon %} 5 | CouchDB 6 | {% endset %} 7 | {% set text %} 8 | {{ collector.requestCount }} 9 | {% endset %} 10 | {% include 'WebProfilerBundle:Profiler:toolbar_item.html.twig' with { 'link': profiler_url } %} 11 | {% endblock %} 12 | 13 | {% block menu %} 14 | 15 | 16 | Doctrine CouchDB 17 | 18 | {{ collector.requestCount }} 19 | {{ '%0.0f'|format(collector.totalDuration * 1000) }} ms 20 | 21 | 22 | {% endblock %} 23 | 24 | {% block panel %} 25 |

CouchDB HTTP Requests

26 | 27 | {% if not collector.requestCount %} 28 |

29 | No http requests to a CouchDB. 30 |

31 | {% else %} 32 | {% for conn,requests in collector.requests %} 33 |

Database {{ conn }}

34 | 35 |
    36 | {% for i, request in requests %} 37 |
  • 38 |
    {{ request.method }} {{ request.path }}
    39 | 40 | Status: {{ request.response_status }}
    41 | Duration: {{ '%0.2f'|format(request.duration * 1000) }} ms
    42 | Request-Size: {{ request.request_size }} 43 |
    44 |
    Request-Body
    {% if request.request is not empty %}
    {{ request.request|json_encode }}
    {% else %}Empty{% endif %}
    45 |
    Response-Body
    {{ request.response|json_encode }}
    46 |
  • 47 | {% endfor %} 48 |
49 | {% endfor %} 50 | {% endif %} 51 | 52 | {% endblock %} -------------------------------------------------------------------------------- /Resources/config/odm.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 6 | 7 | 8 | 9 | Doctrine\ODM\CouchDB\Configuration 10 | Doctrine\ODM\CouchDB\DocumentManager 11 | Doctrine\Common\EventManager 12 | 13 | 14 | Doctrine\Common\Cache\ArrayCache 15 | Doctrine\Common\Cache\ApcCache 16 | Doctrine\Common\Cache\MemcacheCache 17 | localhost 18 | 11211 19 | Memcache 20 | Doctrine\Common\Cache\XcacheCache 21 | Doctrine\Bundle\CouchDBBundle\CacheWarmer\ProxyCacheWarmer 22 | 23 | 24 | Symfony\Bridge\Doctrine\Security\User\EntityUserProvider 25 | 26 | 27 | Doctrine\Bundle\CouchDBBundle\Form\CouchDBTypeGuesser 28 | 29 | Doctrine\Common\Persistence\Mapping\Driver\MappingDriverChain 30 | Doctrine\ODM\CouchDB\Mapping\Driver\AnnotationDriver 31 | Doctrine\Common\Annotations\AnnotationReader 32 | Doctrine\Bundle\CouchDBBundle\Mapping\Driver\XmlDriver 33 | Doctrine\Bundle\CouchDBBundle\Mapping\Driver\YamlDriver 34 | Doctrine\ODM\CouchDB\Mapping\Driver\PHPDriver 35 | 36 | 37 | Symfony\Bridge\Doctrine\Validator\Constraints\UniqueEntityValidator 38 | Symfony\Bridge\Doctrine\Validator\DoctrineInitializer 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 55 | 56 | 58 | 59 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | -------------------------------------------------------------------------------- /Tests/DependencyInjection/ConfigurationTest.php: -------------------------------------------------------------------------------- 1 | config = new Configuration(false); 17 | $this->processor = new Processor(); 18 | } 19 | 20 | public function testEmptyConfig() 21 | { 22 | $this->setExpectedException('Symfony\Component\Config\Definition\Exception\InvalidConfigurationException', 23 | 'The child node "client" at path "doctrine_couch_db" must be configured.'); 24 | $config = $this->processor->processConfiguration($this->config, array()); 25 | } 26 | 27 | public function testEmptyClientLeadsToDefaultConnection() 28 | { 29 | $config = $this->processor->processConfiguration($this->config, array(array('client' => null))); 30 | 31 | $this->assertEquals(array( 32 | 'client' => array('default_connection' => 'default', 'connections' => array( 33 | 'default' => array('host' => 'localhost', 'port' => 5984, 'user' => null, 'password' => null, 'ip' => null, 'logging' => false, 'url' => null, 'ssl' => false) 34 | )) 35 | ), $config); 36 | } 37 | 38 | public function testSingleTopLevelClientConnectionDefinition() 39 | { 40 | $config = $this->processor->processConfiguration($this->config, array( 41 | array( 42 | 'client' => array(), 43 | ) 44 | )); 45 | 46 | $this->assertEquals(array( 47 | 'client' => array('default_connection' => 'default', 'connections' => array( 48 | 'default' => array('host' => 'localhost', 'port' => 5984, 'user' => null, 'password' => null, 'ip' => null, 'logging' => false, 'url' => null, 'ssl' => false) 49 | )) 50 | ), $config); 51 | } 52 | 53 | public function testSingleTopLevelClientRenamedConnectionDefinition() 54 | { 55 | $config = $this->processor->processConfiguration($this->config, array( 56 | array( 57 | 'client' => array('default_connection' => 'test'), 58 | ) 59 | )); 60 | 61 | $this->assertEquals(array( 62 | 'client' => array('default_connection' => 'test', 'connections' => array( 63 | 'test' => array('host' => 'localhost', 'port' => 5984, 'user' => null, 'password' => null, 'ip' => null, 'logging' => false, 'url' => null, 'ssl' => false) 64 | )) 65 | ), $config); 66 | } 67 | 68 | public function testMultipleClientConnections() 69 | { 70 | $config = $this->processor->processConfiguration($this->config, array( 71 | array( 72 | 'client' => array('default_connection' => 'test', 'connections' => array( 73 | 'test' => array('port' => 4000), 74 | 'test2' => array('port' => 1984), 75 | )), 76 | ) 77 | )); 78 | 79 | $this->assertEquals(array( 80 | 'client' => array('default_connection' => 'test', 'connections' => array( 81 | 'test' => array('port' => 4000, 'host' => 'localhost', 'user' => null, 'password' => null, 'ip' => null, 'logging' => false, 'url' => null, 'ssl' => false), 82 | 'test2' => array('port' => 1984, 'host' => 'localhost', 'user' => null, 'password' => null, 'ip' => null, 'logging' => false, 'url' => null, 'ssl' => false) 83 | )) 84 | ), $config); 85 | } 86 | 87 | public function testSingleTopLevelDocumentManager() 88 | { 89 | $config = $this->processor->processConfiguration($this->config, array( 90 | array( 91 | 'client' => array(), 92 | 'odm' => array() 93 | ) 94 | )); 95 | 96 | $this->assertEquals(array( 97 | 'client' => array('default_connection' => 'default', 'connections' => array( 98 | 'default' => array('host' => 'localhost', 'port' => 5984, 'user' => null, 'password' => null, 'ip' => null, 'logging' => false, 'url' => null, 'ssl' => false) 99 | )), 100 | 'odm' => array( 101 | 'default_document_manager' => 'default', 102 | 'document_managers' => array( 103 | 'default' => array( 104 | 'metadata_cache_driver' => array('type' => 'array', 'namespace' => null), 105 | 'auto_mapping' => false, 106 | 'mappings' => array(), 107 | 'design_documents' => array(), 108 | 'lucene_handler_name' => false, 109 | 'uuid_buffer_size' => 20, 110 | 'view_name' => 'symfony', 111 | 'all_or_nothing_flush' => true, 112 | ), 113 | ), 114 | 'auto_generate_proxy_classes' => false, 115 | 'proxy_dir' => '%kernel.cache_dir%/doctrine/CouchDBProxies', 116 | 'proxy_namespace' => 'CouchDBProxies', 117 | ) 118 | ), $config); 119 | } 120 | 121 | public function testMultipleDocumentManager() 122 | { 123 | $config = $this->processor->processConfiguration($this->config, array( 124 | array( 125 | 'client' => array(), 126 | 'odm' => array( 127 | 'default_document_manager' => 'test', 128 | 'document_managers' => array('test' => array('connection' => 'default'), 'test2' => array()) 129 | ) 130 | ) 131 | )); 132 | 133 | $this->assertEquals(array( 134 | 'client' => array('default_connection' => 'default', 'connections' => array( 135 | 'default' => array('host' => 'localhost', 'port' => 5984, 'user' => null, 'password' => null, 'ip' => null, 'logging' => false, 'url' => null, 'ssl' => false) 136 | )), 137 | 'odm' => array( 138 | 'default_document_manager' => 'test', 139 | 'document_managers' => array( 140 | 'test' => array( 141 | 'connection' => 'default', 142 | 'metadata_cache_driver' => array('type' => 'array', 'namespace' => null), 143 | 'auto_mapping' => false, 144 | 'mappings' => array(), 145 | 'design_documents' => array(), 146 | 'lucene_handler_name' => false, 147 | 'uuid_buffer_size' => 20, 148 | 'view_name' => 'symfony', 149 | 'all_or_nothing_flush' => true, 150 | ), 151 | 'test2' => array( 152 | 'metadata_cache_driver' => array('type' => 'array', 'namespace' => null), 153 | 'auto_mapping' => false, 154 | 'mappings' => array(), 155 | 'design_documents' => array(), 156 | 'lucene_handler_name' => false, 157 | 'uuid_buffer_size' => 20, 158 | 'view_name' => 'symfony', 159 | 'all_or_nothing_flush' => true, 160 | ), 161 | ), 162 | 'auto_generate_proxy_classes' => false, 163 | 'proxy_dir' => '%kernel.cache_dir%/doctrine/CouchDBProxies', 164 | 'proxy_namespace' => 'CouchDBProxies', 165 | ) 166 | ), $config); 167 | } 168 | } 169 | -------------------------------------------------------------------------------- /DependencyInjection/Compiler/DoctrineCouchDBMappingsPass.php: -------------------------------------------------------------------------------- 1 | 7 | * (c) Doctrine Project, Benjamin Eberlei 8 | * 9 | * For the full copyright and license information, please view the LICENSE 10 | * file that was distributed with this source code. 11 | */ 12 | 13 | namespace Doctrine\Bundle\CouchDBBundle\DependencyInjection\Compiler; 14 | 15 | use Symfony\Bridge\Doctrine\DependencyInjection\CompilerPass\RegisterMappingsPass; 16 | use Symfony\Component\DependencyInjection\Definition; 17 | use Symfony\Component\DependencyInjection\Reference; 18 | 19 | /** 20 | * Class for Symfony bundles to configure mappings for model classes not in the 21 | * automapped folder. 22 | * 23 | * NOTE: alias is only supported by Symfony 2.6+ and will be ignored with older versions. 24 | * 25 | * @author David Buchmann 26 | */ 27 | class DoctrineCouchDBMappingsPass extends RegisterMappingsPass 28 | { 29 | /** 30 | * You should not directly instantiate this class but use one of the 31 | * factory methods. 32 | * 33 | * @param Definition|Reference $driver the driver to use 34 | * @param array $namespaces list of namespaces this driver should handle 35 | * @param string[] $managerParameters list of parameters that could tell the manager name to use 36 | * @param bool $enabledParameter if specified, the compiler pass only 37 | * executes if this parameter exists in the service container. 38 | * @param string[] $aliasMap Map of alias to namespace. 39 | */ 40 | public function __construct($driver, $namespaces, $managerParameters, $enabledParameter = false, array $aliasMap = array()) 41 | { 42 | $managerParameters[] = 'doctrine_couchdb.default_document_manager'; 43 | parent::__construct( 44 | $driver, 45 | $namespaces, 46 | $managerParameters, 47 | 'doctrine_couchdb.odm.%s_metadata_driver', 48 | $enabledParameter, 49 | 'doctrine_couchdb.odm.%s_configuration', 50 | 'addDocumentNamespace', 51 | $aliasMap 52 | ); 53 | 54 | } 55 | 56 | /** 57 | * @param array $namespaces Hashmap of directory path to namespace 58 | * @param string[] $managerParameters List of parameters that could which object manager name 59 | * your bundle uses. This compiler pass will automatically 60 | * append the parameter name for the default entity manager 61 | * to this list. 62 | * @param string $enabledParameter Service container parameter that must be present to 63 | * enable the mapping. Set to false to not do any check, 64 | * optional. 65 | * @param string[] $aliasMap Map of alias to namespace. 66 | */ 67 | public static function createXmlMappingDriver(array $namespaces, array $managerParameters, $enabledParameter = false, array $aliasMap = array()) 68 | { 69 | $arguments = array($namespaces, '.couchdb.xml'); 70 | $locator = new Definition('Doctrine\Common\Persistence\Mapping\Driver\SymfonyFileLocator', $arguments); 71 | $driver = new Definition('Doctrine\ODM\CouchDB\Mapping\Driver\XmlDriver', array($locator)); 72 | 73 | return new DoctrineCouchDBMappingsPass($driver, $namespaces, $managerParameters, $enabledParameter, $aliasMap); 74 | } 75 | 76 | /** 77 | * @param array $namespaces Hashmap of directory path to namespace 78 | * @param string[] $managerParameters List of parameters that could which object manager name 79 | * your bundle uses. This compiler pass will automatically 80 | * append the parameter name for the default entity manager 81 | * to this list. 82 | * @param string $enabledParameter Service container parameter that must be present to 83 | * enable the mapping. Set to false to not do any check, 84 | * optional. 85 | * @param string[] $aliasMap Map of alias to namespace. 86 | */ 87 | public static function createYamlMappingDriver(array $namespaces, array $managerParameters, $enabledParameter = false, array $aliasMap = array()) 88 | { 89 | $arguments = array($namespaces, '.couchdb.yml'); 90 | $locator = new Definition('Doctrine\Common\Persistence\Mapping\Driver\SymfonyFileLocator', $arguments); 91 | $driver = new Definition('Doctrine\ODM\CouchDB\Mapping\Driver\YamlDriver', array($locator)); 92 | 93 | return new DoctrineCouchDBMappingsPass($driver, $namespaces, $managerParameters, $enabledParameter, $aliasMap); 94 | } 95 | 96 | /** 97 | * @param array $namespaces List of namespaces that are handled with annotation mapping 98 | * @param array $directories List of directories to look for annotation mapping files 99 | * @param string[] $managerParameters List of parameters that could which object manager name 100 | * your bundle uses. This compiler pass will automatically 101 | * append the parameter name for the default entity manager 102 | * to this list. 103 | * @param string $enabledParameter Service container parameter that must be present to 104 | * enable the mapping. Set to false to not do any check, 105 | * optional.. 106 | * @param string[] $aliasMap Map of alias to namespace. 107 | */ 108 | public static function createAnnotationMappingDriver(array $namespaces, array $directories, array $managerParameters, $enabledParameter = false, array $aliasMap = array()) 109 | { 110 | $arguments = array(new Reference('doctrine_couchdb.odm.metadata.annotation_reader'), $directories); 111 | $locator = new Definition('Doctrine\Common\Persistence\Mapping\Driver\SymfonyFileLocator', $arguments); 112 | $driver = new Definition('Doctrine\ODM\CouchDB\Mapping\Driver\AnnotationDriver', array($locator)); 113 | 114 | return new DoctrineCouchDBMappingsPass($driver, $namespaces, $managerParameters, $enabledParameter, $aliasMap); 115 | } 116 | 117 | /** 118 | * @param array $namespaces Hashmap of directory path to namespace 119 | * @param string[] $managerParameters List of parameters that could which object manager name 120 | * your bundle uses. This compiler pass will automatically 121 | * append the parameter name for the default entity manager 122 | * to this list. 123 | * @param string $enabledParameter Service container parameter that must be present to 124 | * enable the mapping. Set to false to not do any check, 125 | * optional.. 126 | * @param string[] $aliasMap Map of alias to namespace. 127 | */ 128 | public static function createPhpMappingDriver(array $namespaces, array $managerParameters = array(), $enabledParameter = false, array $aliasMap = array()) 129 | { 130 | $arguments = array($namespaces, '.php'); 131 | $locator = new Definition('Doctrine\Common\Persistence\Mapping\Driver\SymfonyFileLocator', $arguments); 132 | $driver = new Definition('Doctrine\Common\Persistence\Mapping\Driver\PHPDriver', array($locator)); 133 | 134 | return new DoctrineCouchDBMappingsPass($driver, $namespaces, $managerParameters, $enabledParameter, $aliasMap); 135 | } 136 | 137 | /** 138 | * @param array $namespaces List of namespaces that are handled with static php mapping 139 | * @param array $directories List of directories to look for static php mapping files 140 | * @param string[] $managerParameters List of parameters that could which object manager name 141 | * your bundle uses. This compiler pass will automatically 142 | * append the parameter name for the default entity manager 143 | * to this list. 144 | * @param string $enabledParameter Service container parameter that must be present to 145 | * enable the mapping. Set to false to not do any check, 146 | * optional.. 147 | * @param string[] $aliasMap Map of alias to namespace. 148 | */ 149 | public static function createStaticPhpMappingDriver(array $namespaces, array $directories, array $managerParameters = array(), $enabledParameter = false, array $aliasMap = array()) 150 | { 151 | $driver = new Definition('Doctrine\Common\Persistence\Mapping\Driver\StaticPHPDriver', array($directories)); 152 | 153 | return new DoctrineCouchDBMappingsPass($driver, $namespaces, $managerParameters, $enabledParameter, $aliasMap); 154 | } 155 | } 156 | -------------------------------------------------------------------------------- /DependencyInjection/Configuration.php: -------------------------------------------------------------------------------- 1 | 14 | */ 15 | class Configuration implements ConfigurationInterface 16 | { 17 | private $debug; 18 | 19 | /** 20 | * Constructor 21 | * 22 | * @param Boolean $debug Whether to use the debug mode 23 | */ 24 | public function __construct($debug) 25 | { 26 | $this->debug = (Boolean) $debug; 27 | } 28 | 29 | public function getConfigTreeBuilder() 30 | { 31 | $treeBuilder = new TreeBuilder(); 32 | $rootNode = $treeBuilder->root('doctrine_couch_db'); 33 | 34 | $this->addClientSection($rootNode); 35 | $this->addOdmSection($rootNode); 36 | 37 | return $treeBuilder; 38 | } 39 | 40 | private function addClientSection(ArrayNodeDefinition $node) 41 | { 42 | $node 43 | ->children() 44 | ->arrayNode('client') 45 | ->isRequired() 46 | ->beforeNormalization() 47 | ->ifTrue(function ($v) { return !is_array($v) || (is_array($v) && !array_key_exists('connections', $v) && !array_key_exists('connection', $v)); }) 48 | ->then(function ($v) { 49 | if (!is_array($v)) { 50 | $v = array(); 51 | } 52 | 53 | $connection = array(); 54 | foreach (array( 55 | 'dbname', 56 | 'host', 57 | 'port', 58 | 'user', 59 | 'password', 60 | 'ip', 61 | 'logging', 62 | 'type', 63 | 'url', 64 | 'timeout' 65 | ) as $key) { 66 | if (array_key_exists($key, $v)) { 67 | $connection[$key] = $v[$key]; 68 | unset($v[$key]); 69 | } 70 | } 71 | $v['default_connection'] = isset($v['default_connection']) ? (string) $v['default_connection'] : 'default'; 72 | $v['connections'] = array($v['default_connection'] => $connection); 73 | 74 | return $v; 75 | }) 76 | ->end() 77 | ->children() 78 | ->scalarNode('default_connection')->end() 79 | ->end() 80 | ->fixXmlConfig('connection') 81 | ->append($this->getClientConnectionsNode()) 82 | ->end() 83 | ; 84 | } 85 | 86 | private function getClientConnectionsNode() 87 | { 88 | $treeBuilder = new TreeBuilder(); 89 | $node = $treeBuilder->root('connections'); 90 | 91 | $node 92 | ->requiresAtLeastOneElement() 93 | ->useAttributeAsKey('name') 94 | ->prototype('array') 95 | ->children() 96 | ->scalarNode('dbname')->end() 97 | ->scalarNode('host')->defaultValue('localhost')->end() 98 | ->scalarNode('port')->defaultValue(5984)->end() 99 | ->scalarNode('user')->defaultNull()->end() 100 | ->scalarNode('password')->defaultNull()->end() 101 | ->scalarNode('ip')->defaultNull()->end() 102 | ->scalarNode('url')->defaultNull()->end() 103 | ->scalarNode('ssl')->defaultValue(false)->end() 104 | ->booleanNode('logging')->defaultValue($this->debug)->end() 105 | ->scalarNode('type')->end() 106 | ->scalarNode('timeout')->defaultValue(0.01)->end() 107 | ->end() 108 | ->end() 109 | ; 110 | 111 | return $node; 112 | } 113 | 114 | private function addOdmSection(ArrayNodeDefinition $node) 115 | { 116 | $node 117 | ->children() 118 | ->arrayNode('odm') 119 | ->beforeNormalization() 120 | ->ifTrue(function ($v) { return null === $v || (is_array($v) && !array_key_exists('document_managers', $v) && !array_key_exists('document_manager', $v)); }) 121 | ->then(function ($v) { 122 | $v = (array) $v; 123 | $documentManagers = array(); 124 | foreach (array( 125 | 'metadata_cache_driver', 'metadata-cache-driver', 126 | 'auto_mapping', 'auto-mapping', 127 | 'mappings', 'mapping', 128 | 'connection', 129 | ) as $key) { 130 | if (array_key_exists($key, $v)) { 131 | $documentManagers[$key] = $v[$key]; 132 | unset($v[$key]); 133 | } 134 | } 135 | $v['default_document_manager'] = isset($v['default_document_manager']) ? (string) $v['default_document_manager'] : 'default'; 136 | $v['document_managers'] = array($v['default_document_manager'] => $documentManagers); 137 | 138 | return $v; 139 | }) 140 | ->end() 141 | ->children() 142 | ->scalarNode('default_document_manager')->end() 143 | ->booleanNode('auto_generate_proxy_classes')->defaultFalse()->end() 144 | ->scalarNode('proxy_dir')->defaultValue('%kernel.cache_dir%/doctrine/CouchDBProxies')->end() 145 | ->scalarNode('proxy_namespace')->defaultValue('CouchDBProxies')->end() 146 | ->end() 147 | ->fixXmlConfig('document_manager') 148 | ->append($this->getOdmDocumentManagersNode()) 149 | ->end() 150 | ->end() 151 | ; 152 | } 153 | 154 | private function getOdmDocumentManagersNode() 155 | { 156 | $treeBuilder = new TreeBuilder(); 157 | $node = $treeBuilder->root('document_managers'); 158 | 159 | $node 160 | ->requiresAtLeastOneElement() 161 | ->useAttributeAsKey('name') 162 | ->prototype('array') 163 | ->addDefaultsIfNotSet() 164 | ->append($this->getOdmCacheDriverNode('metadata_cache_driver')) 165 | ->children() 166 | ->scalarNode('connection')->end() 167 | ->scalarNode('auto_mapping')->defaultFalse()->end() 168 | ->end() 169 | ->fixXmlConfig('mapping') 170 | ->fixXmlConfig('design_document') 171 | ->children() 172 | ->arrayNode('mappings') 173 | ->useAttributeAsKey('name') 174 | ->prototype('array') 175 | ->beforeNormalization() 176 | ->ifString() 177 | ->then(function($v) { return array('type' => $v); }) 178 | ->end() 179 | ->treatNullLike(array()) 180 | ->treatFalseLike(array('mapping' => false)) 181 | ->performNoDeepMerging() 182 | ->children() 183 | ->scalarNode('mapping')->defaultValue(true)->end() 184 | ->scalarNode('type')->end() 185 | ->scalarNode('dir')->end() 186 | ->scalarNode('alias')->end() 187 | ->scalarNode('prefix')->end() 188 | ->booleanNode('is_bundle')->end() 189 | ->end() 190 | ->end() 191 | ->end() 192 | ->arrayNode('design_documents') 193 | ->useAttributeAsKey('name') 194 | ->prototype('array') 195 | ->treatNullLike(array()) 196 | ->children() 197 | ->scalarNode('className')->end() 198 | ->variableNode('options')->end() 199 | ->end() 200 | ->end() 201 | ->end() 202 | ->scalarNode('lucene_handler_name')->defaultFalse()->end() 203 | ->scalarNode('uuid_buffer_size')->defaultValue(20)->end() 204 | ->scalarNode('view_name')->defaultValue('symfony')->end() 205 | ->booleanNode('all_or_nothing_flush')->defaultTrue()->end() 206 | ->end() 207 | ->end() 208 | ; 209 | 210 | return $node; 211 | } 212 | 213 | private function getOdmCacheDriverNode($name) 214 | { 215 | $treeBuilder = new TreeBuilder(); 216 | $node = $treeBuilder->root($name); 217 | 218 | $node 219 | ->addDefaultsIfNotSet() 220 | ->beforeNormalization() 221 | ->ifString() 222 | ->then(function($v) { return array('type' => $v); }) 223 | ->end() 224 | ->children() 225 | ->scalarNode('type')->defaultValue('array')->isRequired()->end() 226 | ->scalarNode('host')->end() 227 | ->scalarNode('port')->end() 228 | ->scalarNode('instance_class')->end() 229 | ->scalarNode('class')->end() 230 | ->scalarNode('namespace')->defaultNull()->end() 231 | ->end() 232 | ; 233 | 234 | return $node; 235 | } 236 | } 237 | -------------------------------------------------------------------------------- /DependencyInjection/DoctrineCouchDBExtension.php: -------------------------------------------------------------------------------- 1 | 20 | */ 21 | class DoctrineCouchDBExtension extends AbstractDoctrineExtension 22 | { 23 | private $documentManagers; 24 | 25 | private $bundleDirs = array(); 26 | 27 | public function load(array $configs, ContainerBuilder $container) 28 | { 29 | $processor = new Processor(); 30 | $configuration = new Configuration($container->getParameter('kernel.debug')); 31 | $config = $processor->processConfiguration($configuration, $configs); 32 | 33 | if (!empty($config['client'])) { 34 | $this->clientLoad($config['client'], $container); 35 | } 36 | 37 | if (!empty($config['odm'])) { 38 | $this->odmLoad($config['odm'], $container); 39 | } 40 | } 41 | 42 | public function getConfiguration(array $config, ContainerBuilder $container) 43 | { 44 | return new Configuration($container->getParameter('kernel.debug')); 45 | } 46 | 47 | private function clientLoad($config, ContainerBuilder $container) 48 | { 49 | $loader = new XmlFileLoader($container, new FileLocator(__DIR__.'/../Resources/config')); 50 | $loader->load('client.xml'); 51 | 52 | if (empty($config['default_connection'])) { 53 | $keys = array_keys($config['connections']); 54 | $config['default_connection'] = reset($keys); 55 | } 56 | $this->defaultConnection = $config['default_connection']; 57 | 58 | $container->setAlias('couchdb_connection', sprintf('doctrine_couchdb.client.%s_connection', $this->defaultConnection)); 59 | 60 | $connections = array(); 61 | foreach (array_keys($config['connections']) as $name) { 62 | $connections[$name] = sprintf('doctrine_couchdb.client.%s_connection', $name); 63 | } 64 | $container->setParameter('doctrine_couchdb.connections', $connections); 65 | $container->setParameter('doctrine_couchdb.default_connection', $this->defaultConnection); 66 | 67 | foreach ($config['connections'] as $name => $connection) { 68 | $this->loadClientConnection($name, $connection, $container); 69 | } 70 | } 71 | 72 | protected function loadClientConnection($name, array $connection, ContainerBuilder $container) 73 | { 74 | $container 75 | ->setDefinition(sprintf('doctrine_couchdb.client.%s_connection', $name), new DefinitionDecorator('doctrine_couchdb.client.connection')) 76 | ->setArguments(array( 77 | $connection, 78 | )) 79 | ; 80 | 81 | if (isset($connection['logging']) && $connection['logging'] === true) { 82 | $def = new Definition('Doctrine\CouchDB\HTTP\Client'); 83 | $def->setFactory([new Reference(sprintf('doctrine_couchdb.client.%s_connection', $name)), 'getHttpClient']); 84 | $def->setPublic(false); 85 | 86 | $container->setDefinition(sprintf('doctrine_couchdb.httpclient.%s_client', $name), $def); 87 | 88 | $def = $container->getDefinition('doctrine_couchdb.datacollector'); 89 | $def->addMethodCall('addLoggingClient', array( 90 | new Reference(sprintf('doctrine_couchdb.httpclient.%s_client', $name)), 91 | $name 92 | )); 93 | } 94 | } 95 | 96 | private function odmLoad($config, $container) 97 | { 98 | $loader = new XmlFileLoader($container, new FileLocator(__DIR__.'/../Resources/config')); 99 | $loader->load('odm.xml'); 100 | 101 | $this->documentManagers = array(); 102 | foreach (array_keys($config['document_managers']) as $name) { 103 | $this->documentManagers[$name] = sprintf('doctrine_couchdb.odm.%s_document_manager', $name); 104 | } 105 | $container->setParameter('doctrine_couchdb.document_managers', $this->documentManagers); 106 | 107 | if (empty($config['default_document_manager'])) { 108 | $tmp = array_keys($this->documentManagers); 109 | $config['default_document_manager'] = reset($tmp); 110 | } 111 | $container->setParameter('doctrine_couchdb.default_document_manager', $config['default_document_manager']); 112 | 113 | $options = array('auto_generate_proxy_classes', 'proxy_dir', 'proxy_namespace'); 114 | foreach ($options as $key) { 115 | $container->setParameter('doctrine_couchdb.odm.'.$key, $config[$key]); 116 | } 117 | 118 | $container->setAlias('doctrine_couchdb.odm.document_manager', sprintf('doctrine_couchdb.odm.%s_document_manager', $config['default_document_manager'])); 119 | 120 | foreach ($config['document_managers'] as $name => $documentManager) { 121 | $documentManager['name'] = $name; 122 | $this->loadOdmDocumentManager($documentManager, $container); 123 | } 124 | } 125 | 126 | private function loadOdmDocumentManager($documentManager, ContainerBuilder $container) 127 | { 128 | if ($documentManager['auto_mapping'] && count($this->documentManagers) > 1) { 129 | throw new \LogicException('You cannot enable "auto_mapping" when several CouchDB document managers are defined.'); 130 | } 131 | 132 | $odmConfigDef = $container->setDefinition(sprintf('doctrine_couchdb.odm.%s_configuration', $documentManager['name']), new DefinitionDecorator('doctrine_couchdb.odm.configuration')); 133 | 134 | $this->loadOdmDocumentManagerMappingInformation($documentManager, $odmConfigDef, $container); 135 | $this->loadOdmDocumentManagerDesignDocuments($documentManager, $odmConfigDef); 136 | $this->loadOdmCacheDrivers($documentManager, $container); 137 | 138 | $methods = array( 139 | 'setMetadataCacheImpl' => new Reference(sprintf('doctrine_couchdb.odm.%s_metadata_cache', $documentManager['name'])), 140 | 'setMetadataDriverImpl' => new Reference('doctrine_couchdb.odm.'.$documentManager['name'].'_metadata_driver'), 141 | 'setProxyDir' => '%doctrine_couchdb.odm.proxy_dir%', 142 | 'setProxyNamespace' => '%doctrine_couchdb.odm.proxy_namespace%', 143 | 'setAutoGenerateProxyClasses' => '%doctrine_couchdb.odm.auto_generate_proxy_classes%', 144 | ); 145 | foreach ($methods as $method => $arg) { 146 | $odmConfigDef->addMethodCall($method, array($arg)); 147 | } 148 | 149 | $odmConfigDef->addMethodCall('setAllOrNothingFlush', array($documentManager['all_or_nothing_flush'])); 150 | 151 | if (!isset($documentManager['connection'])) { 152 | $documentManager['connection'] = $this->defaultConnection; 153 | } 154 | 155 | $def = $container->setDefinition(sprintf('doctrine_couchdb.odm.%s_connection.event_manager', $documentManager['name']), new DefinitionDecorator('doctrine_couchdb.odm.document_manager.event_manager')); 156 | 157 | $container 158 | ->setDefinition(sprintf('doctrine_couchdb.odm.%s_document_manager', $documentManager['name']), new DefinitionDecorator('doctrine_couchdb.odm.document_manager.abstract')) 159 | ->setArguments(array( 160 | new Reference(sprintf('doctrine_couchdb.client.%s_connection', $documentManager['connection'])), 161 | new Reference(sprintf('doctrine_couchdb.odm.%s_configuration', $documentManager['name'])), 162 | new Reference(sprintf('doctrine_couchdb.odm.%s_connection.event_manager', $documentManager['name'])) 163 | )) 164 | ; 165 | } 166 | 167 | protected function getMappingDriverBundleConfigDefaults(array $bundleConfig, \ReflectionClass $bundle, ContainerBuilder $container) 168 | { 169 | $this->bundleDirs[$bundle->getNamespaceName()] = dirname($bundle->getFileName()); 170 | return parent::getMappingDriverBundleConfigDefaults($bundleConfig, $bundle, $container); 171 | } 172 | 173 | 174 | protected function loadOdmDocumentManagerMappingInformation(array $documentManager, Definition $odmConfig, ContainerBuilder $container) 175 | { 176 | // reset state of drivers and alias map. They are only used by this methods and children. 177 | $this->drivers = array(); 178 | $this->aliasMap = array(); 179 | $this->bundleDirs = array(); 180 | 181 | $this->loadMappingInformation($documentManager, $container); 182 | $this->registerMappingDrivers($documentManager, $container); 183 | 184 | // This looks scary but essentially finds the right document manager for any registered/mapped bundle 185 | // and then registers any potential CouchDB views with that document manager. 186 | foreach ($this->aliasMap AS $alias => $prefix) { 187 | foreach ($this->bundleDirs AS $bundleNamespace => $bundleDir) { 188 | if (strpos($prefix, $bundleNamespace) === 0 && file_exists($bundleDir."/Resources/couchdb")) { 189 | $it = new \DirectoryIterator($bundleDir."/Resources/couchdb"); 190 | foreach ($it AS $res) { 191 | if ($res->isDir() && !$res->isDot()) { 192 | $odmConfig->addMethodCall('addDesignDocument', array( 193 | $res->getBasename(), 194 | 'Doctrine\CouchDB\View\FolderDesignDocument', 195 | $bundleDir."/Resources/couchdb/" . $res->getBasename() 196 | )); 197 | 198 | } 199 | } 200 | } 201 | } 202 | } 203 | 204 | 205 | $odmConfig->addMethodCall('setDocumentNamespaces', array($this->aliasMap)); 206 | } 207 | 208 | /** 209 | * Loads configured design_documents. 210 | * 211 | * @param array $documentManager The document manager configuration. 212 | * @param Definition $odmConfig A service definition instance. 213 | */ 214 | protected function loadOdmDocumentManagerDesignDocuments(array $documentManager, Definition $odmConfig) 215 | { 216 | foreach ($documentManager['design_documents'] as $name => $designDocument) { 217 | $odmConfig->addMethodCall( 218 | 'addDesignDocument', array( 219 | $name, 220 | $designDocument['className'], 221 | $designDocument['options'] 222 | ) 223 | ); 224 | } 225 | } 226 | 227 | /** 228 | * Loads a configured document managers cache drivers. 229 | * 230 | * @param array $documentManager A configured ORM document manager. 231 | * @param ContainerBuilder $container A ContainerBuilder instance 232 | */ 233 | protected function loadOdmCacheDrivers(array $documentManager, ContainerBuilder $container) 234 | { 235 | $this->loadOdmDocumentManagerCacheDriver($documentManager, $container, 'metadata_cache'); 236 | } 237 | 238 | /** 239 | * Loads a configured document managers metadata, query or result cache driver. 240 | * 241 | * @param array $documentManager A configured ORM document manager. 242 | * @param ContainerBuilder $container A ContainerBuilder instance 243 | * @param string $cacheName 244 | */ 245 | protected function loadOdmDocumentManagerCacheDriver(array $documentManager, ContainerBuilder $container, $cacheName) 246 | { 247 | $cacheDriverService = sprintf('doctrine_couchdb.odm.%s_%s', $documentManager['name'], $cacheName); 248 | 249 | $driver = $cacheName."_driver"; 250 | $cacheDef = $this->getDocumentManagerCacheDefinition($documentManager, $documentManager[$driver], $container); 251 | $container->setDefinition($cacheDriverService, $cacheDef); 252 | } 253 | 254 | /** 255 | * Gets an document manager cache driver definition for caches. 256 | * 257 | * @param array $documentManager The array configuring an document manager. 258 | * @param array $cacheDriver The cache driver configuration. 259 | * @param ContainerBuilder $container 260 | * @return Definition $cacheDef 261 | */ 262 | protected function getDocumentManagerCacheDefinition(array $documentManager, $cacheDriver, ContainerBuilder $container) 263 | { 264 | switch ($cacheDriver['type']) { 265 | case 'memcache': 266 | $memcacheClass = !empty($cacheDriver['class']) ? $cacheDriver['class'] : '%doctrine_couchdb.odm.cache.memcache.class%'; 267 | $memcacheInstanceClass = !empty($cacheDriver['instance_class']) ? $cacheDriver['instance_class'] : '%doctrine_couchdb.odm.cache.memcache_instance.class%'; 268 | $memcacheHost = !empty($cacheDriver['host']) ? $cacheDriver['host'] : '%doctrine_couchdb.odm.cache.memcache_host%'; 269 | $memcachePort = !empty($cacheDriver['port']) ? $cacheDriver['port'] : '%doctrine_couchdb.odm.cache.memcache_port%'; 270 | $cacheDef = new Definition($memcacheClass); 271 | $memcacheInstance = new Definition($memcacheInstanceClass); 272 | $memcacheInstance->addMethodCall('connect', array( 273 | $memcacheHost, $memcachePort 274 | )); 275 | $container->setDefinition(sprintf('doctrine_couchdb.odm.%s_memcache_instance', $documentManager['name']), $memcacheInstance); 276 | $cacheDef->addMethodCall('setMemcache', array(new Reference(sprintf('doctrine_couchdb.odm.%s_memcache_instance', $documentManager['name'])))); 277 | break; 278 | case 'apc': 279 | case 'array': 280 | case 'xcache': 281 | $cacheDef = new Definition('%'.sprintf('doctrine_couchdb.odm.cache.%s.class', $cacheDriver['type']).'%'); 282 | break; 283 | default: 284 | throw new \InvalidArgumentException(sprintf('"%s" is an unrecognized Doctrine cache driver.', $cacheDriver['type'])); 285 | } 286 | 287 | $cacheDef->setPublic(false); 288 | // generate a unique namespace for the given application 289 | $namespace = 'sf2couchdb_'.$documentManager['name'].'_'.md5($container->getParameter('kernel.root_dir')); 290 | $cacheDef->addMethodCall('setNamespace', array($namespace)); 291 | 292 | return $cacheDef; 293 | } 294 | 295 | protected function getObjectManagerElementName($name) 296 | { 297 | return 'doctrine_couchdb.odm.'.$name; 298 | } 299 | 300 | protected function getMappingObjectDefaultName() 301 | { 302 | return 'CouchDocument'; 303 | } 304 | 305 | protected function getMappingResourceConfigDirectory() 306 | { 307 | return 'Resources/config/doctrine'; 308 | } 309 | 310 | protected function getMappingResourceExtension() 311 | { 312 | return 'couchdb'; 313 | } 314 | } 315 | --------------------------------------------------------------------------------