diff --git a/config/oauth2.doctrine-orm.global.php.dist b/config/oauth2.doctrine-orm.global.php.dist index c59d734..2377bd1 100644 --- a/config/oauth2.doctrine-orm.global.php.dist +++ b/config/oauth2.doctrine-orm.global.php.dist @@ -64,6 +64,10 @@ return array( ), ), ), + 'scope_entity' => array( + 'entity' => 'ZF\OAuth2\Doctrine\Entity\Scope', + 'field' => 'scope', + ), ), 'mapping' => array( 'User' => array( diff --git a/media/OAuth2-orm.module.xml b/media/OAuth2-orm.module.xml index 101063b..58ce1ca 100755 --- a/media/OAuth2-orm.module.xml +++ b/media/OAuth2-orm.module.xml @@ -1,6 +1,6 @@ - + @@ -13,6 +13,8 @@ + + @@ -50,7 +52,6 @@ AccessTokenToScope_OAuth2 - @@ -208,19 +209,28 @@ CASCADE + + + + + + - - - + + + + + + - + - + @@ -236,9 +246,10 @@ - - - - + + + + + diff --git a/media/OAuth2-orm.skipper b/media/OAuth2-orm.skipper index e7e294f..de5d5df 100755 --- a/media/OAuth2-orm.skipper +++ b/media/OAuth2-orm.skipper @@ -3,12 +3,12 @@ - + - - - + + + diff --git a/media/oauth2-doctrine-erd.png b/media/oauth2-doctrine-erd.png index 45af7e1..86d4419 100644 Binary files a/media/oauth2-doctrine-erd.png and b/media/oauth2-doctrine-erd.png differ diff --git a/src/EventListener/DynamicMappingSubscriber.php b/src/EventListener/DynamicMappingSubscriber.php index 1beb18c..e9b9bb1 100644 --- a/src/EventListener/DynamicMappingSubscriber.php +++ b/src/EventListener/DynamicMappingSubscriber.php @@ -10,9 +10,15 @@ use Doctrine\ORM\Events; use Doctrine\ORM\Event\LoadClassMetadataEventArgs; use Zend\Config\Config; +use DoctrineModule\Persistence\ProvidesObjectManager; +use DoctrineModule\Persistence\ObjectManagerAwareInterface; -class DynamicMappingSubscriber implements EventSubscriber +class DynamicMappingSubscriber implements + EventSubscriber, + ObjectManagerAwareInterface { + use ProvidesObjectManager; + protected $config = array(); protected $mapping = array(); @@ -47,6 +53,8 @@ public function getSubscribedEvents() */ public function loadClassMetadata(LoadClassMetadataEventArgs $eventArgs) { + $this->setObjectManager($eventArgs->getObjectManager()); + // the $metadata is the whole mapping info for this class $metadata = $eventArgs->getClassMetadata(); @@ -83,8 +91,10 @@ public function loadClassMetadata(LoadClassMetadataEventArgs $eventArgs) $clientIdField = $this->getMapping()->Client->mapping->client_id->name; $clientIdColumn = $metadata->columnNames[$clientIdField]; - $metadata->table['uniqueConstraints']['idx_' . $clientIdColumn . '_unique']['columns'][] = - $clientIdColumn; + $indexName = $this->_generateIdentifierName( + array_merge(array($metadata->table['name']), ['clientId']), "uniq", $this->_getMaxIdentifierLength() + ); + $metadata->table['uniqueConstraints'][$indexName]['columns'][] = $clientIdColumn; $joinMap = array( 'targetEntity' => $this->getConfig()->user_entity->entity, @@ -145,8 +155,39 @@ public function loadClassMetadata(LoadClassMetadataEventArgs $eventArgs) $metadata->mapManyToOne($joinMap); break; + case $this->getConfig()->scope_entity->entity: + // Add unique constriant for clientId based on column + // See https://github.com/TomHAnderson/zf-oauth2-doctrine/issues/24 + $nameField = $this->getMapping()->Scope->mapping->scope->name; + $nameColumn = $metadata->columnNames[$nameField]; + $indexName = $this->_generateIdentifierName( + array_merge(array($metadata->table['name']), ['scope']), "uniq", $this->_getMaxIdentifierLength() + ); + $metadata->table['uniqueConstraints'][$indexName]['columns'][] = $nameColumn; + break; + default: break; } } + + // Copied from Doctrine DBAL\Schema\Table + protected function _generateIdentifierName($columnNames, $prefix='', $maxSize=30) + { + $hash = implode("", array_map(function ($column) { + return dechex(crc32($column)); + }, $columnNames)); + + return substr(strtoupper($prefix . "_" . $hash), 0, $maxSize); + } + + protected function _getMaxIdentifierLength() + { + return $this->getObjectManager() + ->getConnection() + ->getSchemaManager() + ->getDatabasePlatform() + ->getMaxIdentifierLength() + ; + } }