Skip to content

Commit

Permalink
#131 WIP to convert the Db/Collections & Db/NestedSet classes to use …
Browse files Browse the repository at this point in the history
…Doctrine DBAL

This converts all functions that are required to make the tests in CollectionTest pass again
  • Loading branch information
extracts committed Dec 2, 2021
1 parent 3548f0c commit c5587c5
Show file tree
Hide file tree
Showing 4 changed files with 245 additions and 16 deletions.
85 changes: 85 additions & 0 deletions library/Opus/Db2/Collections.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
<?php

/**
* This file is part of OPUS. The software OPUS has been originally developed
* at the University of Stuttgart with funding from the German Research Net,
* the Federal Department of Higher Education and Research and the Ministry
* of Science, Research and the Arts of the State of Baden-Wuerttemberg.
*
* OPUS 4 is a complete rewrite of the original OPUS software and was developed
* by the Stuttgart University Library, the Library Service Center
* Baden-Wuerttemberg, the Cooperative Library Network Berlin-Brandenburg,
* the Saarland University and State Library, the Saxon State Library -
* Dresden State and University Library, the Bielefeld University Library and
* the University Library of Hamburg University of Technology with funding from
* the German Research Foundation and the European Regional Development Fund.
*
* LICENCE
* OPUS is free software; you can redistribute it and/or modify it under the
* terms of the GNU General Public License as published by the Free Software
* Foundation; either version 2 of the Licence, or any later version.
* OPUS is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
* FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
* details. You should have received a copy of the GNU General Public License
* along with OPUS; if not, write to the Free Software Foundation, Inc., 51
* Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
* @copyright Copyright (c) 2010-2018, OPUS 4 development team
* @license http://www.gnu.org/licenses/gpl.html General Public License
*/

namespace Opus\Db2;

/**
* Table gateway class to table 'collections'.
*/

class Collections extends NestedSet
{
/**
* Table name of the nested set table.
*
* @var string
*/
protected $name = 'collections';

/**
* Table column holding the primary key for the nested set structure.
*
* @var string
*/
protected $primary = 'id';

/**
* Table column holding the left-id for the nested set structure.
*
* @var string
*/
protected $left = 'left_id';

/**
* Table column holding the right-id for the nested set structure.
*
* @var string
*/
protected $right = 'right_id';

/**
* Table column holding the parent-id for the structure. This actually is
* more than a nested set structure, but we need this for fast retrieval of
* one nodes' children.
*
* @var string
*/
protected $parent = 'parent_id';

/**
* Table column holding the tree-id for the structure. We're holding more
* than one nested-set structure in the table and we're distinguishing the
* different trees by this ID.
*
* @var string
*/
protected $tree = 'role_id';
}
152 changes: 152 additions & 0 deletions library/Opus/Db2/NestedSet.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,152 @@
<?php

/**
* This file is part of OPUS. The software OPUS has been originally developed
* at the University of Stuttgart with funding from the German Research Net,
* the Federal Department of Higher Education and Research and the Ministry
* of Science, Research and the Arts of the State of Baden-Wuerttemberg.
*
* OPUS 4 is a complete rewrite of the original OPUS software and was developed
* by the Stuttgart University Library, the Library Service Center
* Baden-Wuerttemberg, the Cooperative Library Network Berlin-Brandenburg,
* the Saarland University and State Library, the Saxon State Library -
* Dresden State and University Library, the Bielefeld University Library and
* the University Library of Hamburg University of Technology with funding from
* the German Research Foundation and the European Regional Development Fund.
*
* LICENCE
* OPUS is free software; you can redistribute it and/or modify it under the
* terms of the GNU General Public License as published by the Free Software
* Foundation; either version 2 of the Licence, or any later version.
* OPUS is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
* FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
* details. You should have received a copy of the GNU General Public License
* along with OPUS; if not, write to the Free Software Foundation, Inc., 51
* Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
* @copyright Copyright (c) 2020, OPUS 4 development team
* @license http://www.gnu.org/licenses/gpl.html General Public License
*/

namespace Opus\Db2;

use Doctrine\DBAL\Query\QueryBuilder;
use Opus\Model\ModelException;

