From 35622922f6f1d3a76baedcb4e7cc5f508836c1ca Mon Sep 17 00:00:00 2001 From: Kim Pepper Date: Mon, 5 Dec 2016 17:43:19 +1100 Subject: [PATCH 1/7] [#42387] Split out schema creation --- src/NestedSetSchemaInterface.php | 20 +++++++++++ src/Storage/BaseDbalStorage.php | 47 ++++++++++++++++++++++++++ src/Storage/DbalNestedSet.php | 37 +------------------- src/Storage/DbalNestedSetSchema.php | 41 ++++++++++++++++++++++ tests/Functional/DbalNestedSetTest.php | 40 ++++++---------------- 5 files changed, 120 insertions(+), 65 deletions(-) create mode 100644 src/NestedSetSchemaInterface.php create mode 100644 src/Storage/BaseDbalStorage.php create mode 100644 src/Storage/DbalNestedSetSchema.php diff --git a/src/NestedSetSchemaInterface.php b/src/NestedSetSchemaInterface.php new file mode 100644 index 00000000..eec6efc0 --- /dev/null +++ b/src/NestedSetSchemaInterface.php @@ -0,0 +1,20 @@ +connection = $connection; + if (!preg_match(self::VALID_TABLE_REGEX, $tableName)) { + throw new \InvalidArgumentException("Table name must match the regex " . self::VALID_TABLE_REGEX); + } + $this->tableName = $tableName; + } + +} diff --git a/src/Storage/DbalNestedSet.php b/src/Storage/DbalNestedSet.php index d19c9eeb..f981f5d7 100644 --- a/src/Storage/DbalNestedSet.php +++ b/src/Storage/DbalNestedSet.php @@ -10,42 +10,7 @@ /** * Provides a DBAL implementation of a Tree. */ -class DbalNestedSet implements NestedSetInterface { - - /** - * The regex for validating table names. - */ - const VALID_TABLE_REGEX = '/^[a-zA-Z]\w{1,64}$/'; - - /** - * The database connection. - * - * @var \Doctrine\DBAL\Connection - */ - protected $connection; - - /** - * The table name to use for storing the nested set. - * - * @var string - */ - protected $tableName; - - /** - * DbalTree constructor. - * - * @param \Doctrine\DBAL\Connection $connection - * The database connection. - * @param string $tableName - * (optional) The table name to use. - */ - public function __construct(Connection $connection, $tableName = 'tree') { - $this->connection = $connection; - if (!preg_match(self::VALID_TABLE_REGEX, $tableName)) { - throw new \InvalidArgumentException("Table name must match the regex " . self::VALID_TABLE_REGEX); - } - $this->tableName = $tableName; - } +class DbalNestedSet extends BaseDbalStorage implements NestedSetInterface { /** * {@inheritdoc} diff --git a/src/Storage/DbalNestedSetSchema.php b/src/Storage/DbalNestedSetSchema.php new file mode 100644 index 00000000..cf0b00af --- /dev/null +++ b/src/Storage/DbalNestedSetSchema.php @@ -0,0 +1,41 @@ +createTable($this->tableName); + $tree->addColumn("id", "integer", ["unsigned" => TRUE]); + $tree->addColumn("revision_id", "integer", ["unsigned" => TRUE]); + $tree->addColumn("left_pos", "integer", ["unsigned" => TRUE]); + $tree->addColumn("right_pos", "integer", ["unsigned" => TRUE]); + $tree->addColumn("depth", "integer", ["unsigned" => TRUE]); + + foreach ($schema->toSql($this->connection->getDatabasePlatform()) as $sql) { + $this->connection->exec($sql); + } + } + + /** + * {@inheritdoc} + */ + public function dropTable() { + $schema = new Schema(); + $schema->dropTable("tree"); + foreach ($schema->toSql($this->connection->getDatabasePlatform()) as $sql) { + $this->connection->exec($sql); + } + } + +} diff --git a/tests/Functional/DbalNestedSetTest.php b/tests/Functional/DbalNestedSetTest.php index 4ab8152a..363f0920 100644 --- a/tests/Functional/DbalNestedSetTest.php +++ b/tests/Functional/DbalNestedSetTest.php @@ -8,6 +8,7 @@ use Doctrine\DBAL\Schema\Schema; use PNX\NestedSet\Node; use PNX\NestedSet\Storage\DbalNestedSet; +use PNX\NestedSet\Storage\DbalNestedSetSchema; /** * Tests the Dbal Tree implementation. @@ -37,6 +38,13 @@ class DbalNestedSetTest extends \PHPUnit_Framework_TestCase { */ protected $tableName = 'nested_set'; + /** + * The nested set schema. + * + * @var \PNX\NestedSet\Storage\DbalNestedSetSchema + */ + protected $schema; + /** * {@inheritdoc} */ @@ -45,7 +53,9 @@ protected function setUp() { $this->connection = DriverManager::getConnection([ 'url' => 'sqlite:///:memory:', ], new Configuration()); - $this->createTable(); + + $this->schema = new DbalNestedSetSchema($this->connection, $this->tableName); + $this->schema->createTable(); $this->loadTestData(); $this->nestedSet = new DbalNestedSet($this->connection, $this->tableName); } @@ -423,34 +433,6 @@ public function testValidateTableInvalidFirstChars() { $this->nestedSet = new DbalNestedSet($this->connection, "1abc"); } - /** - * Drops the table. - */ - protected function dropTable() { - $schema = new Schema(); - $schema->dropTable("tree"); - foreach ($schema->toSql($this->connection->getDatabasePlatform()) as $sql) { - $this->connection->exec($sql); - } - } - - /** - * Creates the table. - */ - protected function createTable() { - $schema = new Schema(); - $tree = $schema->createTable($this->tableName); - $tree->addColumn("id", "integer", ["unsigned" => TRUE]); - $tree->addColumn("revision_id", "integer", ["unsigned" => TRUE]); - $tree->addColumn("left_pos", "integer", ["unsigned" => TRUE]); - $tree->addColumn("right_pos", "integer", ["unsigned" => TRUE]); - $tree->addColumn("depth", "integer", ["unsigned" => TRUE]); - - foreach ($schema->toSql($this->connection->getDatabasePlatform()) as $sql) { - $this->connection->exec($sql); - } - } - /** * Loads the test data. */ From 23d67961b64549394d566ec303269b765b7150a3 Mon Sep 17 00:00:00 2001 From: Kim Pepper Date: Mon, 5 Dec 2016 17:49:32 +1100 Subject: [PATCH 2/7] Alway create a new in memory db --- src/Storage/DbalNestedSetSchema.php | 2 +- tests/Functional/DbalNestedSetTest.php | 18 ++++++++---------- 2 files changed, 9 insertions(+), 11 deletions(-) diff --git a/src/Storage/DbalNestedSetSchema.php b/src/Storage/DbalNestedSetSchema.php index cf0b00af..570199f8 100644 --- a/src/Storage/DbalNestedSetSchema.php +++ b/src/Storage/DbalNestedSetSchema.php @@ -32,7 +32,7 @@ public function createTable() { */ public function dropTable() { $schema = new Schema(); - $schema->dropTable("tree"); + $schema->dropTable($this->tableName); foreach ($schema->toSql($this->connection->getDatabasePlatform()) as $sql) { $this->connection->exec($sql); } diff --git a/tests/Functional/DbalNestedSetTest.php b/tests/Functional/DbalNestedSetTest.php index 363f0920..d21b1145 100644 --- a/tests/Functional/DbalNestedSetTest.php +++ b/tests/Functional/DbalNestedSetTest.php @@ -49,16 +49,14 @@ class DbalNestedSetTest extends \PHPUnit_Framework_TestCase { * {@inheritdoc} */ protected function setUp() { - if ($this->connection === NULL) { - $this->connection = DriverManager::getConnection([ - 'url' => 'sqlite:///:memory:', - ], new Configuration()); - - $this->schema = new DbalNestedSetSchema($this->connection, $this->tableName); - $this->schema->createTable(); - $this->loadTestData(); - $this->nestedSet = new DbalNestedSet($this->connection, $this->tableName); - } + $this->connection = DriverManager::getConnection([ + 'url' => 'sqlite:///:memory:', + ], new Configuration()); + + $this->schema = new DbalNestedSetSchema($this->connection, $this->tableName); + $this->schema->createTable(); + $this->loadTestData(); + $this->nestedSet = new DbalNestedSet($this->connection, $this->tableName); } /** From 74818c5633649f710430426429312233f07826b9 Mon Sep 17 00:00:00 2001 From: Kim Pepper Date: Mon, 5 Dec 2016 17:55:51 +1100 Subject: [PATCH 3/7] Adds indexes --- src/Storage/DbalNestedSet.php | 4 ++-- src/Storage/DbalNestedSetSchema.php | 5 +++++ 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/src/Storage/DbalNestedSet.php b/src/Storage/DbalNestedSet.php index f981f5d7..c004118b 100644 --- a/src/Storage/DbalNestedSet.php +++ b/src/Storage/DbalNestedSet.php @@ -134,10 +134,10 @@ public function findDescendants(Node $node, $depth = 0) { $query->select('child.id', 'child.revision_id', 'child.left_pos', 'child.right_pos', 'child.depth') ->from($this->tableName, 'child') ->from($this->tableName, 'parent') - ->where('child.left_pos > parent.left_pos') - ->andWhere('child.right_pos < parent.right_pos') ->andWhere('parent.id = :id') ->andWhere('parent.revision_id = :revision_id') + ->andwhere('child.left_pos > parent.left_pos') + ->andWhere('child.right_pos < parent.right_pos') ->setParameter(':id', $node->getId()) ->setParameter(':revision_id', $node->getRevisionId()); if ($depth > 0) { diff --git a/src/Storage/DbalNestedSetSchema.php b/src/Storage/DbalNestedSetSchema.php index 570199f8..8e7e3eed 100644 --- a/src/Storage/DbalNestedSetSchema.php +++ b/src/Storage/DbalNestedSetSchema.php @@ -22,6 +22,11 @@ public function createTable() { $tree->addColumn("right_pos", "integer", ["unsigned" => TRUE]); $tree->addColumn("depth", "integer", ["unsigned" => TRUE]); + $tree->setPrimaryKey(['id', 'revision_id']); + $tree->addIndex(['id', 'revision_id', 'left_pos', 'right_pos', 'depth']); + $tree->addIndex(['left_pos', 'right_pos']); + $tree->addIndex(['right_pos']); + foreach ($schema->toSql($this->connection->getDatabasePlatform()) as $sql) { $this->connection->exec($sql); } From c31f08f55a169ba68db9aa10d4511bc3522403c5 Mon Sep 17 00:00:00 2001 From: Kim Pepper Date: Tue, 6 Dec 2016 08:54:36 +1100 Subject: [PATCH 4/7] Split out validate function --- src/Storage/BaseDbalStorage.php | 20 +++++++++++++++++++- 1 file changed, 19 insertions(+), 1 deletion(-) diff --git a/src/Storage/BaseDbalStorage.php b/src/Storage/BaseDbalStorage.php index a9f5bd89..0de05ae9 100644 --- a/src/Storage/BaseDbalStorage.php +++ b/src/Storage/BaseDbalStorage.php @@ -38,10 +38,28 @@ abstract class BaseDbalStorage { */ public function __construct(Connection $connection, $tableName = 'tree') { $this->connection = $connection; - if (!preg_match(self::VALID_TABLE_REGEX, $tableName)) { + if (!$this->validTableName($tableName)) { throw new \InvalidArgumentException("Table name must match the regex " . self::VALID_TABLE_REGEX); } $this->tableName = $tableName; } + /** + * Checks if the table name is valid. + * + * Table names must: + * - start with a letter + * - only contain letters, numbers, and underscores + * - be maximum 64 characters. + * + * @param string $tableName + * The table name. + * + * @return bool + * TRUE if the table name is valid. + */ + protected function validTableName($tableName) { + return (bool) preg_match(self::VALID_TABLE_REGEX, $tableName); + } + } From e29de2ce36cceb2353ccd739e75c26c67aaebcf7 Mon Sep 17 00:00:00 2001 From: Kim Pepper Date: Tue, 6 Dec 2016 08:55:24 +1100 Subject: [PATCH 5/7] Remove unused imports --- src/Storage/DbalNestedSet.php | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/Storage/DbalNestedSet.php b/src/Storage/DbalNestedSet.php index c004118b..ef6d1785 100644 --- a/src/Storage/DbalNestedSet.php +++ b/src/Storage/DbalNestedSet.php @@ -2,10 +2,9 @@ namespace PNX\NestedSet\Storage; -use Doctrine\DBAL\Connection; use Exception; -use PNX\NestedSet\Node; use PNX\NestedSet\NestedSetInterface; +use PNX\NestedSet\Node; /** * Provides a DBAL implementation of a Tree. From ac64b4d2785e75991e0a7fcdef1e77d853dd6f9d Mon Sep 17 00:00:00 2001 From: Kim Pepper Date: Tue, 6 Dec 2016 08:59:09 +1100 Subject: [PATCH 6/7] Rename create and drop schema --- src/NestedSetSchemaInterface.php | 4 ++-- src/Storage/DbalNestedSetSchema.php | 4 ++-- tests/Functional/DbalNestedSetTest.php | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/NestedSetSchemaInterface.php b/src/NestedSetSchemaInterface.php index eec6efc0..b9d7431d 100644 --- a/src/NestedSetSchemaInterface.php +++ b/src/NestedSetSchemaInterface.php @@ -10,11 +10,11 @@ interface NestedSetSchemaInterface { /** * Creates the nested set table. */ - public function createTable(); + public function create(); /** * Drops the nested set table. */ - public function dropTable(); + public function drop(); } diff --git a/src/Storage/DbalNestedSetSchema.php b/src/Storage/DbalNestedSetSchema.php index 8e7e3eed..d8e57b66 100644 --- a/src/Storage/DbalNestedSetSchema.php +++ b/src/Storage/DbalNestedSetSchema.php @@ -13,7 +13,7 @@ class DbalNestedSetSchema extends BaseDbalStorage implements NestedSetSchemaInte /** * {@inheritdoc} */ - public function createTable() { + public function create() { $schema = new Schema(); $tree = $schema->createTable($this->tableName); $tree->addColumn("id", "integer", ["unsigned" => TRUE]); @@ -35,7 +35,7 @@ public function createTable() { /** * {@inheritdoc} */ - public function dropTable() { + public function drop() { $schema = new Schema(); $schema->dropTable($this->tableName); foreach ($schema->toSql($this->connection->getDatabasePlatform()) as $sql) { diff --git a/tests/Functional/DbalNestedSetTest.php b/tests/Functional/DbalNestedSetTest.php index d21b1145..e381eefd 100644 --- a/tests/Functional/DbalNestedSetTest.php +++ b/tests/Functional/DbalNestedSetTest.php @@ -54,7 +54,7 @@ protected function setUp() { ], new Configuration()); $this->schema = new DbalNestedSetSchema($this->connection, $this->tableName); - $this->schema->createTable(); + $this->schema->create(); $this->loadTestData(); $this->nestedSet = new DbalNestedSet($this->connection, $this->tableName); } From c44bc88c18094e4feef3ca13f94bcfd58e9bd387 Mon Sep 17 00:00:00 2001 From: Kim Pepper Date: Tue, 6 Dec 2016 09:00:23 +1100 Subject: [PATCH 7/7] Optimise imports --- src/Storage/BaseDbalStorage.php | 2 +- tests/Functional/DbalNestedSetTest.php | 1 - 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/src/Storage/BaseDbalStorage.php b/src/Storage/BaseDbalStorage.php index 0de05ae9..f1d131e3 100644 --- a/src/Storage/BaseDbalStorage.php +++ b/src/Storage/BaseDbalStorage.php @@ -2,7 +2,7 @@ namespace PNX\NestedSet\Storage; -use \Doctrine\DBAL\Connection; +use Doctrine\DBAL\Connection; /** * Abstract base class for DBAL storage classes. diff --git a/tests/Functional/DbalNestedSetTest.php b/tests/Functional/DbalNestedSetTest.php index e381eefd..65b794e1 100644 --- a/tests/Functional/DbalNestedSetTest.php +++ b/tests/Functional/DbalNestedSetTest.php @@ -5,7 +5,6 @@ use Console_Table; use Doctrine\DBAL\Configuration; use Doctrine\DBAL\DriverManager; -use Doctrine\DBAL\Schema\Schema; use PNX\NestedSet\Node; use PNX\NestedSet\Storage\DbalNestedSet; use PNX\NestedSet\Storage\DbalNestedSetSchema;