diff --git a/lib/internal/Magento/Framework/App/Resource.php b/lib/internal/Magento/Framework/App/Resource.php index d76a3a68bdcafbc35eda2c73dc8b1868fb39ee61..fae3cdb761c5fc502aef804db2f7b59f492ef335 100644 --- a/lib/internal/Magento/Framework/App/Resource.php +++ b/lib/internal/Magento/Framework/App/Resource.php @@ -85,6 +85,7 @@ class Resource * * @param string $resourceName * @return \Magento\Framework\DB\Adapter\AdapterInterface|false + * @codeCoverageIgnore */ public function getConnection($resourceName) { @@ -152,12 +153,26 @@ class Resource return $this->getConnection($connectionName)->getTableName($tableName); } + /** + * Build a trigger name + * + * @param string $tableName The table that is the subject of the trigger + * @param string $time Either "before" or "after" + * @param string $event The DB level event which activates the trigger, i.e. "update" or "insert" + * @return string + */ + public function getTriggerName($tableName, $time, $event) + { + return $this->getConnection(self::DEFAULT_READ_RESOURCE)->getTriggerName($tableName, $time, $event); + } + /** * Set mapped table name * * @param string $tableName * @param string $mappedName * @return $this + * @codeCoverageIgnore */ public function setMappedTableName($tableName, $mappedName) { @@ -193,13 +208,12 @@ class Resource $fields, $indexType = \Magento\Framework\DB\Adapter\AdapterInterface::INDEX_TYPE_INDEX ) { - return $this->getConnection( - self::DEFAULT_READ_RESOURCE - )->getIndexName( - $this->getTableName($tableName), - $fields, - $indexType - ); + return $this->getConnection(self::DEFAULT_READ_RESOURCE) + ->getIndexName( + $this->getTableName($tableName), + $fields, + $indexType + ); } /** diff --git a/lib/internal/Magento/Framework/App/Test/Unit/ResourceTest.php b/lib/internal/Magento/Framework/App/Test/Unit/ResourceTest.php index a92a9eb73432db63d22a8b28c104da5ec28360f4..86fc5bf7ac92bcbd89d423311a0fd3fc9be8cfbe 100644 --- a/lib/internal/Magento/Framework/App/Test/Unit/ResourceTest.php +++ b/lib/internal/Magento/Framework/App/Test/Unit/ResourceTest.php @@ -14,7 +14,7 @@ use Magento\Framework\Config\ConfigOptionsListConstants; class ResourceTest extends \PHPUnit_Framework_TestCase { const RESOURCE_NAME = \Magento\Framework\App\Resource::DEFAULT_READ_RESOURCE; - const CONNECTION_NAME = 'Connection Name'; + const CONNECTION_NAME = 'connection-name'; const TABLE_PREFIX = 'prefix_'; /** @@ -197,4 +197,21 @@ class ResourceTest extends \PHPUnit_Framework_TestCase $this->assertEquals('fkName', $this->resource->getFkName($table, $columnName, $refTable, $refColumnName)); } + + public function testGetTriggerName() + { + $tableName = 'subject_table'; + $time = 'before'; + $event = 'insert'; + $triggerName = 'trg_subject_table_before_insert'; + + $this->_connectionFactory->expects($this->once()) + ->method('create') + ->will($this->returnValue($this->connection)); + $this->connection->expects($this->once()) + ->method('getTriggerName') + ->with($tableName, $time, $event) + ->willReturn($triggerName); + $this->assertSame($triggerName, $this->resource->getTriggerName($tableName, $time, $event)); + } } diff --git a/lib/internal/Magento/Framework/DB/Adapter/AdapterInterface.php b/lib/internal/Magento/Framework/DB/Adapter/AdapterInterface.php index 96eb992ade3f58cd9e3d6860c36fc1310baacd4b..ed43451bfa848d1bc40599fa074d113ea7e03670 100644 --- a/lib/internal/Magento/Framework/DB/Adapter/AdapterInterface.php +++ b/lib/internal/Magento/Framework/DB/Adapter/AdapterInterface.php @@ -918,6 +918,17 @@ interface AdapterInterface */ public function getTableName($tableName); + + /** + * Build a trigger name based on table name and trigger details + * + * @param string $tableName The table that is the subject of the trigger + * @param string $time Either "before" or "after" + * @param string $event The DB level event which activates the trigger, i.e. "update" or "insert" + * @return string + */ + public function getTriggerName($tableName, $time, $event); + /** * Retrieve valid index name * Check index name length and allowed symbols diff --git a/lib/internal/Magento/Framework/DB/Adapter/Pdo/Mysql.php b/lib/internal/Magento/Framework/DB/Adapter/Pdo/Mysql.php index 013e4148ba4ba36bcc194a825f3cbf79dec4238b..0ea7863c01942408729bcd06527301cb7f1eac48 100644 --- a/lib/internal/Magento/Framework/DB/Adapter/Pdo/Mysql.php +++ b/lib/internal/Magento/Framework/DB/Adapter/Pdo/Mysql.php @@ -19,6 +19,7 @@ use Magento\Framework\DB\Profiler; use Magento\Framework\DB\Select; use Magento\Framework\DB\Statement\Parameter; use Magento\Framework\Exception\LocalizedException; +use Magento\Framework\Mview\View\Subscription; use Magento\Framework\Phrase; use Magento\Framework\Stdlib\DateTime; use Magento\Framework\Stdlib\String; @@ -3115,47 +3116,31 @@ class Mysql extends \Zend_Db_Adapter_Pdo_Mysql implements AdapterInterface } /** - * Minus superfluous characters from hash. + * Returns a compressed version of the table name if it is too long * - * @param string $hash - * @param string $prefix - * @param int $maxCharacters + * @param string $tableName * @return string + * @codeCoverageIgnore */ - protected function _minusSuperfluous($hash, $prefix, $maxCharacters) + public function getTableName($tableName) { - $diff = strlen($hash) + strlen($prefix) - $maxCharacters; - $superfluous = $diff / 2; - $odd = $diff % 2; - $hash = substr($hash, $superfluous, - ($superfluous + $odd)); - return $hash; + return ExpressionConverter::shortenEntityName($tableName, 't_'); } /** - * Retrieve valid table name - * Check table name length and allowed symbols + * Build a trigger name based on table name and trigger details * - * @param string $tableName + * @param string $tableName The table which is the subject of the trigger + * @param string $time Either "before" or "after" + * @param string $event The DB level event which activates the trigger, i.e. "update" or "insert" * @return string + * @codeCoverageIgnore */ - public function getTableName($tableName) - { - $prefix = 't_'; - if (strlen($tableName) > self::LENGTH_TABLE_NAME) { - $shortName = ExpressionConverter::shortName($tableName); - if (strlen($shortName) > self::LENGTH_TABLE_NAME) { - $hash = md5($tableName); - if (strlen($prefix . $hash) > self::LENGTH_TABLE_NAME) { - $tableName = $this->_minusSuperfluous($hash, $prefix, self::LENGTH_TABLE_NAME); - } else { - $tableName = $prefix . $hash; - } - } else { - $tableName = $shortName; - } - } - return $tableName; + public function getTriggerName($tableName, $time, $event) + { + $triggerName = 'trg_' . $tableName . '_' . $time . '_' . $event; + return ExpressionConverter::shortenEntityName($triggerName, 'trg_'); } /** @@ -3176,35 +3161,15 @@ class Mysql extends \Zend_Db_Adapter_Pdo_Mysql implements AdapterInterface switch (strtolower($indexType)) { case AdapterInterface::INDEX_TYPE_UNIQUE: $prefix = 'unq_'; - $shortPrefix = 'u_'; break; case AdapterInterface::INDEX_TYPE_FULLTEXT: $prefix = 'fti_'; - $shortPrefix = 'f_'; break; case AdapterInterface::INDEX_TYPE_INDEX: default: $prefix = 'idx_'; - $shortPrefix = 'i_'; - } - - $hash = $tableName . '_' . $fields; - - if (strlen($hash) + strlen($prefix) > self::LENGTH_INDEX_NAME) { - $short = ExpressionConverter::shortName($prefix . $hash); - if (strlen($short) > self::LENGTH_INDEX_NAME) { - $hash = md5($hash); - if (strlen($hash) + strlen($shortPrefix) > self::LENGTH_INDEX_NAME) { - $hash = $this->_minusSuperfluous($hash, $shortPrefix, self::LENGTH_INDEX_NAME); - } - } else { - $hash = $short; - } - } else { - $hash = $prefix . $hash; } - - return strtoupper($hash); + return strtoupper(ExpressionConverter::shortenEntityName($tableName . '_' . $fields, $prefix)); } /** @@ -3216,28 +3181,12 @@ class Mysql extends \Zend_Db_Adapter_Pdo_Mysql implements AdapterInterface * @param string $refTableName * @param string $refColumnName * @return string + * @codeCoverageIgnore */ public function getForeignKeyName($priTableName, $priColumnName, $refTableName, $refColumnName) { - $prefix = 'fk_'; - $hash = sprintf('%s_%s_%s_%s', $priTableName, $priColumnName, $refTableName, $refColumnName); - if (strlen($prefix . $hash) > self::LENGTH_FOREIGN_NAME) { - $short = ExpressionConverter::shortName($prefix . $hash); - if (strlen($short) > self::LENGTH_FOREIGN_NAME) { - $hash = md5($hash); - if (strlen($prefix . $hash) > self::LENGTH_FOREIGN_NAME) { - $hash = $this->_minusSuperfluous($hash, $prefix, self::LENGTH_FOREIGN_NAME); - } else { - $hash = $prefix . $hash; - } - } else { - $hash = $short; - } - } else { - $hash = $prefix . $hash; - } - - return strtoupper($hash); + $fkName = sprintf('%s_%s_%s_%s', $priTableName, $priColumnName, $refTableName, $refColumnName); + return strtoupper(ExpressionConverter::shortenEntityName($fkName, 'fk_')); } /** diff --git a/lib/internal/Magento/Framework/DB/ExpressionConverter.php b/lib/internal/Magento/Framework/DB/ExpressionConverter.php index 2df91ab77991222d8f1814134020df7e3d45dc1e..9a9b2d7eacf4797821fded20bf885edb7367ea00 100644 --- a/lib/internal/Magento/Framework/DB/ExpressionConverter.php +++ b/lib/internal/Magento/Framework/DB/ExpressionConverter.php @@ -10,7 +10,12 @@ namespace Magento\Framework\DB; class ExpressionConverter { /** - * Dictionary for generate short name + * Maximum length for many MySql identifiers, including database, table, trigger, and column names + */ + const MYSQL_IDENTIFIER_LEN = 64; + + /** + * Dictionary maps common words in identifiers to abbreviations * * @var array */ @@ -62,7 +67,7 @@ class ExpressionConverter ]; /** - * Convert name using dictionary + * Shorten name by abbreviating words * * @param string $name * @return string @@ -73,7 +78,7 @@ class ExpressionConverter } /** - * Add or replace translate to dictionary + * Add an abbreviation to the dictionary, or replace if it already exists * * @param string $from * @param string $to @@ -83,4 +88,47 @@ class ExpressionConverter { self::$_translateMap[$from] = $to; } + + /** + * Shorten the name of a MySql identifier, by abbreviating common words and hashing if necessary. Prepends the + * given prefix to clarify what kind of entity the identifier represents, in case hashing is used. + * + * @param string $entityName + * @param string $prefix + * @return string + */ + public static function shortenEntityName($entityName, $prefix) + { + if (strlen($entityName) > self::MYSQL_IDENTIFIER_LEN) { + $shortName = ExpressionConverter::shortName($entityName); + if (strlen($shortName) > self::MYSQL_IDENTIFIER_LEN) { + $hash = md5($entityName); + if (strlen($prefix . $hash) > self::MYSQL_IDENTIFIER_LEN) { + $entityName = self::trimHash($hash, $prefix, self::MYSQL_IDENTIFIER_LEN); + } else { + $entityName = $prefix . $hash; + } + } else { + $entityName = $shortName; + } + } + return $entityName; + } + + /** + * Remove superfluous characters from hash + * + * @param string $hash + * @param string $prefix + * @param int $maxCharacters + * @return string + */ + private static function trimHash($hash, $prefix, $maxCharacters) + { + $diff = strlen($hash) + strlen($prefix) - $maxCharacters; + $superfluous = $diff / 2; + $odd = $diff % 2; + $hash = substr($hash, $superfluous, - ($superfluous + $odd)); + return $hash; + } } diff --git a/lib/internal/Magento/Framework/DB/Test/Unit/Adapter/Pdo/MysqlTest.php b/lib/internal/Magento/Framework/DB/Test/Unit/Adapter/Pdo/MysqlTest.php index b7c080064bc969890c42c8ca983025f89548738c..4d7bfa42ed2eab83d5f1d5e67b31ca022cf1e8b1 100644 --- a/lib/internal/Magento/Framework/DB/Test/Unit/Adapter/Pdo/MysqlTest.php +++ b/lib/internal/Magento/Framework/DB/Test/Unit/Adapter/Pdo/MysqlTest.php @@ -11,6 +11,8 @@ */ namespace Magento\Framework\DB\Test\Unit\Adapter\Pdo; +use Magento\Framework\DB\Adapter\AdapterInterface; + class MysqlTest extends \PHPUnit_Framework_TestCase { /** @@ -149,7 +151,7 @@ class MysqlTest extends \PHPUnit_Framework_TestCase } catch (\Exception $e) { $this->assertNotContains( $e->getMessage(), - \Magento\Framework\DB\Adapter\AdapterInterface::ERROR_DDL_MESSAGE + AdapterInterface::ERROR_DDL_MESSAGE ); } @@ -160,7 +162,7 @@ class MysqlTest extends \PHPUnit_Framework_TestCase } catch (\Exception $e) { $this->assertNotContains( $e->getMessage(), - \Magento\Framework\DB\Adapter\AdapterInterface::ERROR_DDL_MESSAGE + AdapterInterface::ERROR_DDL_MESSAGE ); } } @@ -226,7 +228,7 @@ class MysqlTest extends \PHPUnit_Framework_TestCase throw new \Exception('Test Failed!'); } catch (\Exception $e) { $this->assertEquals( - \Magento\Framework\DB\Adapter\AdapterInterface::ERROR_ASYMMETRIC_ROLLBACK_MESSAGE, + AdapterInterface::ERROR_ASYMMETRIC_ROLLBACK_MESSAGE, $e->getMessage() ); } @@ -242,7 +244,7 @@ class MysqlTest extends \PHPUnit_Framework_TestCase throw new \Exception('Test Failed!'); } catch (\Exception $e) { $this->assertEquals( - \Magento\Framework\DB\Adapter\AdapterInterface::ERROR_ASYMMETRIC_COMMIT_MESSAGE, + AdapterInterface::ERROR_ASYMMETRIC_COMMIT_MESSAGE, $e->getMessage() ); } @@ -354,7 +356,7 @@ class MysqlTest extends \PHPUnit_Framework_TestCase throw new \Exception('Test Failed!'); } catch (\Exception $e) { $this->assertEquals( - \Magento\Framework\DB\Adapter\AdapterInterface::ERROR_ROLLBACK_INCOMPLETE_MESSAGE, + AdapterInterface::ERROR_ROLLBACK_INCOMPLETE_MESSAGE, $e->getMessage() ); $this->_adapter->rollBack(); @@ -377,7 +379,7 @@ class MysqlTest extends \PHPUnit_Framework_TestCase throw new \Exception('Test Failed!'); } catch (\Exception $e) { $this->assertEquals( - \Magento\Framework\DB\Adapter\AdapterInterface::ERROR_ROLLBACK_INCOMPLETE_MESSAGE, + AdapterInterface::ERROR_ROLLBACK_INCOMPLETE_MESSAGE, $e->getMessage() ); $this->_adapter->rollBack(); @@ -549,4 +551,28 @@ class MysqlTest extends \PHPUnit_Framework_TestCase ] ]; } + + /** + * @dataProvider getIndexNameDataProvider + */ + public function testGetIndexName($name, $fields, $indexType, $expectedName) + { + $resultIndexName = $this->_mockAdapter->getIndexName($name, $fields, $indexType); + $this->assertTrue( + strpos($resultIndexName, $expectedName) === 0, + "Index name '$resultIndexName' did not begin with expected value '$expectedName'" + ); + } + + public function getIndexNameDataProvider() + { + // 65 characters long - will be compressed + $longTableName = '__________________________________________________long_table_name'; + return [ + [$longTableName, [], AdapterInterface::INDEX_TYPE_UNIQUE, 'UNQ_'], + [$longTableName, [], AdapterInterface::INDEX_TYPE_FULLTEXT, 'FTI_'], + [$longTableName, [], AdapterInterface::INDEX_TYPE_INDEX, 'IDX_'], + ['short_table_name', ['field1', 'field2'], '', 'SHORT_TABLE_NAME_FIELD1_FIELD2'], + ]; + } } diff --git a/lib/internal/Magento/Framework/DB/Test/Unit/ExpressionConverterTest.php b/lib/internal/Magento/Framework/DB/Test/Unit/ExpressionConverterTest.php new file mode 100644 index 0000000000000000000000000000000000000000..a184d7395918a4533cbb1462e5ab3592a9f84ed5 --- /dev/null +++ b/lib/internal/Magento/Framework/DB/Test/Unit/ExpressionConverterTest.php @@ -0,0 +1,57 @@ +<?php +/*** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ + +namespace Magento\Framework\DB\Test\Unit; + + +use Magento\Framework\DB\ExpressionConverter; + +class ExpressionConverterTest extends \PHPUnit_Framework_TestCase +{ + /** + * @dataProvider shortenEntityNameDataProvider + */ + public function testShortenEntityName($in, $prefix, $expectedOut) + { + $resultEntityName = ExpressionConverter::shortenEntityName($in, $prefix); + $this->assertTrue( + strpos($resultEntityName, $expectedOut) === 0, + "Entity name '$resultEntityName' did not begin with expected value '$expectedOut'" + ); + } + + public function shortenEntityNameDataProvider() + { + $length64 = '________________________________________________________________'; + $length40 = '________________________________________'; + return [ + 'Short identifier' => [ + 'already_short', + 'pre_', + 'already_short' + ], + 'Hashed identifer' => [ + $length64 . '_cannotBeAbbreviated', + 'pre_', + 'pre_' + ], + 'Abbreviated identifier' => [ + $length40 . 'enterprise_notification_index', + 'pre_', + $length40 . 'ent_ntfc_idx' + ], + ]; + } + + public function testShortenEntityNameReducedHash() + { + /** Length of 64 characters, to go over max MySql identifier length */ + $length64 = '________________________________________________________________'; + $longPrefix = 'pre_____________________________________'; + $shortenedName = ExpressionConverter::shortenEntityName($length64 . '_cannotBeAbbreviated', $longPrefix); + $this->assertNotSame(0, strpos($shortenedName, 'pre'), 'Entity name not supposed to with long prefix'); + } +} diff --git a/lib/internal/Magento/Framework/Mview/Test/Unit/View/SubscriptionTest.php b/lib/internal/Magento/Framework/Mview/Test/Unit/View/SubscriptionTest.php index 8b36902a699e2f0f56c397a9e787651c07faeb06..f9b642136422dd229deebd9762f183742646c698 100644 --- a/lib/internal/Magento/Framework/Mview/Test/Unit/View/SubscriptionTest.php +++ b/lib/internal/Magento/Framework/Mview/Test/Unit/View/SubscriptionTest.php @@ -12,11 +12,6 @@ use \Magento\Framework\Mview\View\Subscription; class SubscriptionTest extends \PHPUnit_Framework_TestCase { - /** - * @var \Magento\Framework\Mview\View\Subscription - */ - protected $model; - /** * Mysql PDO DB adapter mock * @@ -24,34 +19,37 @@ class SubscriptionTest extends \PHPUnit_Framework_TestCase */ protected $connectionMock; - /** - * @var \PHPUnit_Framework_MockObject_MockObject|\Magento\Framework\App\Resource - */ + /** @var \Magento\Framework\Mview\View\Subscription */ + protected $model; + + /** @var \PHPUnit_Framework_MockObject_MockObject|\Magento\Framework\App\Resource */ protected $resourceMock; - /** - * @var \PHPUnit_Framework_MockObject_MockObject|\Magento\Framework\DB\Ddl\TriggerFactory - */ + /** @var \PHPUnit_Framework_MockObject_MockObject|\Magento\Framework\DB\Ddl\TriggerFactory */ protected $triggerFactoryMock; - /** - * @var \PHPUnit_Framework_MockObject_MockObject|\Magento\Framework\Mview\View\CollectionInterface - */ + /** @var \PHPUnit_Framework_MockObject_MockObject|\Magento\Framework\Mview\View\CollectionInterface */ protected $viewCollectionMock; - /** - * @var \PHPUnit_Framework_MockObject_MockObject|\Magento\Framework\Mview\ViewInterface - */ + /** @var \PHPUnit_Framework_MockObject_MockObject|\Magento\Framework\Mview\ViewInterface */ protected $viewMock; + /** @var string */ + private $tableName; + protected function setUp() { $this->connectionMock = $this->getMock('Magento\Framework\DB\Adapter\Pdo\Mysql', [], [], '', false); + $this->resourceMock = $this->getMock('Magento\Framework\App\Resource', [], [], '', false, false); + + $this->connectionMock->expects($this->any()) + ->method('quoteIdentifier') + ->will($this->returnArgument(0)); + + $this->resourceMock->expects($this->atLeastOnce()) + ->method('getConnection') + ->willReturn($this->connectionMock); - $this->resourceMock = $this->getMock( - 'Magento\Framework\App\Resource', ['getConnection', 'getTableName'], [], '', false, false - ); - $this->mockGetConnection($this->connectionMock); $this->triggerFactoryMock = $this->getMock( 'Magento\Framework\DB\Ddl\TriggerFactory', [], [], '', false, false ); @@ -62,16 +60,16 @@ class SubscriptionTest extends \PHPUnit_Framework_TestCase 'Magento\Framework\Mview\ViewInterface', [], '', false, false, true, [] ); - $this->connectionMock->expects($this->any()) - ->method('quoteIdentifier') - ->will($this->returnArgument(0)); + $this->resourceMock->expects($this->any()) + ->method('getTableName') + ->willReturn($this->tableName); $this->model = new Subscription( $this->resourceMock, $this->triggerFactoryMock, $this->viewCollectionMock, $this->viewMock, - 'tableName', + $this->tableName, 'columnName' ); } @@ -83,7 +81,7 @@ class SubscriptionTest extends \PHPUnit_Framework_TestCase public function testGetTableName() { - $this->assertEquals('tableName', $this->model->getTableName()); + $this->assertEquals($this->tableName, $this->model->getTableName()); } public function testGetColumnName() @@ -93,11 +91,14 @@ class SubscriptionTest extends \PHPUnit_Framework_TestCase public function testCreate() { - $this->mockGetTableName(); - - $triggerMock = $this->getMock('Magento\Framework\DB\Ddl\Trigger', [], [], '', false, false); + $triggerName = 'trigger_name'; + $this->resourceMock->expects($this->atLeastOnce())->method('getTriggerName')->willReturn($triggerName); + $triggerMock = $this->getMockBuilder('Magento\Framework\DB\Ddl\Trigger') + ->disableOriginalConstructor() + ->getMock(); $triggerMock->expects($this->exactly(3)) ->method('setName') + ->with($triggerName) ->will($this->returnSelf()); $triggerMock->expects($this->exactly(3)) ->method('getName') @@ -111,7 +112,7 @@ class SubscriptionTest extends \PHPUnit_Framework_TestCase ->will($this->returnSelf()); $triggerMock->expects($this->exactly(3)) ->method('setTable') - ->with('tableName') + ->with($this->tableName) ->will($this->returnSelf()); $triggerMock->expects($this->exactly(6)) ->method('addStatement') @@ -153,7 +154,7 @@ class SubscriptionTest extends \PHPUnit_Framework_TestCase ->will($this->returnValue('other_id')); $otherViewMock->expects($this->exactly(1)) ->method('getSubscriptions') - ->will($this->returnValue([['name' => 'tableName'], ['name' => 'otherTableName']])); + ->will($this->returnValue([['name' => $this->tableName], ['name' => 'otherTableName']])); $otherViewMock->expects($this->exactly(3)) ->method('getChangelog') ->will($this->returnValue($otherChangelogMock)); @@ -182,8 +183,6 @@ class SubscriptionTest extends \PHPUnit_Framework_TestCase public function testRemove() { - $this->mockGetTableName(); - $triggerMock = $this->getMock('Magento\Framework\DB\Ddl\Trigger', [], [], '', false, false); $triggerMock->expects($this->exactly(3)) ->method('setName') @@ -200,7 +199,7 @@ class SubscriptionTest extends \PHPUnit_Framework_TestCase ->will($this->returnSelf()); $triggerMock->expects($this->exactly(3)) ->method('setTable') - ->with('tableName') + ->with($this->tableName) ->will($this->returnSelf()); $triggerMock->expects($this->exactly(3)) ->method('addStatement') @@ -228,7 +227,7 @@ class SubscriptionTest extends \PHPUnit_Framework_TestCase ->will($this->returnValue('other_id')); $otherViewMock->expects($this->exactly(1)) ->method('getSubscriptions') - ->will($this->returnValue([['name' => 'tableName'], ['name' => 'otherTableName']])); + ->will($this->returnValue([['name' => $this->tableName], ['name' => 'otherTableName']])); $otherViewMock->expects($this->exactly(3)) ->method('getChangelog') ->will($this->returnValue($otherChangelogMock)); @@ -259,21 +258,4 @@ class SubscriptionTest extends \PHPUnit_Framework_TestCase $this->model->remove(); } - - /** - * @param $connection - */ - protected function mockGetConnection($connection) - { - $this->resourceMock->expects($this->once()) - ->method('getConnection') - ->will($this->returnValue($connection)); - } - - protected function mockGetTableName() - { - $this->resourceMock->expects($this->any()) - ->method('getTableName') - ->will($this->returnArgument(0)); - } } diff --git a/lib/internal/Magento/Framework/Mview/View/Subscription.php b/lib/internal/Magento/Framework/Mview/View/Subscription.php index 498cb0e147801ef8709a89a13def616677662be3..e72c255d750ac85df31a1d4a9a1e8eb6e30d3c53 100644 --- a/lib/internal/Magento/Framework/Mview/View/Subscription.php +++ b/lib/internal/Magento/Framework/Mview/View/Subscription.php @@ -8,13 +8,11 @@ namespace Magento\Framework\Mview\View; +use Magento\Framework\App\Resource; +use Magento\Framework\DB\Ddl\Trigger; + class Subscription implements SubscriptionInterface { - /** - * Trigger name qualifier - */ - const TRIGGER_NAME_QUALIFIER = 'trg'; - /** * Database write connection * @@ -23,7 +21,7 @@ class Subscription implements SubscriptionInterface protected $write; /** - * @var \Magento\Framework\DB\Ddl\Trigger + * @var \Magento\Framework\DB\Ddl\TriggerFactory */ protected $triggerFactory; @@ -55,12 +53,12 @@ class Subscription implements SubscriptionInterface protected $linkedViews = []; /** - * @var \Magento\Framework\App\Resource + * @var Resource */ protected $resource; /** - * @param \Magento\Framework\App\Resource $resource + * @param Resource $resource * @param \Magento\Framework\DB\Ddl\TriggerFactory $triggerFactory * @param \Magento\Framework\Mview\View\CollectionInterface $viewCollection * @param \Magento\Framework\Mview\ViewInterface $view @@ -68,7 +66,7 @@ class Subscription implements SubscriptionInterface * @param string $columnName */ public function __construct( - \Magento\Framework\App\Resource $resource, + Resource $resource, \Magento\Framework\DB\Ddl\TriggerFactory $triggerFactory, \Magento\Framework\Mview\View\CollectionInterface $viewCollection, \Magento\Framework\Mview\ViewInterface $view, @@ -91,23 +89,14 @@ class Subscription implements SubscriptionInterface */ public function create() { - foreach (\Magento\Framework\DB\Ddl\Trigger::getListOfEvents() as $event) { - $triggerName = $this->getTriggerName( - $this->resource->getTableName($this->getTableName()), - \Magento\Framework\DB\Ddl\Trigger::TIME_AFTER, - $event - ); - - /** @var \Magento\Framework\DB\Ddl\Trigger $trigger */ - $trigger = $this->triggerFactory->create()->setName( - $triggerName - )->setTime( - \Magento\Framework\DB\Ddl\Trigger::TIME_AFTER - )->setEvent( - $event - )->setTable( - $this->resource->getTableName($this->getTableName()) - ); + foreach (Trigger::getListOfEvents() as $event) { + $triggerName = $this->getAfterEventTriggerName($event); + /** @var Trigger $trigger */ + $trigger = $this->triggerFactory->create() + ->setName($triggerName) + ->setTime(Trigger::TIME_AFTER) + ->setEvent($event) + ->setTable($this->resource->getTableName($this->tableName)); $trigger->addStatement($this->buildStatement($event, $this->getView()->getChangelog())); @@ -131,23 +120,14 @@ class Subscription implements SubscriptionInterface */ public function remove() { - foreach (\Magento\Framework\DB\Ddl\Trigger::getListOfEvents() as $event) { - $triggerName = $this->getTriggerName( - $this->resource->getTableName($this->getTableName()), - \Magento\Framework\DB\Ddl\Trigger::TIME_AFTER, - $event - ); - - /** @var \Magento\Framework\DB\Ddl\Trigger $trigger */ - $trigger = $this->triggerFactory->create()->setName( - $triggerName - )->setTime( - \Magento\Framework\DB\Ddl\Trigger::TIME_AFTER - )->setEvent( - $event - )->setTable( - $this->resource->getTableName($this->getTableName()) - ); + foreach (Trigger::getListOfEvents() as $event) { + $triggerName = $this->getAfterEventTriggerName($event); + /** @var Trigger $trigger */ + $trigger = $this->triggerFactory->create() + ->setName($triggerName) + ->setTime(Trigger::TIME_AFTER) + ->setEvent($event) + ->setTable($this->resource->getTableName($this->getTableName())); // Add statements for linked views foreach ($this->getLinkedViews() as $view) { @@ -204,8 +184,8 @@ class Subscription implements SubscriptionInterface protected function buildStatement($event, $changelog) { switch ($event) { - case \Magento\Framework\DB\Ddl\Trigger::EVENT_INSERT: - case \Magento\Framework\DB\Ddl\Trigger::EVENT_UPDATE: + case Trigger::EVENT_INSERT: + case Trigger::EVENT_UPDATE: return sprintf( "INSERT IGNORE INTO %s (%s) VALUES (NEW.%s);", $this->write->quoteIdentifier($this->resource->getTableName($changelog->getName())), @@ -213,7 +193,7 @@ class Subscription implements SubscriptionInterface $this->write->quoteIdentifier($this->getColumnName()) ); - case \Magento\Framework\DB\Ddl\Trigger::EVENT_DELETE: + case Trigger::EVENT_DELETE: return sprintf( "INSERT IGNORE INTO %s (%s) VALUES (OLD.%s);", $this->write->quoteIdentifier($this->resource->getTableName($changelog->getName())), @@ -227,25 +207,26 @@ class Subscription implements SubscriptionInterface } /** - * Retrieve trigger name + * Build an "after" event for the given table and event * - * Build a trigger name by concatenating trigger name prefix, table name, - * trigger time and trigger event. + * @param string $event The DB level event, like "update" or "insert" * - * @param string $tableName - * @param string $time - * @param string $event * @return string */ - protected function getTriggerName($tableName, $time, $event) + private function getAfterEventTriggerName($event) { - return self::TRIGGER_NAME_QUALIFIER . '_' . $tableName . '_' . $time . '_' . $event; + return $this->resource->getTriggerName( + $this->resource->getTableName($this->getTableName()), + Trigger::TIME_AFTER, + $event + ); } /** * Retrieve View related to subscription * * @return \Magento\Framework\Mview\ViewInterface + * @codeCoverageIgnore */ public function getView() { @@ -256,6 +237,7 @@ class Subscription implements SubscriptionInterface * Retrieve table name * * @return string + * @codeCoverageIgnore */ public function getTableName() { @@ -266,6 +248,7 @@ class Subscription implements SubscriptionInterface * Retrieve table column name * * @return string + * @codeCoverageIgnore */ public function getColumnName() {