/**
* Table gateway class to nested sets.
*
* WARNING: This class does not use transactions. If you want to be transaction
* WARNING: safe, beginTransaction() before using methods from here and commit()
* WARNING: when you're done.
*
* ANOTHER WARNING: Always make sure, $treeId, $id and all the parameters you
* ANOTHER WARNING: are clean. Currently, we assume that tree_id and id are
* ANOTHER WARNING: integer datatypes and explicitly cast to int. This might
* ANOTHER WARNING: result in strange behaviour, if you're not using integers
* ANOTHER WARNING: or submitting NULL values.
*
* TODO Reevaluate above warnings
*
* phpcs:disable
*/
abstract class NestedSet extends AbstractTableGateway
{
/**
* Returns the row data for the node of the given ID.
*
* @param int $id Primary key of the node.
* @throws ModelException
* @return array
*/
public function getNodeById($id)
{
$select = $this->selectNodeById($id);
$row = $select->execute()->fetchAssociative();

if ($row === null) {
throw new ModelException("Node $id not found.");
}

return $row;
}

/**
* Returns an SQL query builder instance preconfigured with an SQL statement
* for retrieving nodes by ID.
*
* @param int $id Primary key of the node.
* @return QueryBuilder
*/
private function selectNodeById($id)
{
$queryBuilder = $this->getQueryBuilder();

$select = $queryBuilder
->select('*')
->from($this->name, 'node')
->where("node.{$this->primary} = ?");

return $select->setParameters([$id]);
}

/**
* Returns the row data for all child nodes of the node with given ID.
*
* @param int $id The ID of the node whose children shall be returned.
* @return array
*/
public function getChildrenById($id)
{
$select = $this->selectChildrenById($id, 'id');

return $select->execute()->fetchAllAssociative();
}

/**
* Returns an SQL query builder instance preconfigured with an SQL statement
* for fetching all children of the node with the given ID. A second
* parameter allows the selection of the returned columns in the same format
* as \QueryBuilder::select() takes.
*
* @param int $id The ID of the parent node.
* @param mixed $cols The columns to show, defaults to '*'.
*
* @return QueryBuilder
*/
public function selectChildrenById($id, $cols = '*')
{
$queryBuilder = $this->getQueryBuilder();

$select = $queryBuilder
->select($cols)
->from($this->name, 'node')
->where("node.{$this->parent} = ?")
->orderBy("node.{$this->left}", "ASC");

return $select->setParameters([$id]);
}

/**
* Returns the row data for all nodes with the given tree ID. Returns null
* if nothing was found.
*
* @param int $treeId The ID of the nested-set structure whose nodes shall be returned.
* @return array|null
*/
public function getNodesByTreeId($treeId)
{
$queryBuilder = $this->getQueryBuilder();

$select = $queryBuilder
->select('*')
->from($this->name)
->where("{$this->tree} = ?")
->orderBy("{$this->left}", "ASC");

$select->setParameters([$treeId]);

return $queryBuilder->execute()->fetchAllAssociative();
}
}
10 changes: 4 additions & 6 deletions tests/Opus/CollectionTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@
use Opus\Collection;
use Opus\CollectionRole;
use Opus\Config;
use Opus\Db\Collections;
use Opus\Db2\Collections;
use Opus\Document;
use Opus\Model\NotFoundException;
use Opus\Model\Xml\Cache;
Expand Down Expand Up @@ -1235,14 +1235,12 @@ protected function validateNestedSet()
{
$table = new Collections();

$select = $table->select()->where('role_id = ?', 1)->order('left_id ASC');

$rows = $table->fetchAll($select);
$rows = $table->getNodesByTreeId(1);

$this->assertEquals(14, count($rows));

$this->assertEquals(1, $rows[0]->left_id);
$this->assertEquals(28, $rows[0]->right_id);
$this->assertEquals(1, $rows[0]["left_id"]);
$this->assertEquals(28, $rows[0]["right_id"]);

$validator = new NestedSetValidator($table);

Expand Down
14 changes: 4 additions & 10 deletions tests/Opus/TestAsset/NestedSetValidator.php
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@

namespace OpusTest\TestAsset;

use Opus\Db\NestedSet;
use Opus\Db2\NestedSet;
use Opus\LoggingTrait;
use Opus\Model\ModelException;

Expand Down Expand Up @@ -81,8 +81,7 @@ public function __construct($table)
*/
public function validate($rootId)
{
$select = $this->table->select()->where('id = ?', $rootId);
$node = $this->table->fetchRow($select);
$node = $this->table->getNodeById($rootId);
$this->counter = (int) $node['left_id'];
return $this->validateNode($rootId); // root node
}
Expand All @@ -97,8 +96,7 @@ public function validateNode($nodeId)
{
$logger = $this->getLogger();

$select = $this->table->select()->where('id = ?', $nodeId);
$node = $this->table->fetchRow($select);
$node = $this->table->getNodeById($nodeId);
$leftId = $node['left_id'];
$rightId = $node['right_id'];

Expand All @@ -121,11 +119,7 @@ public function validateNode($nodeId)
// node
if ($distance & 1) {
// odd; valid
$selectChildren = $this->table->select()->where(
'parent_id = ?',
$nodeId
)->order('left_id ASC');
$children = $this->table->fetchAll($selectChildren);
$children = $this->table->getChildrenById($nodeId);
foreach ($children as $child) {
if ($this->validateNode($child['id']) === false) {
return false;
Expand Down

0 comments on commit c5587c5

Please sign in to comment.