Included vendor/ to the project

This commit is contained in:
2017-09-13 09:35:32 +07:00
parent e72205ff09
commit 17f1643875
2483 changed files with 179073 additions and 0 deletions

View File

@@ -0,0 +1,157 @@
<?php
/*
* This file is part of DbUnit.
*
* (c) Sebastian Bergmann <sebastian@phpunit.de>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace PHPUnit\DbUnit;
use PHPUnit\DbUnit\Database\Connection;
use PHPUnit\DbUnit\DataSet\IDataSet;
use PHPUnit\DbUnit\Operation\Factory;
use PHPUnit\DbUnit\Operation\Operation;
/**
* Can be used as a foundation for new DatabaseTesters.
*/
abstract class AbstractTester implements Tester
{
/**
* @var Operation
*/
protected $setUpOperation;
/**
* @var Operation
*/
protected $tearDownOperation;
/**
* @var IDataSet
*/
protected $dataSet;
/**
* @var string
*/
protected $schema;
/**
* Creates a new database tester.
*/
public function __construct()
{
$this->setUpOperation = Factory::CLEAN_INSERT();
$this->tearDownOperation = Factory::NONE();
}
/**
* Closes the specified connection.
*
* @param Connection $connection
*/
public function closeConnection(Connection $connection)
{
$connection->close();
}
/**
* Returns the test dataset.
*
* @return IDataSet
*/
public function getDataSet()
{
return $this->dataSet;
}
/**
* TestCases must call this method inside setUp().
*/
public function onSetUp()
{
$this->getSetUpOperation()->execute($this->getConnection(), $this->getDataSet());
}
/**
* TestCases must call this method inside tearDown().
*/
public function onTearDown()
{
$this->getTearDownOperation()->execute($this->getConnection(), $this->getDataSet());
}
/**
* Sets the test dataset to use.
*
* @param IDataSet $dataSet
*/
public function setDataSet(IDataSet $dataSet)
{
$this->dataSet = $dataSet;
}
/**
* Sets the schema value.
*
* @param string $schema
*/
public function setSchema($schema)
{
$this->schema = $schema;
}
/**
* Sets the DatabaseOperation to call when starting the test.
*
* @param Operation $setUpOperation
*/
public function setSetUpOperation(Operation $setUpOperation)
{
$this->setUpOperation = $setUpOperation;
}
/**
* Sets the DatabaseOperation to call when ending the test.
*
* @param Operation $tearDownOperation
*/
public function setTearDownOperation(Operation $tearDownOperation)
{
$this->tearDownOperation = $tearDownOperation;
}
/**
* Returns the schema value
*
* @return string
*/
protected function getSchema()
{
return $this->schema;
}
/**
* Returns the database operation that will be called when starting the test.
*
* @return Operation
*/
protected function getSetUpOperation()
{
return $this->setUpOperation;
}
/**
* Returns the database operation that will be called when ending the test.
*
* @return Operation
*/
protected function getTearDownOperation()
{
return $this->tearDownOperation;
}
}

View File

@@ -0,0 +1,90 @@
<?php
/*
* This file is part of DbUnit.
*
* (c) Sebastian Bergmann <sebastian@phpunit.de>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace PHPUnit\DbUnit\Constraint;
use PHPUnit\DbUnit\DataSet\IDataSet;
use PHPUnit\DbUnit\InvalidArgumentException;
use PHPUnit\Framework\Constraint\Constraint;
/**
* Asserts whether or not two dbunit datasets are equal.
*/
class DataSetIsEqual extends Constraint
{
/**
* @var IDataSet
*/
protected $value;
/**
* @var string
*/
protected $failure_reason;
/**
* Creates a new constraint.
*
* @param IDataSet $value
*/
public function __construct(IDataSet $value)
{
parent::__construct();
$this->value = $value;
}
/**
* Evaluates the constraint for parameter $other. Returns TRUE if the
* constraint is met, FALSE otherwise.
*
* This method can be overridden to implement the evaluation algorithm.
*
* @param mixed $other Value or object to evaluate.
*
* @return bool
*/
protected function matches($other)
{
if (!$other instanceof IDataSet) {
throw new InvalidArgumentException(
'PHPUnit_Extensions_Database_DataSet_IDataSet expected'
);
}
return $this->value->matches($other);
}
/**
* Returns the description of the failure
*
* The beginning of failure messages is "Failed asserting that" in most
* cases. This method should return the second part of that sentence.
*
* @param mixed $other Evaluated value or object.
*
* @return string
*/
protected function failureDescription($other)
{
return $other->__toString() . ' ' . $this->toString();
}
/**
* Returns a string representation of the constraint.
*
* @return string
*/
public function toString()
{
return sprintf(
'is equal to expected %s', $this->value->__toString()
);
}
}

View File

@@ -0,0 +1,90 @@
<?php
/*
* This file is part of DbUnit.
*
* (c) Sebastian Bergmann <sebastian@phpunit.de>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace PHPUnit\DbUnit\Constraint;
use PHPUnit\DbUnit\DataSet\ITable;
use PHPUnit\DbUnit\InvalidArgumentException;
use PHPUnit\Framework\Constraint\Constraint;
/**
* Asserts whether or not two dbunit tables are equal.
*/
class TableIsEqual extends Constraint
{
/**
* @var ITable
*/
protected $value;
/**
* @var string
*/
protected $failure_reason;
/**
* Creates a new constraint.
*
* @param ITable $value
*/
public function __construct(ITable $value)
{
parent::__construct();
$this->value = $value;
}
/**
* Evaluates the constraint for parameter $other. Returns TRUE if the
* constraint is met, FALSE otherwise.
*
* This method can be overridden to implement the evaluation algorithm.
*
* @param mixed $other Value or object to evaluate.
*
* @return bool
*/
protected function matches($other)
{
if (!$other instanceof ITable) {
throw new InvalidArgumentException(
'PHPUnit_Extensions_Database_DataSet_ITable expected'
);
}
return $this->value->matches($other);
}
/**
* Returns the description of the failure
*
* The beginning of failure messages is "Failed asserting that" in most
* cases. This method should return the second part of that sentence.
*
* @param mixed $other Evaluated value or object.
*
* @return string
*/
protected function failureDescription($other)
{
return $other->__toString() . ' ' . $this->toString();
}
/**
* Returns a string representation of the constraint.
*
* @return string
*/
public function toString()
{
return sprintf(
'is equal to expected %s', $this->value->__toString()
);
}
}

View File

@@ -0,0 +1,67 @@
<?php
/*
* This file is part of DbUnit.
*
* (c) Sebastian Bergmann <sebastian@phpunit.de>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace PHPUnit\DbUnit\Constraint;
use PHPUnit\Framework\Constraint\Constraint;
/**
* Asserts the row count in a table
*/
class TableRowCount extends Constraint
{
/**
* @var int
*/
protected $value;
/**
* @var string
*/
protected $tableName;
/**
* Creates a new constraint.
*
* @param $tableName
* @param $value
*/
public function __construct($tableName, $value)
{
parent::__construct();
$this->tableName = $tableName;
$this->value = $value;
}
/**
* Evaluates the constraint for parameter $other. Returns TRUE if the
* constraint is met, FALSE otherwise.
*
* This method can be overridden to implement the evaluation algorithm.
*
* @param mixed $other Value or object to evaluate.
*
* @return bool
*/
protected function matches($other)
{
return $other == $this->value;
}
/**
* Returns a string representation of the constraint.
*
* @return string
*/
public function toString()
{
return sprintf('is equal to expected row count %d', $this->value);
}
}

View File

@@ -0,0 +1,133 @@
<?php
/*
* This file is part of DbUnit.
*
* (c) Sebastian Bergmann <sebastian@phpunit.de>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace PHPUnit\DbUnit\DataSet;
/**
* Implements the basic functionality of data sets.
*/
abstract class AbstractDataSet implements IDataSet
{
/**
* Creates an iterator over the tables in the data set. If $reverse is
* true a reverse iterator will be returned.
*
* @param bool $reverse
*
* @return ITableIterator
*/
abstract protected function createIterator($reverse = false);
/**
* Returns an array of table names contained in the dataset.
*
* @return array
*/
public function getTableNames()
{
$tableNames = [];
foreach ($this->getIterator() as $table) {
/* @var $table ITable */
$tableNames[] = $table->getTableMetaData()->getTableName();
}
return $tableNames;
}
/**
* Returns a table meta data object for the given table.
*
* @param string $tableName
*
* @return ITableMetadata
*/
public function getTableMetaData($tableName)
{
return $this->getTable($tableName)->getTableMetaData();
}
/**
* Returns a table object for the given table.
*
* @param string $tableName
*
* @return ITable
*/
public function getTable($tableName)
{
foreach ($this->getIterator() as $table) {
/* @var $table ITable */
if ($table->getTableMetaData()->getTableName() == $tableName) {
return $table;
}
}
}
/**
* Returns an iterator for all table objects in the given dataset.
*
* @return ITableIterator
*/
public function getIterator()
{
return $this->createIterator();
}
/**
* Returns a reverse iterator for all table objects in the given dataset.
*
* @return ITableIterator
*/
public function getReverseIterator()
{
return $this->createIterator(true);
}
/**
* Asserts that the given data set matches this data set.
*
* @param IDataSet $other
*/
public function matches(IDataSet $other)
{
$thisTableNames = $this->getTableNames();
$otherTableNames = $other->getTableNames();
sort($thisTableNames);
sort($otherTableNames);
if ($thisTableNames != $otherTableNames) {
return false;
}
foreach ($thisTableNames as $tableName) {
$table = $this->getTable($tableName);
if (!$table->matches($other->getTable($tableName))) {
return false;
}
}
return true;
}
public function __toString()
{
$iterator = $this->getIterator();
$dataSetString = '';
foreach ($iterator as $table) {
$dataSetString .= $table->__toString();
}
return $dataSetString;
}
}

View File

@@ -0,0 +1,222 @@
<?php
/*
* This file is part of DbUnit.
*
* (c) Sebastian Bergmann <sebastian@phpunit.de>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace PHPUnit\DbUnit\DataSet;
use PHPUnit\DbUnit\InvalidArgumentException;
use SimpleXMLElement;
/**
* Provides a basic functionality for dbunit tables
*/
class AbstractTable implements ITable
{
/**
* @var ITableMetadata
*/
protected $tableMetaData;
/**
* A 2-dimensional array containing the data for this table.
*
* @var array
*/
protected $data;
/**
* @var ITable|null
*/
private $other;
/**
* Sets the metadata for this table.
*
* @param ITableMetadata $tableMetaData
*
* @deprecated
*/
protected function setTableMetaData(ITableMetadata $tableMetaData)
{
$this->tableMetaData = $tableMetaData;
}
/**
* Returns the table's meta data.
*
* @return ITableMetadata
*/
public function getTableMetaData()
{
return $this->tableMetaData;
}
/**
* Returns the number of rows in this table.
*
* @return int
*/
public function getRowCount()
{
return count($this->data);
}
/**
* Returns the value for the given column on the given row.
*
* @param int $row
* @param int $column
*
* @todo reorganize this function to throw the exception first.
*/
public function getValue($row, $column)
{
if (isset($this->data[$row][$column])) {
$value = $this->data[$row][$column];
return ($value instanceof SimpleXMLElement) ? (string) $value : $value;
} else {
if (!in_array($column, $this->getTableMetaData()->getColumns()) || $this->getRowCount() <= $row) {
throw new InvalidArgumentException("The given row ({$row}) and column ({$column}) do not exist in table {$this->getTableMetaData()->getTableName()}");
} else {
return;
}
}
}
/**
* Returns the an associative array keyed by columns for the given row.
*
* @param int $row
*
* @return array
*/
public function getRow($row)
{
if (isset($this->data[$row])) {
return $this->data[$row];
} else {
if ($this->getRowCount() <= $row) {
throw new InvalidArgumentException("The given row ({$row}) does not exist in table {$this->getTableMetaData()->getTableName()}");
} else {
return;
}
}
}
/**
* Asserts that the given table matches this table.
*
* @param ITable $other
*/
public function matches(ITable $other)
{
$thisMetaData = $this->getTableMetaData();
$otherMetaData = $other->getTableMetaData();
if (!$thisMetaData->matches($otherMetaData) ||
$this->getRowCount() != $other->getRowCount()
) {
return false;
}
$columns = $thisMetaData->getColumns();
$rowCount = $this->getRowCount();
for ($i = 0; $i < $rowCount; $i++) {
foreach ($columns as $columnName) {
$thisValue = $this->getValue($i, $columnName);
$otherValue = $other->getValue($i, $columnName);
if (is_numeric($thisValue) && is_numeric($otherValue)) {
if ($thisValue != $otherValue) {
$this->other = $other;
return false;
}
} elseif ($thisValue !== $otherValue) {
$this->other = $other;
return false;
}
}
}
return true;
}
/**
* Checks if a given row is in the table
*
* @param array $row
*
* @return bool
*/
public function assertContainsRow(array $row)
{
return in_array($row, $this->data);
}
public function __toString()
{
$columns = $this->getTableMetaData()->getColumns();
$lineSeperator = str_repeat('+----------------------', count($columns)) . "+\n";
$lineLength = strlen($lineSeperator) - 1;
$tableString = $lineSeperator;
$tableString .= '| ' . str_pad($this->getTableMetaData()->getTableName(), $lineLength - 4, ' ', STR_PAD_RIGHT) . " |\n";
$tableString .= $lineSeperator;
$tableString .= $this->rowToString($columns);
$tableString .= $lineSeperator;
$rowCount = $this->getRowCount();
for ($i = 0; $i < $rowCount; $i++) {
$values = [];
foreach ($columns as $columnName) {
if ($this->other) {
try {
if ($this->getValue($i, $columnName) != $this->other->getValue($i, $columnName)) {
$values[] = sprintf(
'%s != actual %s',
var_export($this->getValue($i, $columnName), true),
var_export($this->other->getValue($i, $columnName), true)
);
} else {
$values[] = $this->getValue($i, $columnName);
}
} catch (\InvalidArgumentException $ex) {
$values[] = $this->getValue($i, $columnName) . ': no row';
}
} else {
$values[] = $this->getValue($i, $columnName);
}
}
$tableString .= $this->rowToString($values) . $lineSeperator;
}
return ($this->other ? '(table diff enabled)' : '') . "\n" . $tableString . "\n";
}
protected function rowToString(array $row)
{
$rowString = '';
foreach ($row as $value) {
if (is_null($value)) {
$value = 'NULL';
}
$rowString .= '| ' . str_pad(substr($value, 0, 20), 20, ' ', STR_PAD_BOTH) . ' ';
}
return $rowString . "|\n";
}
}

View File

@@ -0,0 +1,82 @@
<?php
/*
* This file is part of DbUnit.
*
* (c) Sebastian Bergmann <sebastian@phpunit.de>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace PHPUnit\DbUnit\DataSet;
/**
* Provides basic functionality for table meta data.
*/
abstract class AbstractTableMetadata implements ITableMetadata
{
/**
* The names of all columns in the table.
*
* @var array
*/
protected $columns;
/**
* The names of all the primary keys in the table.
*
* @var array
*/
protected $primaryKeys;
/**
* @var string
*/
protected $tableName;
/**
* Returns the names of the columns in the table.
*
* @return array
*/
public function getColumns()
{
return $this->columns;
}
/**
* Returns the names of the primary key columns in the table.
*
* @return array
*/
public function getPrimaryKeys()
{
return $this->primaryKeys;
}
/**
* Returns the name of the table.
*
* @return string
*/
public function getTableName()
{
return $this->tableName;
}
/**
* Asserts that the given tableMetaData matches this tableMetaData.
*
* @param ITableMetadata $other
*/
public function matches(ITableMetadata $other)
{
if ($this->getTableName() != $other->getTableName() ||
$this->getColumns() != $other->getColumns()
) {
return false;
}
return true;
}
}

View File

@@ -0,0 +1,114 @@
<?php
/*
* This file is part of DbUnit.
*
* (c) Sebastian Bergmann <sebastian@phpunit.de>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace PHPUnit\DbUnit\DataSet;
use PHPUnit\DbUnit\InvalidArgumentException;
use RuntimeException;
use SimpleXmlElement;
/**
* The default implementation of a data set.
*/
abstract class AbstractXmlDataSet extends AbstractDataSet
{
/**
* @var array
*/
protected $tables;
/**
* @var SimpleXmlElement
*/
protected $xmlFileContents;
/**
* Creates a new dataset using the given tables.
*
* @param array $tables
*/
public function __construct($xmlFile)
{
if (!is_file($xmlFile)) {
throw new InvalidArgumentException(
"Could not find xml file: {$xmlFile}"
);
}
$libxmlErrorReporting = libxml_use_internal_errors(true);
$this->xmlFileContents = simplexml_load_file($xmlFile, 'SimpleXMLElement', LIBXML_COMPACT | LIBXML_PARSEHUGE);
if (!$this->xmlFileContents) {
$message = '';
foreach (libxml_get_errors() as $error) {
$message .= print_r($error, true);
}
throw new RuntimeException($message);
}
libxml_clear_errors();
libxml_use_internal_errors($libxmlErrorReporting);
$tableColumns = [];
$tableValues = [];
$this->getTableInfo($tableColumns, $tableValues);
$this->createTables($tableColumns, $tableValues);
}
/**
* Reads the simple xml object and creates the appropriate tables and meta
* data for this dataset.
*/
abstract protected function getTableInfo(array &$tableColumns, array &$tableValues);
protected function createTables(array &$tableColumns, array &$tableValues)
{
foreach ($tableValues as $tableName => $values) {
$table = $this->getOrCreateTable($tableName, $tableColumns[$tableName]);
foreach ($values as $value) {
$table->addRow($value);
}
}
}
/**
* Returns the table with the matching name. If the table does not exist
* an empty one is created.
*
* @param string $tableName
*
* @return ITable
*/
protected function getOrCreateTable($tableName, $tableColumns)
{
if (empty($this->tables[$tableName])) {
$tableMetaData = new DefaultTableMetadata($tableName, $tableColumns);
$this->tables[$tableName] = new DefaultTable($tableMetaData);
}
return $this->tables[$tableName];
}
/**
* Creates an iterator over the tables in the data set. If $reverse is
* true a reverse iterator will be returned.
*
* @param bool $reverse
*
* @return ITableIterator
*/
protected function createIterator($reverse = false)
{
return new DefaultTableIterator($this->tables, $reverse);
}
}

View File

@@ -0,0 +1,72 @@
<?php
/*
* This file is part of DbUnit.
*
* (c) Sebastian Bergmann <sebastian@phpunit.de>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace PHPUnit\DbUnit\DataSet;
use PHPUnit\DbUnit\InvalidArgumentException;
/**
* Implements the basic functionality of data sets using a PHP array.
*/
class ArrayDataSet extends AbstractDataSet
{
/**
* @var array
*/
protected $tables = [];
/**
* Constructor to build a new ArrayDataSet with the given array.
* The array parameter is an associative array of tables where the key is
* the table name and the value an array of rows. Each row is an associative
* array by itself with keys representing the field names and the values the
* actual data.
* For example:
* array(
* "addressbook" => array(
* array("id" => 1, "name" => "...", "address" => "..."),
* array("id" => 2, "name" => "...", "address" => "...")
* )
* )
*
* @param array $data
*/
public function __construct(array $data)
{
foreach ($data as $tableName => $rows) {
$columns = [];
if (isset($rows[0])) {
$columns = array_keys($rows[0]);
}
$metaData = new DefaultTableMetadata($tableName, $columns);
$table = new DefaultTable($metaData);
foreach ($rows as $row) {
$table->addRow($row);
}
$this->tables[$tableName] = $table;
}
}
protected function createIterator($reverse = false)
{
return new DefaultTableIterator($this->tables, $reverse);
}
public function getTable($tableName)
{
if (!isset($this->tables[$tableName])) {
throw new InvalidArgumentException("$tableName is not a table in the current database.");
}
return $this->tables[$tableName];
}
}

View File

@@ -0,0 +1,83 @@
<?php
/*
* This file is part of DbUnit.
*
* (c) Sebastian Bergmann <sebastian@phpunit.de>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace PHPUnit\DbUnit\DataSet;
use PHPUnit\DbUnit\InvalidArgumentException;
/**
* Creates Composite Datasets
*
* Allows for creating datasets from multiple sources (csv, query, xml, etc.)
*/
class CompositeDataSet extends AbstractDataSet
{
protected $motherDataSet;
/**
* Creates a new Composite dataset
*
* You can pass in any data set that implements PHPUnit_Extensions_Database_DataSet_IDataSet
*
* @param string $delimiter
* @param string $enclosure
* @param string $escape
*/
public function __construct(array $dataSets = [])
{
$this->motherDataSet = new DefaultDataSet();
foreach ($dataSets as $dataSet) {
$this->addDataSet($dataSet);
}
}
/**
* Adds a new data set to the composite.
*
* The dataset may not define tables that already exist in the composite.
*
* @param IDataSet $dataSet
*/
public function addDataSet(IDataSet $dataSet)
{
foreach ($dataSet->getTableNames() as $tableName) {
if (!in_array($tableName, $this->getTableNames())) {
$this->motherDataSet->addTable($dataSet->getTable($tableName));
} else {
$other = $dataSet->getTable($tableName);
$table = $this->getTable($tableName);
if (!$table->getTableMetaData()->matches($other->getTableMetaData())) {
throw new InvalidArgumentException("There is already a table named $tableName with different table definition");
}
$table->addTableRows($dataSet->getTable($tableName));
}
}
}
/**
* Creates an iterator over the tables in the data set. If $reverse is
* true a reverse iterator will be returned.
*
* @param bool $reverse
*
* @return ITableIterator
*/
protected function createIterator($reverse = false)
{
if ($reverse) {
return $this->motherDataSet->getReverseIterator();
} else {
return $this->motherDataSet->getIterator();
}
}
}

View File

@@ -0,0 +1,122 @@
<?php
/*
* This file is part of DbUnit.
*
* (c) Sebastian Bergmann <sebastian@phpunit.de>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace PHPUnit\DbUnit\DataSet;
use PHPUnit\DbUnit\InvalidArgumentException;
/**
* Creates CsvDataSets.
*
* You can incrementally add CSV files as tables to your datasets
*/
class CsvDataSet extends AbstractDataSet
{
/**
* @var array
*/
protected $tables = [];
/**
* @var string
*/
protected $delimiter = ',';
/**
* @var string
*/
protected $enclosure = '"';
/**
* @var string
*/
protected $escape = '"';
/**
* Creates a new CSV dataset
*
* You can pass in the parameters for how csv files will be read.
*
* @param string $delimiter
* @param string $enclosure
* @param string $escape
*/
public function __construct($delimiter = ',', $enclosure = '"', $escape = '"')
{
$this->delimiter = $delimiter;
$this->enclosure = $enclosure;
$this->escape = $escape;
}
/**
* Adds a table to the dataset
*
* The table will be given the passed name. $csvFile should be a path to
* a valid csv file (based on the arguments passed to the constructor.)
*
* @param string $tableName
* @param string $csvFile
*/
public function addTable($tableName, $csvFile)
{
if (!is_file($csvFile)) {
throw new InvalidArgumentException("Could not find csv file: {$csvFile}");
}
if (!is_readable($csvFile)) {
throw new InvalidArgumentException("Could not read csv file: {$csvFile}");
}
$fh = fopen($csvFile, 'r');
$columns = $this->getCsvRow($fh);
if ($columns === false) {
throw new InvalidArgumentException("Could not determine the headers from the given file {$csvFile}");
}
$metaData = new DefaultTableMetadata($tableName, $columns);
$table = new DefaultTable($metaData);
while (($row = $this->getCsvRow($fh)) !== false) {
$table->addRow(array_combine($columns, $row));
}
$this->tables[$tableName] = $table;
}
/**
* Creates an iterator over the tables in the data set. If $reverse is
* true a reverse iterator will be returned.
*
* @param bool $reverse
*
* @return ITableIterator
*/
protected function createIterator($reverse = false)
{
return new DefaultTableIterator($this->tables, $reverse);
}
/**
* Returns a row from the csv file in an indexed array.
*
* @param resource $fh
*
* @return array
*/
protected function getCsvRow($fh)
{
if (version_compare(PHP_VERSION, '5.3.0', '>')) {
return fgetcsv($fh, null, $this->delimiter, $this->enclosure, $this->escape);
} else {
return fgetcsv($fh, null, $this->delimiter, $this->enclosure);
}
}
}

View File

@@ -0,0 +1,57 @@
<?php
/*
* This file is part of DbUnit.
*
* (c) Sebastian Bergmann <sebastian@phpunit.de>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace PHPUnit\DbUnit\DataSet;
/**
* The default implementation of a data set.
*/
class DefaultDataSet extends AbstractDataSet
{
/**
* An array of ITable objects.
*
* @var array
*/
protected $tables;
/**
* Creates a new dataset using the given tables.
*
* @param array $tables
*/
public function __construct(array $tables = [])
{
$this->tables = $tables;
}
/**
* Adds a table to the dataset.
*
* @param ITable $table
*/
public function addTable(ITable $table)
{
$this->tables[] = $table;
}
/**
* Creates an iterator over the tables in the data set. If $reverse is
* true a reverse iterator will be returned.
*
* @param bool $reverse
*
* @return ITableIterator
*/
protected function createIterator($reverse = false)
{
return new DefaultTableIterator($this->tables, $reverse);
}
}

View File

@@ -0,0 +1,78 @@
<?php
/*
* This file is part of DbUnit.
*
* (c) Sebastian Bergmann <sebastian@phpunit.de>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace PHPUnit\DbUnit\DataSet;
use PHPUnit\DbUnit\InvalidArgumentException;
/**
* Provides default table functionality.
*/
class DefaultTable extends AbstractTable
{
/**
* Creates a new table object using the given $tableMetaData
*
* @param ITableMetadata $tableMetaData
*/
public function __construct(ITableMetadata $tableMetaData)
{
$this->setTableMetaData($tableMetaData);
$this->data = [];
}
/**
* Adds a row to the table with optional values.
*
* @param array $values
*/
public function addRow($values = [])
{
$this->data[] = array_replace(
array_fill_keys($this->getTableMetaData()->getColumns(), null),
$values
);
}
/**
* Adds the rows in the passed table to the current table.
*
* @param ITable $table
*/
public function addTableRows(ITable $table)
{
$tableColumns = $this->getTableMetaData()->getColumns();
$rowCount = $table->getRowCount();
for ($i = 0; $i < $rowCount; $i++) {
$newRow = [];
foreach ($tableColumns as $columnName) {
$newRow[$columnName] = $table->getValue($i, $columnName);
}
$this->addRow($newRow);
}
}
/**
* Sets the specified column of the specied row to the specified value.
*
* @param int $row
* @param string $column
* @param mixed $value
*/
public function setValue($row, $column, $value)
{
if (isset($this->data[$row])) {
$this->data[$row][$column] = $value;
} else {
throw new InvalidArgumentException('The row given does not exist.');
}
}
}

View File

@@ -0,0 +1,120 @@
<?php
/*
* This file is part of DbUnit.
*
* (c) Sebastian Bergmann <sebastian@phpunit.de>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace PHPUnit\DbUnit\DataSet;
/**
* The default table iterator
*/
class DefaultTableIterator implements ITableIterator
{
/**
* An array of tables in the iterator.
*
* @var array
*/
protected $tables;
/**
* If this property is true then the tables will be iterated in reverse
* order.
*
* @var bool
*/
protected $reverse;
/**
* Creates a new default table iterator object.
*
* @param array $tables
* @param bool $reverse
*/
public function __construct(array $tables, $reverse = false)
{
$this->tables = $tables;
$this->reverse = $reverse;
$this->rewind();
}
/**
* Returns the current table.
*
* @return ITable
*/
public function getTable()
{
return $this->current();
}
/**
* Returns the current table's meta data.
*
* @return ITableMetadata
*/
public function getTableMetaData()
{
return $this->current()->getTableMetaData();
}
/**
* Returns the current table.
*
* @return ITable
*/
public function current()
{
return current($this->tables);
}
/**
* Returns the name of the current table.
*
* @return string
*/
public function key()
{
return $this->current()->getTableMetaData()->getTableName();
}
/**
* advances to the next element.
*/
public function next()
{
if ($this->reverse) {
prev($this->tables);
} else {
next($this->tables);
}
}
/**
* Rewinds to the first element
*/
public function rewind()
{
if ($this->reverse) {
end($this->tables);
} else {
reset($this->tables);
}
}
/**
* Returns true if the current index is valid
*
* @return bool
*/
public function valid()
{
return ($this->current() !== false);
}
}

View File

@@ -0,0 +1,41 @@
<?php
/*
* This file is part of DbUnit.
*
* (c) Sebastian Bergmann <sebastian@phpunit.de>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace PHPUnit\DbUnit\DataSet;
use PHPUnit\DbUnit\InvalidArgumentException;
/**
* The default implementation of table meta data
*/
class DefaultTableMetadata extends AbstractTableMetadata
{
/**
* Creates a new default table meta data object.
*
* @param string $tableName
* @param array $columns
* @param array $primaryKeys
*/
public function __construct($tableName, array $columns, array $primaryKeys = [])
{
$this->tableName = $tableName;
$this->columns = $columns;
$this->primaryKeys = [];
foreach ($primaryKeys as $columnName) {
if (!in_array($columnName, $this->columns)) {
throw new InvalidArgumentException('Primary key column passed that is not in the column list.');
} else {
$this->primaryKeys[] = $columnName;
}
}
}
}

View File

@@ -0,0 +1,165 @@
<?php
/*
* This file is part of DbUnit.
*
* (c) Sebastian Bergmann <sebastian@phpunit.de>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace PHPUnit\DbUnit\DataSet;
/**
* A dataset decorator that allows filtering out tables and table columns from
* results.
*/
class Filter extends AbstractDataSet
{
/**
* The dataset being decorated.
*
* @var IDataSet
*/
protected $originalDataSet;
/**
* The tables to exclude from the data set.
*
* @var array
*/
protected $excludeTables = [];
/**
* The tables to exclude from the data set.
*
* @var array
*/
protected $includeTables = [];
/**
* The columns to exclude from the data set.
*
* @var array
*/
protected $excludeColumns = [];
/**
* The columns to exclude from the data set.
*
* @var array
*/
protected $includeColumns = [];
/**
* Creates a new filtered data set.
*
* The $exclude tables should be an associative array using table names as
* the key and an array of column names to exclude for the value. If you
* would like to exclude a full table set the value of the table's entry
* to the special string '*'.
*
* @param IDataSet $originalDataSet
* @param array $excludeTables @deprecated use set* methods instead.
*/
public function __construct(IDataSet $originalDataSet, array $excludeTables = [])
{
$this->originalDataSet = $originalDataSet;
$tables = [];
foreach ($excludeTables as $tableName => $values) {
if (is_array($values)) {
$this->setExcludeColumnsForTable($tableName, $values);
} elseif ($values == '*') {
$tables[] = $tableName;
} else {
$this->setExcludeColumnsForTable($tableName, (array) $values);
}
}
$this->addExcludeTables($tables);
}
/**
* Creates an iterator over the tables in the data set. If $reverse is
* true a reverse iterator will be returned.
*
* @param bool $reverse
*
* @return ITableIterator
*/
protected function createIterator($reverse = false)
{
$original_tables = $this->originalDataSet->getIterator($reverse);
$new_tables = [];
foreach ($original_tables as $table) {
/* @var $table ITable */
$tableName = $table->getTableMetaData()->getTableName();
if ((!in_array($tableName, $this->includeTables) && !empty($this->includeTables)) ||
in_array($tableName, $this->excludeTables)
) {
continue;
} elseif (!empty($this->excludeColumns[$tableName]) || !empty($this->includeColumns[$tableName])) {
$new_table = new TableFilter($table);
if (!empty($this->includeColumns[$tableName])) {
$new_table->addIncludeColumns($this->includeColumns[$tableName]);
}
if (!empty($this->excludeColumns[$tableName])) {
$new_table->addExcludeColumns($this->excludeColumns[$tableName]);
}
$new_tables[] = $new_table;
} else {
$new_tables[] = $table;
}
}
return new DefaultTableIterator($new_tables);
}
/**
* Adds tables to be included in the data set.
*
* @param array $tables
*/
public function addIncludeTables(array $tables)
{
$this->includeTables = array_unique(array_merge($this->includeTables, $tables));
}
/**
* Adds tables to be included in the data set.
*
* @param array $tables
*/
public function addExcludeTables(array $tables)
{
$this->excludeTables = array_unique(array_merge($this->excludeTables, $tables));
}
/**
* Adds columns to include in the data set for the given table.
*
* @param string $table
* @param array $columns
*/
public function setIncludeColumnsForTable($table, array $columns)
{
$this->includeColumns[$table] = $columns;
}
/**
* Adds columns to include in the data set for the given table.
*
* @param string $table
* @param array $columns
*/
public function setExcludeColumnsForTable($table, array $columns)
{
$this->excludeColumns[$table] = $columns;
}
}

View File

@@ -0,0 +1,48 @@
<?php
/*
* This file is part of DbUnit.
*
* (c) Sebastian Bergmann <sebastian@phpunit.de>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace PHPUnit\DbUnit\DataSet;
use PHPUnit\DbUnit\RuntimeException;
/**
* The default implementation of a data set.
*/
class FlatXmlDataSet extends AbstractXmlDataSet
{
protected function getTableInfo(array &$tableColumns, array &$tableValues)
{
if ($this->xmlFileContents->getName() != 'dataset') {
throw new RuntimeException('The root element of a flat xml data set file must be called <dataset>');
}
foreach ($this->xmlFileContents->children() as $row) {
$tableName = $row->getName();
if (!isset($tableColumns[$tableName])) {
$tableColumns[$tableName] = [];
$tableValues[$tableName] = [];
}
$values = [];
foreach ($row->attributes() as $name => $value) {
if (!in_array($name, $tableColumns[$tableName])) {
$tableColumns[$tableName][] = $name;
}
$values[$name] = $value;
}
if (count($values)) {
$tableValues[$tableName][] = $values;
}
}
}
}

View File

@@ -0,0 +1,58 @@
<?php
/*
* This file is part of DbUnit.
*
* (c) Sebastian Bergmann <sebastian@phpunit.de>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace PHPUnit\DbUnit\DataSet;
use IteratorAggregate;
/**
* Provides a basic interface for creating and reading data from data sets.
*/
interface IDataSet extends IteratorAggregate
{
/**
* Returns an array of table names contained in the dataset.
*
* @return array
*/
public function getTableNames();
/**
* Returns a table meta data object for the given table.
*
* @param string $tableName
*
* @return ITableMetadata
*/
public function getTableMetaData($tableName);
/**
* Returns a table object for the given table.
*
* @param string $tableName
*
* @return ITable
*/
public function getTable($tableName);
/**
* Returns a reverse iterator for all table objects in the given dataset.
*
* @return ITableIterator
*/
public function getReverseIterator();
/**
* Asserts that the given data set matches this data set.
*
* @param IDataSet $other
*/
public function matches(IDataSet $other);
}

View File

@@ -0,0 +1,55 @@
<?php
/*
* This file is part of DbUnit.
*
* (c) Sebastian Bergmann <sebastian@phpunit.de>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace PHPUnit\DbUnit\DataSet;
/**
* Provides a basic interface for creating and reading data from data sets.
*/
interface ITable
{
/**
* Returns the table's meta data.
*
* @return ITableMetadata
*/
public function getTableMetaData();
/**
* Returns the number of rows in this table.
*
* @return int
*/
public function getRowCount();
/**
* Returns the value for the given column on the given row.
*
* @param int $row
* @param int $column
*/
public function getValue($row, $column);
/**
* Returns the an associative array keyed by columns for the given row.
*
* @param int $row
*
* @return array
*/
public function getRow($row);
/**
* Asserts that the given table matches this table.
*
* @param ITable $other
*/
public function matches(ITable $other);
}

View File

@@ -0,0 +1,33 @@
<?php
/*
* This file is part of DbUnit.
*
* (c) Sebastian Bergmann <sebastian@phpunit.de>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace PHPUnit\DbUnit\DataSet;
use Iterator;
/**
* Provides a basic interface for creating and reading data from data sets.
*/
interface ITableIterator extends Iterator
{
/**
* Returns the current table.
*
* @return ITable
*/
public function getTable();
/**
* Returns the current table's meta data.
*
* @return ITableMetadata
*/
public function getTableMetaData();
}

View File

@@ -0,0 +1,45 @@
<?php
/*
* This file is part of DbUnit.
*
* (c) Sebastian Bergmann <sebastian@phpunit.de>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace PHPUnit\DbUnit\DataSet;
/**
* Provides a basic interface for returning table meta data.
*/
interface ITableMetadata
{
/**
* Returns the names of the columns in the table.
*
* @return array
*/
public function getColumns();
/**
* Returns the names of the primary key columns in the table.
*
* @return array
*/
public function getPrimaryKeys();
/**
* Returns the name of the table.
*
* @return string
*/
public function getTableName();
/**
* Asserts that the given tableMetaData matches this tableMetaData.
*
* @param ITableMetadata $other
*/
public function matches(ITableMetadata $other);
}

View File

@@ -0,0 +1,24 @@
<?php
/*
* This file is part of DbUnit.
*
* (c) Sebastian Bergmann <sebastian@phpunit.de>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace PHPUnit\DbUnit\DataSet;
/**
* An interface for parsing YAML files.
*/
interface IYamlParser
{
/**
* @param string $yamlFile
*
* @return array parsed YAML
*/
public function parseYaml($yamlFile);
}

View File

@@ -0,0 +1,95 @@
<?php
/*
* This file is part of DbUnit.
*
* (c) Sebastian Bergmann <sebastian@phpunit.de>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace PHPUnit\DbUnit\DataSet;
use PHPUnit\DbUnit\RuntimeException;
/**
* Data set implementation for the output of mysqldump --xml.
*/
class MysqlXmlDataSet extends AbstractXmlDataSet
{
protected function getTableInfo(array &$tableColumns, array &$tableValues)
{
if ($this->xmlFileContents->getName() != 'mysqldump') {
throw new RuntimeException('The root element of a MySQL XML data set file must be called <mysqldump>');
}
foreach ($this->xmlFileContents->xpath('./database/table_data') as $tableElement) {
if (empty($tableElement['name'])) {
throw new RuntimeException('<table_data> elements must include a name attribute');
}
$tableName = (string) $tableElement['name'];
if (!isset($tableColumns[$tableName])) {
$tableColumns[$tableName] = [];
}
if (!isset($tableValues[$tableName])) {
$tableValues[$tableName] = [];
}
foreach ($tableElement->xpath('./row') as $rowElement) {
$rowValues = [];
foreach ($rowElement->xpath('./field') as $columnElement) {
if (empty($columnElement['name'])) {
throw new RuntimeException('<field> element name attributes cannot be empty');
}
$columnName = (string) $columnElement['name'];
if (!in_array($columnName, $tableColumns[$tableName])) {
$tableColumns[$tableName][] = $columnName;
}
}
foreach ($tableColumns[$tableName] as $columnName) {
$fields = $rowElement->xpath('./field[@name="' . $columnName . '"]');
$column = $fields[0];
$attr = $column->attributes('http://www.w3.org/2001/XMLSchema-instance');
if (isset($attr['type']) && (string) $attr['type'] === 'xs:hexBinary') {
$columnValue = pack('H*', (string) $column);
} else {
$null = isset($column['nil']) || isset($attr[0]);
$columnValue = $null ? null : (string) $column;
}
$rowValues[$columnName] = $columnValue;
}
$tableValues[$tableName][] = $rowValues;
}
}
foreach ($this->xmlFileContents->xpath('./database/table_structure') as $tableElement) {
if (empty($tableElement['name'])) {
throw new RuntimeException('<table_structure> elements must include a name attribute');
}
$tableName = (string) $tableElement['name'];
foreach ($tableElement->xpath('./field') as $fieldElement) {
if (empty($fieldElement['Field']) && empty($fieldElement['field'])) {
throw new RuntimeException('<field> elements must include a Field attribute');
}
$columnName = (string) (empty($fieldElement['Field']) ? $fieldElement['field'] : $fieldElement['Field']);
if (!in_array($columnName, $tableColumns[$tableName])) {
$tableColumns[$tableName][] = $columnName;
}
}
}
}
}

View File

@@ -0,0 +1,94 @@
<?php
/*
* This file is part of DbUnit.
*
* (c) Sebastian Bergmann <sebastian@phpunit.de>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace PHPUnit\DbUnit\DataSet;
use PHPUnit\DbUnit\Database\Connection;
use PHPUnit\DbUnit\Database\Table;
use PHPUnit\DbUnit\Database\TableIterator;
use PHPUnit\DbUnit\InvalidArgumentException;
/**
* Provides access to a database instance as a data set.
*/
class QueryDataSet extends AbstractDataSet
{
/**
* An array of ITable objects.
*
* @var array
*/
protected $tables = [];
/**
* The database connection this dataset is using.
*
* @var Connection
*/
protected $databaseConnection;
/**
* Creates a new dataset using the given database connection.
*
* @param Connection $databaseConnection
*/
public function __construct(Connection $databaseConnection)
{
$this->databaseConnection = $databaseConnection;
}
public function addTable($tableName, $query = null)
{
if ($query === null) {
$query = 'SELECT * FROM ' . $tableName;
}
$this->tables[$tableName] = new QueryTable($tableName, $query, $this->databaseConnection);
}
/**
* Creates an iterator over the tables in the data set. If $reverse is
* true a reverse iterator will be returned.
*
* @param bool $reverse
*
* @return TableIterator
*/
protected function createIterator($reverse = false)
{
return new DefaultTableIterator($this->tables, $reverse);
}
/**
* Returns a table object for the given table.
*
* @param string $tableName
*
* @return Table
*/
public function getTable($tableName)
{
if (!isset($this->tables[$tableName])) {
throw new InvalidArgumentException("$tableName is not a table in the current database.");
}
return $this->tables[$tableName];
}
/**
* Returns a list of table names for the database
*
* @return array
*/
public function getTableNames()
{
return array_keys($this->tables);
}
}

View File

@@ -0,0 +1,159 @@
<?php
/*
* This file is part of DbUnit.
*
* (c) Sebastian Bergmann <sebastian@phpunit.de>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace PHPUnit\DbUnit\DataSet;
use PDO;
use PHPUnit\DbUnit\Database\Connection;
/**
* Provides the functionality to represent a database table.
*/
class QueryTable extends AbstractTable
{
/**
* @var string
*/
protected $query;
/**
* @var Connection
*/
protected $databaseConnection;
/**
* @var string
*/
protected $tableName;
/**
* Creates a new database query table object.
*
* @param string $table_name
* @param string $query
* @param Connection $databaseConnection
*/
public function __construct($tableName, $query, Connection $databaseConnection)
{
$this->query = $query;
$this->databaseConnection = $databaseConnection;
$this->tableName = $tableName;
}
/**
* Returns the table's meta data.
*
* @return ITableMetadata
*/
public function getTableMetaData()
{
$this->createTableMetaData();
return parent::getTableMetaData();
}
/**
* Checks if a given row is in the table
*
* @param array $row
*
* @return bool
*/
public function assertContainsRow(array $row)
{
$this->loadData();
return parent::assertContainsRow($row);
}
/**
* Returns the number of rows in this table.
*
* @return int
*/
public function getRowCount()
{
$this->loadData();
return parent::getRowCount();
}
/**
* Returns the value for the given column on the given row.
*
* @param int $row
* @param int $column
*/
public function getValue($row, $column)
{
$this->loadData();
return parent::getValue($row, $column);
}
/**
* Returns the an associative array keyed by columns for the given row.
*
* @param int $row
*
* @return array
*/
public function getRow($row)
{
$this->loadData();
return parent::getRow($row);
}
/**
* Asserts that the given table matches this table.
*
* @param ITable $other
*/
public function matches(ITable $other)
{
$this->loadData();
return parent::matches($other);
}
protected function loadData()
{
if ($this->data === null) {
$pdoStatement = $this->databaseConnection->getConnection()->query($this->query);
$this->data = $pdoStatement->fetchAll(PDO::FETCH_ASSOC);
}
}
protected function createTableMetaData()
{
if ($this->tableMetaData === null) {
$this->loadData();
// if some rows are in the table
$columns = [];
if (isset($this->data[0])) {
// get column names from data
$columns = array_keys($this->data[0]);
} else {
// if no rows found, get column names from database
$pdoStatement = $this->databaseConnection->getConnection()->prepare('SELECT column_name FROM information_schema.COLUMNS WHERE table_schema=:schema AND table_name=:table');
$pdoStatement->execute([
'table' => $this->tableName,
'schema' => $this->databaseConnection->getSchema()
]);
$columns = $pdoStatement->fetchAll(PDO::FETCH_COLUMN, 0);
}
// create metadata
$this->tableMetaData = new DefaultTableMetadata($this->tableName, $columns);
}
}
}

View File

@@ -0,0 +1,91 @@
<?php
/*
* This file is part of DbUnit.
*
* (c) Sebastian Bergmann <sebastian@phpunit.de>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace PHPUnit\DbUnit\DataSet;
/**
* Allows for replacing arbitrary values or portions of values with new data.
*
* A usage for this is replacing all values == '[NULL'] with a true NULL value
*/
class ReplacementDataSet extends AbstractDataSet
{
/**
* @var IDataSet
*/
protected $dataSet;
/**
* @var array
*/
protected $fullReplacements;
/**
* @var array
*/
protected $subStrReplacements;
/**
* Creates a new replacement dataset
*
* You can pass in any data set that implements PHPUnit_Extensions_Database_DataSet_IDataSet
*
* @param string $delimiter
* @param string $enclosure
* @param string $escape
*/
public function __construct(IDataSet $dataSet, array $fullReplacements = [], array $subStrReplacements = [])
{
$this->dataSet = $dataSet;
$this->fullReplacements = $fullReplacements;
$this->subStrReplacements = $subStrReplacements;
}
/**
* Adds a new full replacement
*
* Full replacements will only replace values if the FULL value is a match
*
* @param string $value
* @param string $replacement
*/
public function addFullReplacement($value, $replacement)
{
$this->fullReplacements[$value] = $replacement;
}
/**
* Adds a new substr replacement
*
* Substr replacements will replace all occurances of the substr in every column
*
* @param string $value
* @param string $replacement
*/
public function addSubStrReplacement($value, $replacement)
{
$this->subStrReplacements[$value] = $replacement;
}
/**
* Creates an iterator over the tables in the data set. If $reverse is
* true a reverse iterator will be returned.
*
* @param bool $reverse
*
* @return ITableIterator
*/
protected function createIterator($reverse = false)
{
$innerIterator = $reverse ? $this->dataSet->getReverseIterator() : $this->dataSet->getIterator();
return new ReplacementTableIterator($innerIterator, $this->fullReplacements, $this->subStrReplacements);
}
}

View File

@@ -0,0 +1,210 @@
<?php
/*
* This file is part of DbUnit.
*
* (c) Sebastian Bergmann <sebastian@phpunit.de>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace PHPUnit\DbUnit\DataSet;
/**
* Allows for replacing arbitrary strings in your data sets with other values.
*
* @todo When setTableMetaData() is taken out of the AbstractTable this class should extend AbstractTable.
*/
class ReplacementTable implements ITable
{
/**
* @var ITable
*/
protected $table;
/**
* @var array
*/
protected $fullReplacements;
/**
* @var array
*/
protected $subStrReplacements;
/**
* Creates a new replacement table
*
* @param ITable $table
* @param array $fullReplacements
* @param array $subStrReplacements
*/
public function __construct(ITable $table, array $fullReplacements = [], array $subStrReplacements = [])
{
$this->table = $table;
$this->fullReplacements = $fullReplacements;
$this->subStrReplacements = $subStrReplacements;
}
/**
* Adds a new full replacement
*
* Full replacements will only replace values if the FULL value is a match
*
* @param string $value
* @param string $replacement
*/
public function addFullReplacement($value, $replacement)
{
$this->fullReplacements[$value] = $replacement;
}
/**
* Adds a new substr replacement
*
* Substr replacements will replace all occurances of the substr in every column
*
* @param string $value
* @param string $replacement
*/
public function addSubStrReplacement($value, $replacement)
{
$this->subStrReplacements[$value] = $replacement;
}
/**
* Returns the table's meta data.
*
* @return ITableMetadata
*/
public function getTableMetaData()
{
return $this->table->getTableMetaData();
}
/**
* Returns the number of rows in this table.
*
* @return int
*/
public function getRowCount()
{
return $this->table->getRowCount();
}
/**
* Returns the value for the given column on the given row.
*
* @param int $row
* @param int $column
*/
public function getValue($row, $column)
{
return $this->getReplacedValue($this->table->getValue($row, $column));
}
/**
* Returns the an associative array keyed by columns for the given row.
*
* @param int $row
*
* @return array
*/
public function getRow($row)
{
$row = $this->table->getRow($row);
return array_map([$this, 'getReplacedValue'], $row);
}
/**
* Asserts that the given table matches this table.
*
* @param ITable $other
*/
public function matches(ITable $other)
{
$thisMetaData = $this->getTableMetaData();
$otherMetaData = $other->getTableMetaData();
if (!$thisMetaData->matches($otherMetaData) ||
$this->getRowCount() != $other->getRowCount()
) {
return false;
}
$columns = $thisMetaData->getColumns();
$rowCount = $this->getRowCount();
for ($i = 0; $i < $rowCount; $i++) {
foreach ($columns as $columnName) {
$thisValue = $this->getValue($i, $columnName);
$otherValue = $other->getValue($i, $columnName);
if (is_numeric($thisValue) && is_numeric($otherValue)) {
if ($thisValue != $otherValue) {
return false;
}
} elseif ($thisValue !== $otherValue) {
return false;
}
}
}
return true;
}
public function __toString()
{
$columns = $this->getTableMetaData()->getColumns();
$lineSeperator = str_repeat('+----------------------', count($columns)) . "+\n";
$lineLength = strlen($lineSeperator) - 1;
$tableString = $lineSeperator;
$tableString .= '| ' . str_pad($this->getTableMetaData()->getTableName(), $lineLength - 4, ' ', STR_PAD_RIGHT) . " |\n";
$tableString .= $lineSeperator;
$tableString .= $this->rowToString($columns);
$tableString .= $lineSeperator;
$rowCount = $this->getRowCount();
for ($i = 0; $i < $rowCount; $i++) {
$values = [];
foreach ($columns as $columnName) {
$values[] = $this->getValue($i, $columnName);
}
$tableString .= $this->rowToString($values);
$tableString .= $lineSeperator;
}
return "\n" . $tableString . "\n";
}
protected function rowToString(array $row)
{
$rowString = '';
foreach ($row as $value) {
if (is_null($value)) {
$value = 'NULL';
}
$rowString .= '| ' . str_pad(substr($value, 0, 20), 20, ' ', STR_PAD_BOTH) . ' ';
}
return $rowString . "|\n";
}
protected function getReplacedValue($value)
{
if (is_scalar($value) && array_key_exists((string) $value, $this->fullReplacements)) {
return $this->fullReplacements[$value];
} elseif (count($this->subStrReplacements) && isset($value)) {
return str_replace(array_keys($this->subStrReplacements), array_values($this->subStrReplacements), $value);
} else {
return $value;
}
}
}

View File

@@ -0,0 +1,145 @@
<?php
/*
* This file is part of DbUnit.
*
* (c) Sebastian Bergmann <sebastian@phpunit.de>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace PHPUnit\DbUnit\DataSet;
use OuterIterator;
/**
* The default table iterator
*/
class ReplacementTableIterator implements OuterIterator, ITableIterator
{
/**
* @var ITableIterator
*/
protected $innerIterator;
/**
* @var array
*/
protected $fullReplacements;
/**
* @var array
*/
protected $subStrReplacements;
/**
* Creates a new replacement table iterator object.
*
* @param ITableIterator $innerIterator
* @param array $fullReplacements
* @param array $subStrReplacements
*/
public function __construct(ITableIterator $innerIterator, array $fullReplacements = [], array $subStrReplacements = [])
{
$this->innerIterator = $innerIterator;
$this->fullReplacements = $fullReplacements;
$this->subStrReplacements = $subStrReplacements;
}
/**
* Adds a new full replacement
*
* Full replacements will only replace values if the FULL value is a match
*
* @param string $value
* @param string $replacement
*/
public function addFullReplacement($value, $replacement)
{
$this->fullReplacements[$value] = $replacement;
}
/**
* Adds a new substr replacement
*
* Substr replacements will replace all occurances of the substr in every column
*
* @param string $value
* @param string $replacement
*/
public function addSubStrReplacement($value, $replacement)
{
$this->subStrReplacements[$value] = $replacement;
}
/**
* Returns the current table.
*
* @return ITable
*/
public function getTable()
{
return $this->current();
}
/**
* Returns the current table's meta data.
*
* @return ITableMetadata
*/
public function getTableMetaData()
{
$this->current()->getTableMetaData();
}
/**
* Returns the current table.
*
* @return ITable
*/
public function current()
{
return new ReplacementTable($this->innerIterator->current(), $this->fullReplacements, $this->subStrReplacements);
}
/**
* Returns the name of the current table.
*
* @return string
*/
public function key()
{
return $this->current()->getTableMetaData()->getTableName();
}
/**
* advances to the next element.
*/
public function next()
{
$this->innerIterator->next();
}
/**
* Rewinds to the first element
*/
public function rewind()
{
$this->innerIterator->rewind();
}
/**
* Returns true if the current index is valid
*
* @return bool
*/
public function valid()
{
return $this->innerIterator->valid();
}
public function getInnerIterator()
{
return $this->innerIterator;
}
}

View File

@@ -0,0 +1,92 @@
<?php
/*
* This file is part of DbUnit.
*
* (c) Sebastian Bergmann <sebastian@phpunit.de>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace PHPUnit\DbUnit\DataSet\Specification;
use PHPUnit\DbUnit\DataSet\CsvDataSet;
use ReflectionClass;
/**
* Creates CsvDataSets based off of a spec string.
*
* The format of the spec string is as follows:
*
* <csv options>|table1:filename.csv,table2:filename2.csv
*
* The first portion of the spec including the pipe symbol '|' is optional.
* If the pipe option is included than it may be preceded by up to four
* characters specifying values for the following arguments in order:
* delimiter (defaults to ',',) enclosure (defaults to '"',) escape (defaults to '"',).
*
* Any additional characters in the csv options will be discarded.
*/
class Csv implements Specification
{
/**
* Creates CSV Data Set from a data set spec.
*
* @param string $dataSetSpec
*
* @return CsvDataSet
*/
public function getDataSet($dataSetSpec)
{
$csvDataSetArgs = $this->getCsvOptions($dataSetSpec);
$csvDataSetRfl = new ReflectionClass(CsvDataSet::class);
$csvDataSet = $csvDataSetRfl->newInstanceArgs($csvDataSetArgs);
foreach ($this->getTableFileMap($dataSetSpec) as $tableName => $file) {
$csvDataSet->addTable($tableName, $file);
}
return $csvDataSet;
}
/**
* Returns CSV options.
*
* Returns an array containing the options that will be passed to the
* PHPUnit_Extensions_Database_DataSet_CsvDataSet constructor. The options
* are determined by the given $dataSetSpec.
*
* @param string $dataSetSpec
*
* @return array
*/
protected function getCsvOptions($dataSetSpec)
{
list($csvOptStr) = explode('|', $dataSetSpec, 2);
return str_split($csvOptStr);
}
/**
* Returns map of tables to files.
*
* Returns an associative array containing a mapping of tables (the key)
* to files (the values.) The tables and files are determined by the given
* $dataSetSpec
*
* @param string $dataSetSpec
*
* @return array
*/
protected function getTableFileMap($dataSetSpec)
{
$tables = [];
foreach (explode(',', $dataSetSpec) as $csvfile) {
list($tableName, $file) = explode(':', $csvfile, 2);
$tables[$tableName] = $file;
}
return $tables;
}
}

View File

@@ -0,0 +1,52 @@
<?php
/*
* This file is part of DbUnit.
*
* (c) Sebastian Bergmann <sebastian@phpunit.de>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace PHPUnit\DbUnit\DataSet\Specification;
use PHPUnit\DbUnit\RuntimeException;
/**
* Creates the appropriate DataSet Spec based on a given type.
*/
class Factory implements IFactory
{
/**
* Returns the data set
*
* @param string $type
*
* @return Specification
*/
public function getDataSetSpecByType($type)
{
switch ($type) {
case 'xml':
return new Xml();
case 'flatxml':
return new FlatXml();
case 'csv':
return new Csv();
case 'yaml':
return new Yaml();
case 'dbtable':
return new Table();
case 'dbquery':
return new Query();
default:
throw new RuntimeException("I don't know what you want from me.");
}
}
}

View File

@@ -0,0 +1,38 @@
<?php
/*
* This file is part of DbUnit.
*
* (c) Sebastian Bergmann <sebastian@phpunit.de>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace PHPUnit\DbUnit\DataSet\Specification;
use PHPUnit\DbUnit\DataSet\FlatXmlDataSet;
/**
* Creates a FlatXML dataset based off of a spec string.
*
* The format of the spec string is as follows:
*
* <filename>
*
* The filename should be the location of a flat xml file relative to the
* current working directory.
*/
class FlatXml implements Specification
{
/**
* Creates Flat XML Data Set from a data set spec.
*
* @param string $dataSetSpec
*
* @return FlatXmlDataSet
*/
public function getDataSet($dataSetSpec)
{
return new FlatXmlDataSet($dataSetSpec);
}
}

View File

@@ -0,0 +1,26 @@
<?php
/*
* This file is part of DbUnit.
*
* (c) Sebastian Bergmann <sebastian@phpunit.de>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace PHPUnit\DbUnit\DataSet\Specification;
/**
* An interface for data set spec factories.
*/
interface IFactory
{
/**
* Returns the data set
*
* @param string $type
*
* @return Specification
*/
public function getDataSetSpecByType($type);
}

View File

@@ -0,0 +1,77 @@
<?php
/*
* This file is part of DbUnit.
*
* (c) Sebastian Bergmann <sebastian@phpunit.de>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace PHPUnit\DbUnit\DataSet\Specification;
use PHPUnit\DbUnit\Database\DefaultConnection;
use PHPUnit\DbUnit\DatabaseListConsumer;
use PHPUnit\DbUnit\DataSet\DefaultDataSet;
use ReflectionClass;
/**
* Creates DefaultDataSets based off of a spec string.
*
* This spec class requires a list of databases to be set to the object before
* it can return a list of databases.
*
* The format of the spec string is as follows:
*
* <db label>:<schema>:<table name>:<sql>
*
* The db label should be equal to one of the keys in the array of databases
* passed to setDatabases().
*
* The schema should be the primary schema you will be running the sql query
* against.
*
* The table name should be set to what you would like the table name in the
* dataset to be.
*
* The sql is the query you want to use to generate the table columns and data.
* The column names in the table will be identical to the column aliases in the
* query.
*/
class Query implements Specification, DatabaseListConsumer
{
/**
* @var array
*/
protected $databases = [];
/**
* Sets the database for the spec
*
* @param array $databases
*/
public function setDatabases(array $databases)
{
$this->databases = $databases;
}
/**
* Creates a Default Data Set with a query table from a data set spec.
*
* @param string $dataSetSpec
*
* @return DefaultDataSet
*/
public function getDataSet($dataSetSpec)
{
list($dbLabel, $schema, $table, $sql) = explode(':', $dataSetSpec, 4);
$databaseInfo = $this->databases[$dbLabel];
$pdoRflc = new ReflectionClass('PDO');
$pdo = $pdoRflc->newInstanceArgs(explode('|', $databaseInfo));
$dbConnection = new DefaultConnection($pdo, $schema);
$table = $dbConnection->createQueryTable($table, $sql);
return new DefaultDataSet([$table]);
}
}

View File

@@ -0,0 +1,28 @@
<?php
/*
* This file is part of DbUnit.
*
* (c) Sebastian Bergmann <sebastian@phpunit.de>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace PHPUnit\DbUnit\DataSet\Specification;
use PHPUnit\DbUnit\DataSet\IDataSet;
/**
* Provides an interface for creating data sets from data set spec strings.
*/
interface Specification
{
/**
* Creates a data set from a data set spec string.
*
* @param string $dataSetSpec
*
* @return IDataSet
*/
public function getDataSet($dataSetSpec);
}

View File

@@ -0,0 +1,75 @@
<?php
/*
* This file is part of DbUnit.
*
* (c) Sebastian Bergmann <sebastian@phpunit.de>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace PHPUnit\DbUnit\DataSet\Specification;
use PHPUnit\DbUnit\Database\DefaultConnection;
use PHPUnit\DbUnit\DatabaseListConsumer;
use PHPUnit\DbUnit\DataSet\IDataSet;
use ReflectionClass;
/**
* Creates a database dataset based off of a spec string.
*
* This spec class requires a list of databases to be set to the object before
* it can return a list of databases.
*
* The format of the spec string is as follows:
*
* <db label>:<schema>:<tables>
*
* The db label should be equal to one of the keys in the array of databases
* passed to setDatabases().
*
* The schema should be the primary schema you will be choosing tables from.
*
* The tables should be a comma delimited list of all tables you would like to
* pull data from.
*
* The sql is the query you want to use to generate the table columns and data.
* The column names in the table will be identical to the column aliases in the
* query.
*/
class Table implements Specification, DatabaseListConsumer
{
/**
* @var array
*/
protected $databases = [];
/**
* Sets the database for the spec
*
* @param array $databases
*/
public function setDatabases(array $databases)
{
$this->databases = $databases;
}
/**
* Creates a DB Data Set from a data set spec.
*
* @param string $dataSetSpec
*
* @return IDataSet
*/
public function getDataSet($dataSetSpec)
{
list($dbLabel, $schema, $tables) = explode(':', $dataSetSpec, 3);
$databaseInfo = $this->databases[$dbLabel];
$pdoRflc = new ReflectionClass('PDO');
$pdo = $pdoRflc->newInstanceArgs(explode('|', $databaseInfo));
$dbConnection = new DefaultConnection($pdo, $schema);
return !empty($tables) ? $dbConnection->createDataSet(explode(',', $tables)) : $dbConnection->createDataSet();
}
}

View File

@@ -0,0 +1,38 @@
<?php
/*
* This file is part of DbUnit.
*
* (c) Sebastian Bergmann <sebastian@phpunit.de>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace PHPUnit\DbUnit\DataSet\Specification;
use PHPUnit\DbUnit\DataSet\XmlDataSet;
/**
* Creates a XML dataset based off of a spec string.
*
* The format of the spec string is as follows:
*
* <filename>
*
* The filename should be the location of a xml file relative to the
* current working directory.
*/
class Xml implements Specification
{
/**
* Creates XML Data Set from a data set spec.
*
* @param string $dataSetSpec
*
* @return XmlDataSet
*/
public function getDataSet($dataSetSpec)
{
return new XmlDataSet($dataSetSpec);
}
}

View File

@@ -0,0 +1,38 @@
<?php
/*
* This file is part of DbUnit.
*
* (c) Sebastian Bergmann <sebastian@phpunit.de>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace PHPUnit\DbUnit\DataSet\Specification;
use PHPUnit\DbUnit\DataSet\YamlDataSet;
/**
* Creates a YAML dataset based off of a spec string.
*
* The format of the spec string is as follows:
*
* <filename>
*
* The filename should be the location of a yaml file relative to the
* current working directory.
*/
class Yaml implements Specification
{
/**
* Creates YAML Data Set from a data set spec.
*
* @param string $dataSetSpec
*
* @return YamlDataSet
*/
public function getDataSet($dataSetSpec)
{
return new YamlDataSet($dataSetSpec);
}
}

View File

@@ -0,0 +1,24 @@
<?php
/*
* This file is part of DbUnit.
*
* (c) Sebastian Bergmann <sebastian@phpunit.de>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace PHPUnit\DbUnit\DataSet;
use Symfony;
/**
* The default YAML parser, using Symfony/Yaml.
*/
class SymfonyYamlParser implements IYamlParser
{
public function parseYaml($yamlFile)
{
return Symfony\Component\Yaml\Yaml::parse(file_get_contents($yamlFile));
}
}

View File

@@ -0,0 +1,132 @@
<?php
/*
* This file is part of DbUnit.
*
* (c) Sebastian Bergmann <sebastian@phpunit.de>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace PHPUnit\DbUnit\DataSet;
use PHPUnit\DbUnit\InvalidArgumentException;
/**
* A table decorator that allows filtering out table columns from results.
*/
class TableFilter extends AbstractTable
{
/**
* The table meta data being decorated.
*
* @var ITable
*/
protected $originalTable;
/**
* Creates a new table filter using the original table
*
* @param $originalTable ITable
* @param $excludeColumns Array @deprecated, use the set* methods instead.
*/
public function __construct(ITable $originalTable, array $excludeColumns = [])
{
$this->originalTable = $originalTable;
$this->setTableMetaData(new TableMetadataFilter($originalTable->getTableMetaData()));
$this->addExcludeColumns($excludeColumns);
}
/**
* Returns the number of rows in this table.
*
* @return int
*/
public function getRowCount()
{
return $this->originalTable->getRowCount();
}
/**
* Returns the value for the given column on the given row.
*
* @param int $row
* @param int $column
*/
public function getValue($row, $column)
{
if (in_array($column, $this->getTableMetaData()->getColumns())) {
return $this->originalTable->getValue($row, $column);
} else {
throw new InvalidArgumentException("The given row ({$row}) and column ({$column}) do not exist in table {$this->getTableMetaData()->getTableName()}");
}
}
/**
* Sets the columns to include in the table.
*
* @param array $includeColumns
*/
public function addIncludeColumns(array $includeColumns)
{
$this->tableMetaData->addIncludeColumns($includeColumns);
}
/**
* Clears the included columns.
*/
public function clearIncludeColumns()
{
$this->tableMetaData->clearIncludeColumns();
}
/**
* Sets the columns to exclude from the table.
*
* @param array $excludeColumns
*/
public function addExcludeColumns(array $excludeColumns)
{
$this->tableMetaData->addExcludeColumns($excludeColumns);
}
/**
* Clears the included columns.
*/
public function clearExcludeColumns()
{
$this->tableMetaData->clearExcludeColumns();
}
/**
* Checks if a given row is in the table
*
* @param array $row
*
* @return bool
*/
public function assertContainsRow(array $row)
{
$this->loadData();
return parent::assertContainsRow($row);
}
/**
* Loads data into local data table if it's not already loaded
*/
protected function loadData()
{
if ($this->data === null) {
$data = [];
for ($row = 0; $row < $this->originalTable->getRowCount(); $row++) {
$tRow = [];
foreach ($this->getTableMetaData()->getColumns() as $col) {
$tRow[$col] = $this->getValue($row, $col);
}
$data[$row] = $tRow;
}
$this->data = $data;
}
}
}

View File

@@ -0,0 +1,127 @@
<?php
/*
* This file is part of DbUnit.
*
* (c) Sebastian Bergmann <sebastian@phpunit.de>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace PHPUnit\DbUnit\DataSet;
/**
* A TableMetaData decorator that allows filtering columns from another
* metaData object.
*
* The if a whitelist (include) filter is specified, then only those columns
* will be included.
*/
class TableMetadataFilter extends AbstractTableMetadata
{
/**
* The table meta data being decorated.
*
* @var ITableMetadata
*/
protected $originalMetaData;
/**
* The columns to exclude from the meta data.
*
* @var array
*/
protected $excludeColumns = [];
/**
* The columns to include from the meta data.
*
* @var array
*/
protected $includeColumns = [];
/**
* Creates a new filtered table meta data object filtering out
* $excludeColumns.
*
* @param ITableMetadata $originalMetaData
* @param array $excludeColumns - Deprecated. Use the set* methods instead.
*/
public function __construct(ITableMetadata $originalMetaData, array $excludeColumns = [])
{
$this->originalMetaData = $originalMetaData;
$this->addExcludeColumns($excludeColumns);
}
/**
* Returns the names of the columns in the table.
*
* @return array
*/
public function getColumns()
{
if (!empty($this->includeColumns)) {
return array_values(array_intersect($this->originalMetaData->getColumns(), $this->includeColumns));
} elseif (!empty($this->excludeColumns)) {
return array_values(array_diff($this->originalMetaData->getColumns(), $this->excludeColumns));
} else {
return $this->originalMetaData->getColumns();
}
}
/**
* Returns the names of the primary key columns in the table.
*
* @return array
*/
public function getPrimaryKeys()
{
return $this->originalMetaData->getPrimaryKeys();
}
/**
* Returns the name of the table.
*
* @return string
*/
public function getTableName()
{
return $this->originalMetaData->getTableName();
}
/**
* Sets the columns to include in the table.
*
* @param array $includeColumns
*/
public function addIncludeColumns(array $includeColumns)
{
$this->includeColumns = array_unique(array_merge($this->includeColumns, $includeColumns));
}
/**
* Clears the included columns.
*/
public function clearIncludeColumns()
{
$this->includeColumns = [];
}
/**
* Sets the columns to exclude from the table.
*
* @param array $excludeColumns
*/
public function addExcludeColumns(array $excludeColumns)
{
$this->excludeColumns = array_unique(array_merge($this->excludeColumns, $excludeColumns));
}
/**
* Clears the excluded columns.
*/
public function clearExcludeColumns()
{
$this->excludeColumns = [];
}
}

View File

@@ -0,0 +1,83 @@
<?php
/*
* This file is part of DbUnit.
*
* (c) Sebastian Bergmann <sebastian@phpunit.de>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace PHPUnit\DbUnit\DataSet;
use PHPUnit\DbUnit\RuntimeException;
/**
* The default implementation of a data set.
*/
class XmlDataSet extends AbstractXmlDataSet
{
protected function getTableInfo(array &$tableColumns, array &$tableValues)
{
if ($this->xmlFileContents->getName() != 'dataset') {
throw new RuntimeException('The root element of an xml data set file must be called <dataset>');
}
foreach ($this->xmlFileContents->xpath('/dataset/table') as $tableElement) {
if (empty($tableElement['name'])) {
throw new RuntimeException('Table elements must include a name attribute specifying the table name.');
}
$tableName = (string) $tableElement['name'];
if (!isset($tableColumns[$tableName])) {
$tableColumns[$tableName] = [];
}
if (!isset($tableValues[$tableName])) {
$tableValues[$tableName] = [];
}
$tableInstanceColumns = [];
foreach ($tableElement->xpath('./column') as $columnElement) {
$columnName = (string) $columnElement;
if (empty($columnName)) {
throw new RuntimeException("Missing <column> elements for table $tableName. Add one or more <column> elements to the <table> element.");
}
if (!in_array($columnName, $tableColumns[$tableName])) {
$tableColumns[$tableName][] = $columnName;
}
$tableInstanceColumns[] = $columnName;
}
foreach ($tableElement->xpath('./row') as $rowElement) {
$rowValues = [];
$index = 0;
$numOfTableInstanceColumns = count($tableInstanceColumns);
foreach ($rowElement->children() as $columnValue) {
if ($index >= $numOfTableInstanceColumns) {
throw new RuntimeException("Row contains more values than the number of columns defined for table $tableName.");
}
switch ($columnValue->getName()) {
case 'value':
$rowValues[$tableInstanceColumns[$index]] = (string) $columnValue;
$index++;
break;
case 'null':
$rowValues[$tableInstanceColumns[$index]] = null;
$index++;
break;
default:
throw new RuntimeException('Unknown element ' . $columnValue->getName() . ' in a row element.');
}
}
$tableValues[$tableName][] = $rowValues;
}
}
}
}

View File

@@ -0,0 +1,116 @@
<?php
/*
* This file is part of DbUnit.
*
* (c) Sebastian Bergmann <sebastian@phpunit.de>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace PHPUnit\DbUnit\DataSet;
/**
* Creates YamlDataSets.
*
* You can incrementally add YAML files as tables to your datasets
*/
class YamlDataSet extends AbstractDataSet
{
/**
* @var array
*/
protected $tables = [];
/**
* @var IYamlParser
*/
protected $parser;
/**
* Creates a new YAML dataset
*
* @param string $yamlFile
* @param IYamlParser $parser
*/
public function __construct($yamlFile, $parser = null)
{
if ($parser == null) {
$parser = new SymfonyYamlParser();
}
$this->parser = $parser;
$this->addYamlFile($yamlFile);
}
/**
* Adds a new yaml file to the dataset.
*
* @param string $yamlFile
*/
public function addYamlFile($yamlFile)
{
$data = $this->parser->parseYaml($yamlFile);
foreach ($data as $tableName => $rows) {
if (!isset($rows)) {
$rows = [];
}
if (!is_array($rows)) {
continue;
}
if (!array_key_exists($tableName, $this->tables)) {
$columns = $this->getColumns($rows);
$tableMetaData = new DefaultTableMetadata(
$tableName, $columns
);
$this->tables[$tableName] = new DefaultTable(
$tableMetaData
);
}
foreach ($rows as $row) {
$this->tables[$tableName]->addRow($row);
}
}
}
/**
* Creates a unique list of columns from all the rows in a table.
* If the table is defined another time in the Yaml, and if the Yaml
* parser could return the multiple occerrences, then this would be
* insufficient unless we grouped all the occurences of the table
* into onwe row set. sfYaml, however, does not provide multiple tables
* with the same name, it only supplies the last table.
*
* @params all the rows in a table.
*/
private function getColumns($rows)
{
$columns = [];
foreach ($rows as $row) {
$columns = array_merge($columns, array_keys($row));
}
return array_values(array_unique($columns));
}
/**
* Creates an iterator over the tables in the data set. If $reverse is
* true a reverse iterator will be returned.
*
* @param bool $reverse
*
* @return ITableIterator
*/
protected function createIterator($reverse = false)
{
return new DefaultTableIterator(
$this->tables, $reverse
);
}
}

View File

@@ -0,0 +1,117 @@
<?php
/*
* This file is part of DbUnit.
*
* (c) Sebastian Bergmann <sebastian@phpunit.de>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace PHPUnit\DbUnit\Database;
use PDO;
use PHPUnit\DbUnit\Database\Metadata\Metadata;
use PHPUnit\DbUnit\DataSet\IDataSet;
use PHPUnit\DbUnit\DataSet\ITable;
/**
* Provides a basic interface for communicating with a database.
*/
interface Connection
{
/**
* Close this connection.
*/
public function close();
/**
* Creates a dataset containing the specified table names. If no table
* names are specified then it will created a dataset over the entire
* database.
*
* @param array $tableNames
*
* @return IDataSet
*/
public function createDataSet(array $tableNames = null);
/**
* Creates a table with the result of the specified SQL statement.
*
* @param string $resultName
* @param string $sql
*
* @return ITable
*/
public function createQueryTable($resultName, $sql);
/**
* Returns a PDO Connection
*
* @return PDO
*/
public function getConnection();
/**
* Returns a database metadata object that can be used to retrieve table
* meta data from the database.
*
* @return Metadata
*/
public function getMetaData();
/**
* Returns the number of rows in the given table. You can specify an
* optional where clause to return a subset of the table.
*
* @param string $tableName
* @param string $whereClause
* @param int
*/
public function getRowCount($tableName, $whereClause = null);
/**
* Returns the schema for the connection.
*
* @return string
*/
public function getSchema();
/**
* Returns a quoted schema object. (table name, column name, etc)
*
* @param string $object
*
* @return string
*/
public function quoteSchemaObject($object);
/**
* Returns the command used to truncate a table.
*
* @return string
*/
public function getTruncateCommand();
/**
* Returns true if the connection allows cascading
*
* @return bool
*/
public function allowsCascading();
/**
* Disables primary keys if connection does not allow setting them otherwise
*
* @param string $tableName
*/
public function disablePrimaryKeys($tableName);
/**
* Reenables primary keys after they have been disabled
*
* @param string $tableName
*/
public function enablePrimaryKeys($tableName);
}

View File

@@ -0,0 +1,142 @@
<?php
/*
* This file is part of DbUnit.
*
* (c) Sebastian Bergmann <sebastian@phpunit.de>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace PHPUnit\DbUnit\Database;
use PHPUnit\DbUnit\DataSet\AbstractDataSet;
use PHPUnit\DbUnit\DataSet\DefaultTableMetadata;
use PHPUnit\DbUnit\DataSet\ITableMetadata;
use PHPUnit\DbUnit\InvalidArgumentException;
use PHPUnit\DbUnit\RuntimeException;
/**
* Provides access to a database instance as a data set.
*/
class DataSet extends AbstractDataSet
{
/**
* An array of ITable objects.
*
* @var array
*/
protected $tables = [];
/**
* The database connection this dataset is using.
*
* @var Connection
*/
protected $databaseConnection;
/**
* Creates a new dataset using the given database connection.
*
* @param Connection $databaseConnection
*/
public function __construct(Connection $databaseConnection)
{
$this->databaseConnection = $databaseConnection;
}
/**
* Creates the query necessary to pull all of the data from a table.
*
* @param ITableMetadata $tableMetaData
*
* @return string
*/
public static function buildTableSelect(ITableMetadata $tableMetaData, Connection $databaseConnection = null)
{
if ($tableMetaData->getTableName() == '') {
$e = new RuntimeException('Empty Table Name');
echo $e->getTraceAsString();
throw $e;
}
$columns = $tableMetaData->getColumns();
if ($databaseConnection) {
$columns = array_map([$databaseConnection, 'quoteSchemaObject'], $columns);
}
$columnList = implode(', ', $columns);
if ($databaseConnection) {
$tableName = $databaseConnection->quoteSchemaObject($tableMetaData->getTableName());
} else {
$tableName = $tableMetaData->getTableName();
}
$primaryKeys = $tableMetaData->getPrimaryKeys();
if ($databaseConnection) {
$primaryKeys = array_map([$databaseConnection, 'quoteSchemaObject'], $primaryKeys);
}
if (count($primaryKeys)) {
$orderBy = 'ORDER BY ' . implode(' ASC, ', $primaryKeys) . ' ASC';
} else {
$orderBy = '';
}
return "SELECT {$columnList} FROM {$tableName} {$orderBy}";
}
/**
* Creates an iterator over the tables in the data set. If $reverse is
* true a reverse iterator will be returned.
*
* @param bool $reverse
*
* @return TableIterator
*/
protected function createIterator($reverse = false)
{
return new TableIterator($this->getTableNames(), $this, $reverse);
}
/**
* Returns a table object for the given table.
*
* @param string $tableName
*
* @return Table
*/
public function getTable($tableName)
{
if (!in_array($tableName, $this->getTableNames())) {
throw new InvalidArgumentException("$tableName is not a table in the current database.");
}
if (empty($this->tables[$tableName])) {
$this->tables[$tableName] = new Table($this->getTableMetaData($tableName), $this->databaseConnection);
}
return $this->tables[$tableName];
}
/**
* Returns a table meta data object for the given table.
*
* @param string $tableName
*
* @return DefaultTableMetadata
*/
public function getTableMetaData($tableName)
{
return new DefaultTableMetadata($tableName, $this->databaseConnection->getMetaData()->getTableColumns($tableName), $this->databaseConnection->getMetaData()->getTablePrimaryKeys($tableName));
}
/**
* Returns a list of table names for the database
*
* @return array
*/
public function getTableNames()
{
return $this->databaseConnection->getMetaData()->getTableNames();
}
}

View File

@@ -0,0 +1,199 @@
<?php
/*
* This file is part of DbUnit.
*
* (c) Sebastian Bergmann <sebastian@phpunit.de>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace PHPUnit\DbUnit\Database;
use PDO;
use PHPUnit\DbUnit\Database\Metadata\AbstractMetadata;
use PHPUnit\DbUnit\Database\Metadata\Metadata;
use PHPUnit\DbUnit\DataSet\IDataSet;
use PHPUnit\DbUnit\DataSet\QueryTable;
/**
* Provides a basic interface for communicating with a database.
*/
class DefaultConnection implements Connection
{
/**
* @var PDO
*/
protected $connection;
/**
* The metadata object used to retrieve table meta data from the database.
*
* @var Metadata
*/
protected $metaData;
/**
* Creates a new database connection
*
* @param PDO $connection
* @param string $schema - The name of the database schema you will be testing against.
*/
public function __construct(PDO $connection, $schema = '')
{
$this->connection = $connection;
$this->metaData = AbstractMetadata::createMetaData($connection, $schema);
$connection->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
}
/**
* Close this connection.
*/
public function close()
{
unset($this->connection);
}
/**
* Returns a database metadata object that can be used to retrieve table
* meta data from the database.
*
* @return Metadata
*/
public function getMetaData()
{
return $this->metaData;
}
/**
* Returns the schema for the connection.
*
* @return string
*/
public function getSchema()
{
return $this->getMetaData()->getSchema();
}
/**
* Creates a dataset containing the specified table names. If no table
* names are specified then it will created a dataset over the entire
* database.
*
* @param array $tableNames
*
* @return IDataSet
*
* @todo Implement the filtered data set.
*/
public function createDataSet(array $tableNames = null)
{
if (empty($tableNames)) {
return new DataSet($this);
} else {
return new FilteredDataSet($this, $tableNames);
}
}
/**
* Creates a table with the result of the specified SQL statement.
*
* @param string $resultName
* @param string $sql
*
* @return Table
*/
public function createQueryTable($resultName, $sql)
{
return new QueryTable($resultName, $sql, $this);
}
/**
* Returns this connection database configuration
*/
public function getConfig()
{
}
/**
* Returns a PDO Connection
*
* @return PDO
*/
public function getConnection()
{
return $this->connection;
}
/**
* Returns the number of rows in the given table. You can specify an
* optional where clause to return a subset of the table.
*
* @param string $tableName
* @param string $whereClause
*
* @return int
*/
public function getRowCount($tableName, $whereClause = null)
{
$query = 'SELECT COUNT(*) FROM ' . $this->quoteSchemaObject($tableName);
if (isset($whereClause)) {
$query .= " WHERE {$whereClause}";
}
return (int) $this->connection->query($query)->fetchColumn();
}
/**
* Returns a quoted schema object. (table name, column name, etc)
*
* @param string $object
*
* @return string
*/
public function quoteSchemaObject($object)
{
return $this->getMetaData()->quoteSchemaObject($object);
}
/**
* Returns the command used to truncate a table.
*
* @return string
*/
public function getTruncateCommand()
{
return $this->getMetaData()->getTruncateCommand();
}
/**
* Returns true if the connection allows cascading
*
* @return bool
*/
public function allowsCascading()
{
return $this->getMetaData()->allowsCascading();
}
/**
* Disables primary keys if connection does not allow setting them otherwise
*
* @param string $tableName
*/
public function disablePrimaryKeys($tableName)
{
$this->getMetaData()->disablePrimaryKeys($tableName);
}
/**
* Reenables primary keys after they have been disabled
*
* @param string $tableName
*/
public function enablePrimaryKeys($tableName)
{
$this->getMetaData()->enablePrimaryKeys($tableName);
}
}

View File

@@ -0,0 +1,43 @@
<?php
/*
* This file is part of DbUnit.
*
* (c) Sebastian Bergmann <sebastian@phpunit.de>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace PHPUnit\DbUnit\Database;
/**
* Provides access to a database instance as a data set.
*/
class FilteredDataSet extends DataSet
{
/**
* @var array
*/
protected $tableNames;
/**
* Creates a new dataset using the given database connection.
*
* @param Connection $databaseConnection
*/
public function __construct(Connection $databaseConnection, array $tableNames)
{
parent::__construct($databaseConnection);
$this->tableNames = $tableNames;
}
/**
* Returns a list of table names for the database
*
* @return array
*/
public function getTableNames()
{
return $this->tableNames;
}
}

View File

@@ -0,0 +1,217 @@
<?php
/*
* This file is part of DbUnit.
*
* (c) Sebastian Bergmann <sebastian@phpunit.de>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace PHPUnit\DbUnit\Database\Metadata;
use PDO;
use PHPUnit\DbUnit\RuntimeException;
use ReflectionClass;
/**
* Provides a basic constructor for all meta data classes and a factory for
* generating the appropriate meta data class.
*/
abstract class AbstractMetadata implements Metadata
{
protected static $metaDataClassMap = [
'pgsql' => PgSQL::class,
'mysql' => MySQL::class,
'oci' => Oci::class,
'sqlite' => Sqlite::class,
'sqlite2' => Sqlite::class,
'sqlsrv' => SqlSrv::class,
'firebird' => Firebird::class,
'dblib' => Dblib::class
];
/**
* The PDO connection used to retreive database meta data
*
* @var PDO
*/
protected $pdo;
/**
* The default schema name for the meta data object.
*
* @var string
*/
protected $schema;
/**
* The character used to quote schema objects.
*/
protected $schemaObjectQuoteChar = '"';
/**
* The command used to perform a TRUNCATE operation.
*/
protected $truncateCommand = 'TRUNCATE';
/**
* Creates a new database meta data object using the given pdo connection
* and schema name.
*
* @param PDO $pdo
* @param string $schema
*/
final public function __construct(PDO $pdo, $schema = '')
{
$this->pdo = $pdo;
$this->schema = $schema;
}
/**
* Creates a meta data object based on the driver of given $pdo object and
* $schema name.
*
* @param PDO $pdo
* @param string $schema
*
* @return AbstractMetadata
*/
public static function createMetaData(PDO $pdo, $schema = '')
{
$driverName = $pdo->getAttribute(PDO::ATTR_DRIVER_NAME);
if (isset(self::$metaDataClassMap[$driverName])) {
$className = self::$metaDataClassMap[$driverName];
if ($className instanceof ReflectionClass) {
return $className->newInstance($pdo, $schema);
} else {
return self::registerClassWithDriver($className, $driverName)->newInstance($pdo, $schema);
}
} else {
throw new RuntimeException("Could not find a meta data driver for {$driverName} pdo driver.");
}
}
/**
* Validates and registers the given $className with the given $pdoDriver.
* It should be noted that this function will not attempt to include /
* require the file. The $pdoDriver can be determined by the value of the
* PDO::ATTR_DRIVER_NAME attribute for a pdo object.
*
* A reflection of the $className is returned.
*
* @param string $className
* @param string $pdoDriver
*
* @return ReflectionClass
*/
public static function registerClassWithDriver($className, $pdoDriver)
{
if (!class_exists($className)) {
throw new RuntimeException("Specified class for {$pdoDriver} driver ({$className}) does not exist.");
}
$reflection = new ReflectionClass($className);
if ($reflection->isSubclassOf(self::class)) {
return self::$metaDataClassMap[$pdoDriver] = $reflection;
} else {
throw new RuntimeException("Specified class for {$pdoDriver} driver ({$className}) does not extend PHPUnit_Extensions_Database_DB_MetaData.");
}
}
/**
* Returns the schema for the connection.
*
* @return string
*/
public function getSchema()
{
return $this->schema;
}
/**
* Returns a quoted schema object. (table name, column name, etc)
*
* @param string $object
*
* @return string
*/
public function quoteSchemaObject($object)
{
$parts = explode('.', $object);
$quotedParts = [];
foreach ($parts as $part) {
$quotedParts[] = $this->schemaObjectQuoteChar .
str_replace($this->schemaObjectQuoteChar, $this->schemaObjectQuoteChar . $this->schemaObjectQuoteChar, $part) .
$this->schemaObjectQuoteChar;
}
return implode('.', $quotedParts);
}
/**
* Seperates the schema and the table from a fully qualified table name.
*
* Returns an associative array containing the 'schema' and the 'table'.
*
* @param string $fullTableName
*
* @return array
*/
public function splitTableName($fullTableName)
{
if (($dot = strpos($fullTableName, '.')) !== false) {
return [
'schema' => substr($fullTableName, 0, $dot),
'table' => substr($fullTableName, $dot + 1)
];
} else {
return [
'schema' => null,
'table' => $fullTableName
];
}
}
/**
* Returns the command for the database to truncate a table.
*
* @return string
*/
public function getTruncateCommand()
{
return $this->truncateCommand;
}
/**
* Returns true if the rdbms allows cascading
*
* @return bool
*/
public function allowsCascading()
{
return false;
}
/**
* Disables primary keys if the rdbms does not allow setting them otherwise
*
* @param string $tableName
*/
public function disablePrimaryKeys($tableName)
{
return;
}
/**
* Reenables primary keys after they have been disabled
*
* @param string $tableName
*/
public function enablePrimaryKeys($tableName)
{
return;
}
}

View File

@@ -0,0 +1,128 @@
<?php
/*
* This file is part of DbUnit.
*
* (c) Sebastian Bergmann <sebastian@phpunit.de>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace PHPUnit\DbUnit\Database\Metadata;
/**
* Provides functionality to retrieve meta data from an Dblib (SQL Server) database.
*/
class Dblib extends AbstractMetadata
{
/**
* No character used to quote schema objects.
*
* @var string
*/
protected $schemaObjectQuoteChar = '';
/**
* The command used to perform a TRUNCATE operation.
*
* @var string
*/
protected $truncateCommand = 'TRUNCATE TABLE';
/**
* @var array
*/
protected $columns = [];
/**
* @var array
*/
protected $keys = [];
/**
* Returns an array containing the names of all the tables in the database.
*
* @return array
*/
public function getTableNames()
{
$tableNames = [];
$query = 'SELECT name
FROM sys.tables
ORDER BY name';
$result = $this->pdo->query($query);
while ($tableName = $result->fetchColumn(0)) {
$tableNames[] = $tableName;
}
return $tableNames;
}
/**
* Returns an array containing the names of all the columns in the
* $tableName table,
*
* @param string $tableName
*
* @return array
*/
public function getTableColumns($tableName)
{
if (!isset($this->columns[$tableName])) {
$this->loadColumnInfo($tableName);
}
return $this->columns[$tableName];
}
/**
* Returns an array containing the names of all the primary key columns in
* the $tableName table.
*
* @param string $tableName
*
* @return array
*/
public function getTablePrimaryKeys($tableName)
{
if (!isset($this->keys[$tableName])) {
$this->loadColumnInfo($tableName);
}
return $this->keys[$tableName];
}
/**
* Loads column info from a sql server database.
*
* @param string $tableName
*/
protected function loadColumnInfo($tableName)
{
$query = "SELECT name
FROM sys.columns
WHERE object_id = OBJECT_ID('" . $tableName . "')
ORDER BY column_id";
$result = $this->pdo->query($query);
while ($columnName = $result->fetchColumn(0)) {
$this->columns[$tableName][] = $columnName;
}
$keyQuery = "SELECT COL_NAME(ic.OBJECT_ID,ic.column_id) AS ColumnName
FROM sys.indexes AS i INNER JOIN
sys.index_columns AS ic ON i.OBJECT_ID = ic.OBJECT_ID
AND i.index_id = ic.index_id
WHERE i.is_primary_key = 1 AND OBJECT_NAME(ic.OBJECT_ID) = '" . $tableName . "'";
$result = $this->pdo->query($keyQuery);
while ($columnName = $result->fetchColumn(0)) {
$this->keys[$tableName][] = $columnName;
}
}
}

View File

@@ -0,0 +1,214 @@
<?php
/*
* This file is part of DbUnit.
*
* (c) Sebastian Bergmann <sebastian@phpunit.de>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace PHPUnit\DbUnit\Database\Metadata;
/**
* Provides functionality to retrieve meta data from a Firebird database.
*/
class Firebird extends AbstractMetadata
{
/**
* The command used to perform a TRUNCATE operation.
*
* @var string
*/
protected $truncateCommand = 'DELETE FROM';
/**
* Returns an array containing the names of all the tables in the database.
*
* @return array
*/
public function getTableNames()
{
$query = "
SELECT DISTINCT
TABLE_NAME
FROM INFORMATION_SCHEMA.TABLES
WHERE
TABLE_TYPE='BASE TABLE' AND
TABLE_SCHEMA = ?
ORDER BY TABLE_NAME
";
$query = "
select
RDB$RELATION_NAME as TABLE_NAME
from RDB$RELATIONS
where
((RDB$RELATION_TYPE = 0) or
(RDB$RELATION_TYPE is null)) and
(RDB$SYSTEM_FLAG = 0)
order by (RDB$RELATION_NAME)
";
$statement = $this->pdo->prepare($query);
$statement->execute([$this->getSchema()]);
$tableNames = [];
while ($tableName = $statement->fetchColumn(0)) {
$tableNames[] = $tableName;
}
return $tableNames;
}
/**
* Returns an array containing the names of all the columns in the
* $tableName table,
*
* @param string $tableName
*
* @return array
*/
public function getTableColumns($tableName)
{
if (!isset($this->columns[$tableName])) {
$this->loadColumnInfo($tableName);
}
return $this->columns[$tableName];
}
/**
* Returns an array containing the names of all the primary key columns in
* the $tableName table.
*
* @param string $tableName
*
* @return array
*/
public function getTablePrimaryKeys($tableName)
{
if (!isset($this->keys[$tableName])) {
$this->loadColumnInfo($tableName);
}
return $this->keys[$tableName];
}
/**
* Loads column info from a database table.
*
* @param string $tableName
*/
protected function loadColumnInfo($tableName)
{
$this->columns[$tableName] = [];
$this->keys[$tableName] = [];
$columnQuery = '
SELECT DISTINCT
COLUMN_NAME, ORDINAL_POSITION
FROM INFORMATION_SCHEMA.COLUMNS
WHERE
TABLE_NAME = ? AND
TABLE_SCHEMA = ?
ORDER BY ORDINAL_POSITION
';
$columnQuery = '
select
rf.RDB$FIELD_NAME as COLUMN_NAME,
rf.RDB$FIELD_POSITION as ORDINAL_POSITION
from RDB$RELATION_FIELDS as rf
where
upper(RDB$RELATION_NAME) = upper(?)
order by
ORDINAL_POSITION
';
$columnStatement = $this->pdo->prepare($columnQuery);
$columnStatement->execute([$tableName]);
while ($columName = $columnStatement->fetchColumn(0)) {
$this->columns[$tableName][] = $columName;
}
$keyQuery = "
SELECT
KCU.COLUMN_NAME,
KCU.ORDINAL_POSITION
FROM
INFORMATION_SCHEMA.KEY_COLUMN_USAGE as KCU
LEFT JOIN INFORMATION_SCHEMA.TABLE_CONSTRAINTS as TC
ON TC.TABLE_NAME = KCU.TABLE_NAME
WHERE
TC.CONSTRAINT_TYPE = 'PRIMARY KEY' AND
TC.TABLE_NAME = ? AND
TC.TABLE_SCHEMA = ?
ORDER BY
KCU.ORDINAL_POSITION ASC
";
$keyQuery = "
select
idseg.rdb\$field_name as COLUMN_NAME,
idseg.rdb\$field_position as ORDINAL_POSITION,
rc.rdb\$relation_name as tablename,
rc.rdb\$constraint_name as pk_name
from
RDB\$RELATION_CONSTRAINTS AS rc
left join
rdb\$index_segments as idseg on
(rc.rdb\$index_name = idseg.rdb\$index_name)
where
rc.RDB\$CONSTRAINT_TYPE = 'PRIMARY KEY'
and upper(rc.RDB\$RELATION_NAME) = upper(?)
order by
rc.rdb\$constraint_name, idseg.rdb\$field_position
";
$keyStatement = $this->pdo->prepare($keyQuery);
$keyStatement->execute([$tableName]);
while ($columName = $keyStatement->fetchColumn(0)) {
$this->keys[$tableName][] = $columName;
}
}
/**
* Returns the schema for the connection.
*
* @return string
*/
public function getSchema()
{
if (empty($this->schema)) {
return 'public';
} else {
return $this->schema;
}
}
/**
* Returns true if the rdbms allows cascading
*
* @return bool
*/
public function allowsCascading()
{
return false;
}
/**
* Returns a quoted schema object. (table name, column name, etc)
*
* @param string $object
*
* @return string
*/
public function quoteSchemaObject($object)
{
return $object; //firebird does not allow object quoting
}
}

View File

@@ -0,0 +1,135 @@
<?php
/*
* This file is part of DbUnit.
*
* (c) Sebastian Bergmann <sebastian@phpunit.de>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace PHPUnit\DbUnit\Database\Metadata;
/**
* Provides functionality to retrieve meta data from a database with information_schema support.
*/
class InformationSchema extends AbstractMetadata
{
protected $columns = [];
protected $keys = [];
/**
* Returns an array containing the names of all the tables in the database.
*
* @return array
*/
public function getTableNames()
{
$query = "
SELECT DISTINCT
TABLE_NAME
FROM INFORMATION_SCHEMA.TABLES
WHERE
TABLE_TYPE='BASE TABLE' AND
TABLE_SCHEMA = ?
ORDER BY TABLE_NAME
";
$statement = $this->pdo->prepare($query);
$statement->execute([$this->getSchema()]);
$tableNames = [];
while ($tableName = $statement->fetchColumn(0)) {
$tableNames[] = $tableName;
}
return $tableNames;
}
/**
* Returns an array containing the names of all the columns in the
* $tableName table,
*
* @param string $tableName
*
* @return array
*/
public function getTableColumns($tableName)
{
if (!isset($this->columns[$tableName])) {
$this->loadColumnInfo($tableName);
}
return $this->columns[$tableName];
}
/**
* Returns an array containing the names of all the primary key columns in
* the $tableName table.
*
* @param string $tableName
*
* @return array
*/
public function getTablePrimaryKeys($tableName)
{
if (!isset($this->keys[$tableName])) {
$this->loadColumnInfo($tableName);
}
return $this->keys[$tableName];
}
/**
* Loads column info from a sqlite database.
*
* @param string $tableName
*/
protected function loadColumnInfo($tableName)
{
$this->columns[$tableName] = [];
$this->keys[$tableName] = [];
$columnQuery = '
SELECT DISTINCT
COLUMN_NAME
FROM INFORMATION_SCHEMA.COLUMNS
WHERE
TABLE_NAME = ? AND
TABLE_SCHEMA = ?
ORDER BY ORDINAL_POSITION
';
$columnStatement = $this->pdo->prepare($columnQuery);
$columnStatement->execute([$tableName, $this->getSchema()]);
while ($columName = $columnStatement->fetchColumn(0)) {
$this->columns[$tableName][] = $columName;
}
$keyQuery = "
SELECT
KCU.COLUMN_NAME
FROM
INFORMATION_SCHEMA.TABLE_CONSTRAINTS as TC,
INFORMATION_SCHEMA.KEY_COLUMN_USAGE as KCU
WHERE
TC.CONSTRAINT_NAME = KCU.CONSTRAINT_NAME AND
TC.TABLE_NAME = KCU.TABLE_NAME AND
TC.TABLE_SCHEMA = KCU.TABLE_SCHEMA AND
TC.CONSTRAINT_TYPE = 'PRIMARY KEY' AND
TC.TABLE_NAME = ? AND
TC.TABLE_SCHEMA = ?
ORDER BY
KCU.ORDINAL_POSITION ASC
";
$keyStatement = $this->pdo->prepare($keyQuery);
$keyStatement->execute([$tableName, $this->getSchema()]);
while ($columName = $keyStatement->fetchColumn(0)) {
$this->keys[$tableName][] = $columName;
}
}
}

View File

@@ -0,0 +1,81 @@
<?php
/*
* This file is part of DbUnit.
*
* (c) Sebastian Bergmann <sebastian@phpunit.de>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace PHPUnit\DbUnit\Database\Metadata;
/**
* Provides a basic interface for retreiving metadata from a database.
*/
interface Metadata
{
/**
* Returns an array containing the names of all the tables in the database.
*
* @return array
*/
public function getTableNames();
/**
* Returns an array containing the names of all the columns in the
* $tableName table,
*
* @param string $tableName
*
* @return array
*/
public function getTableColumns($tableName);
/**
* Returns an array containing the names of all the primary key columns in
* the $tableName table.
*
* @param string $tableName
*
* @return array
*/
public function getTablePrimaryKeys($tableName);
/**
* Returns the name of the default schema.
*
* @return string
*/
public function getSchema();
/**
* Returns a quoted schema object. (table name, column name, etc)
*
* @param string $object
*
* @return string
*/
public function quoteSchemaObject($object);
/**
* Returns true if the rdbms allows cascading
*
* @return bool
*/
public function allowsCascading();
/**
* Disables primary keys if rdbms does not allow setting them otherwise
*
* @param string $tableName
*/
public function disablePrimaryKeys($tableName);
/**
* Reenables primary keys after they have been disabled
*
* @param string $tableName
*/
public function enablePrimaryKeys($tableName);
}

View File

@@ -0,0 +1,87 @@
<?php
/*
* This file is part of DbUnit.
*
* (c) Sebastian Bergmann <sebastian@phpunit.de>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace PHPUnit\DbUnit\Database\Metadata;
use PDO;
/**
* Provides functionality to retrieve meta data from a MySQL database.
*/
class MySQL extends AbstractMetadata
{
protected $schemaObjectQuoteChar = '`';
/**
* Returns an array containing the names of all the tables in the database.
*
* @return array
*/
public function getTableNames()
{
$query = 'SHOW TABLES';
$statement = $this->pdo->prepare($query);
$statement->execute();
$tableNames = [];
while (($tableName = $statement->fetchColumn(0))) {
$tableNames[] = $tableName;
}
return $tableNames;
}
/**
* Returns an array containing the names of all the columns in the
* $tableName table,
*
* @param string $tableName
*
* @return array
*/
public function getTableColumns($tableName)
{
$query = 'SHOW COLUMNS FROM ' . $this->quoteSchemaObject($tableName);
$statement = $this->pdo->prepare($query);
$statement->execute();
$columnNames = [];
while (($columnName = $statement->fetchColumn(0))) {
$columnNames[] = $columnName;
}
return $columnNames;
}
/**
* Returns an array containing the names of all the primary key columns in
* the $tableName table.
*
* @param string $tableName
*
* @return array
*/
public function getTablePrimaryKeys($tableName)
{
$query = 'SHOW INDEX FROM ' . $this->quoteSchemaObject($tableName);
$statement = $this->pdo->prepare($query);
$statement->execute();
$statement->setFetchMode(PDO::FETCH_ASSOC);
$columnNames = [];
while (($column = $statement->fetch())) {
if ($column['Key_name'] == 'PRIMARY') {
$columnNames[] = $column['Column_name'];
}
}
return $columnNames;
}
}

View File

@@ -0,0 +1,143 @@
<?php
/*
* This file is part of DbUnit.
*
* (c) Sebastian Bergmann <sebastian@phpunit.de>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace PHPUnit\DbUnit\Database\Metadata;
/**
* Provides functionality to retrieve meta data from an Oracle database.
*/
class Oci extends AbstractMetadata
{
/**
* No character used to quote schema objects.
*
* @var string
*/
protected $schemaObjectQuoteChar = '';
/**
* The command used to perform a TRUNCATE operation.
*
* @var string
*/
protected $truncateCommand = 'TRUNCATE TABLE';
/**
* @var array
*/
protected $columns = [];
/**
* @var array
*/
protected $keys = [];
/**
* Returns an array containing the names of all the tables in the database.
*
* @return array
*/
public function getTableNames()
{
$tableNames = [];
$query = "SELECT table_name
FROM cat
WHERE table_type='TABLE'
ORDER BY table_name";
$result = $this->pdo->query($query);
while ($tableName = $result->fetchColumn(0)) {
$tableNames[] = $tableName;
}
return $tableNames;
}
/**
* Returns an array containing the names of all the columns in the
* $tableName table,
*
* @param string $tableName
*
* @return array
*/
public function getTableColumns($tableName)
{
if (!isset($this->columns[$tableName])) {
$this->loadColumnInfo($tableName);
}
return $this->columns[$tableName];
}
/**
* Returns an array containing the names of all the primary key columns in
* the $tableName table.
*
* @param string $tableName
*
* @return array
*/
public function getTablePrimaryKeys($tableName)
{
if (!isset($this->keys[$tableName])) {
$this->loadColumnInfo($tableName);
}
return $this->keys[$tableName];
}
/**
* Loads column info from a oracle database.
*
* @param string $tableName
*/
protected function loadColumnInfo($tableName)
{
$ownerQuery = '';
$conOwnerQuery = '';
$tableParts = $this->splitTableName($tableName);
$this->columns[$tableName] = [];
$this->keys[$tableName] = [];
if (!empty($tableParts['schema'])) {
$ownerQuery = " AND OWNER = '{$tableParts['schema']}'";
$conOwnerQuery = " AND a.owner = '{$tableParts['schema']}'";
}
$query = "SELECT DISTINCT COLUMN_NAME
FROM USER_TAB_COLUMNS
WHERE TABLE_NAME='" . $tableParts['table'] . "'
$ownerQuery
ORDER BY COLUMN_NAME";
$result = $this->pdo->query($query);
while ($columnName = $result->fetchColumn(0)) {
$this->columns[$tableName][] = $columnName;
}
$keyQuery = "SELECT b.column_name
FROM user_constraints a, user_cons_columns b
WHERE a.constraint_type='P'
AND a.constraint_name=b.constraint_name
$conOwnerQuery
AND a.table_name = '" . $tableParts['table'] . "' ";
$result = $this->pdo->query($keyQuery);
while ($columnName = $result->fetchColumn(0)) {
$this->keys[$tableName][] = $columnName;
}
}
}

View File

@@ -0,0 +1,155 @@
<?php
/*
* This file is part of DbUnit.
*
* (c) Sebastian Bergmann <sebastian@phpunit.de>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace PHPUnit\DbUnit\Database\Metadata;
/**
* Provides functionality to retrieve meta data from a PostgreSQL database.
*/
class PgSQL extends AbstractMetadata
{
/**
* Returns an array containing the names of all the tables in the database.
*
* @return array
*/
public function getTableNames()
{
$query = "
SELECT DISTINCT
TABLE_NAME
FROM INFORMATION_SCHEMA.TABLES
WHERE
TABLE_TYPE='BASE TABLE' AND
TABLE_SCHEMA = ?
ORDER BY TABLE_NAME
";
$statement = $this->pdo->prepare($query);
$statement->execute([$this->getSchema()]);
$tableNames = [];
while ($tableName = $statement->fetchColumn(0)) {
$tableNames[] = $tableName;
}
return $tableNames;
}
/**
* Returns an array containing the names of all the columns in the
* $tableName table,
*
* @param string $tableName
*
* @return array
*/
public function getTableColumns($tableName)
{
if (!isset($this->columns[$tableName])) {
$this->loadColumnInfo($tableName);
}
return $this->columns[$tableName];
}
/**
* Returns an array containing the names of all the primary key columns in
* the $tableName table.
*
* @param string $tableName
*
* @return array
*/
public function getTablePrimaryKeys($tableName)
{
if (!isset($this->keys[$tableName])) {
$this->loadColumnInfo($tableName);
}
return $this->keys[$tableName];
}
/**
* Loads column info from a database table.
*
* @param string $tableName
*/
protected function loadColumnInfo($tableName)
{
$this->columns[$tableName] = [];
$this->keys[$tableName] = [];
$columnQuery = '
SELECT DISTINCT
COLUMN_NAME, ORDINAL_POSITION
FROM INFORMATION_SCHEMA.COLUMNS
WHERE
TABLE_NAME = ? AND
TABLE_SCHEMA = ?
ORDER BY ORDINAL_POSITION
';
$columnStatement = $this->pdo->prepare($columnQuery);
$columnStatement->execute([$tableName, $this->getSchema()]);
while ($columName = $columnStatement->fetchColumn(0)) {
$this->columns[$tableName][] = $columName;
}
$keyQuery = "
SELECT
KCU.COLUMN_NAME,
KCU.ORDINAL_POSITION
FROM
INFORMATION_SCHEMA.KEY_COLUMN_USAGE as KCU
LEFT JOIN INFORMATION_SCHEMA.TABLE_CONSTRAINTS as TC
ON TC.TABLE_NAME = KCU.TABLE_NAME AND
TC.CONSTRAINT_NAME = KCU.CONSTRAINT_NAME
WHERE
TC.CONSTRAINT_TYPE = 'PRIMARY KEY' AND
TC.TABLE_NAME = ? AND
TC.TABLE_SCHEMA = ?
ORDER BY
KCU.ORDINAL_POSITION ASC
";
$keyStatement = $this->pdo->prepare($keyQuery);
$keyStatement->execute([$tableName, $this->getSchema()]);
while ($columName = $keyStatement->fetchColumn(0)) {
$this->keys[$tableName][] = $columName;
}
}
/**
* Returns the schema for the connection.
*
* @return string
*/
public function getSchema()
{
if (empty($this->schema)) {
return 'public';
} else {
return $this->schema;
}
}
/**
* Returns true if the rdbms allows cascading
*
* @return bool
*/
public function allowsCascading()
{
return true;
}
}

View File

@@ -0,0 +1,137 @@
<?php
/*
* This file is part of DbUnit.
*
* (c) Sebastian Bergmann <sebastian@phpunit.de>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace PHPUnit\DbUnit\Database\Metadata;
use PDO;
use PDOException;
/**
* Provides functionality to retrieve meta data from a Microsoft SQL Server database.
*/
class SqlSrv extends AbstractMetadata
{
/**
* No character used to quote schema objects.
*
* @var string
*/
protected $schemaObjectQuoteChar = '';
/**
* The command used to perform a TRUNCATE operation.
*
* @var string
*/
protected $truncateCommand = 'TRUNCATE TABLE';
/**
* Returns an array containing the names of all the tables in the database.
*
* @return array
*/
public function getTableNames()
{
$query = "SELECT name
FROM sysobjects
WHERE type='U'";
$statement = $this->pdo->prepare($query);
$statement->execute();
$tableNames = [];
while (($tableName = $statement->fetchColumn(0))) {
$tableNames[] = $tableName;
}
return $tableNames;
}
/**
* Returns an array containing the names of all the columns in the
* $tableName table.
*
* @param string $tableName
*
* @return array
*/
public function getTableColumns($tableName)
{
$query = "SELECT c.name
FROM syscolumns c
LEFT JOIN sysobjects o ON c.id = o.id
WHERE o.name = '$tableName'";
$statement = $this->pdo->prepare($query);
$statement->execute();
$columnNames = [];
while (($columnName = $statement->fetchColumn(0))) {
$columnNames[] = $columnName;
}
return $columnNames;
}
/**
* Returns an array containing the names of all the primary key columns in
* the $tableName table.
*
* @param string $tableName
*
* @return array
*/
public function getTablePrimaryKeys($tableName)
{
$query = "EXEC sp_statistics '$tableName'";
$statement = $this->pdo->prepare($query);
$statement->execute();
$statement->setFetchMode(PDO::FETCH_ASSOC);
$columnNames = [];
while (($column = $statement->fetch())) {
if ($column['TYPE'] == 1) {
$columnNames[] = $column['COLUMN_NAME'];
}
}
return $columnNames;
}
/**
* Allow overwriting identities for the given table.
*
* @param string $tableName
*/
public function disablePrimaryKeys($tableName)
{
try {
$query = "SET IDENTITY_INSERT $tableName ON";
$this->pdo->exec($query);
} catch (PDOException $e) {
// ignore the error here - can happen if primary key is not an identity
}
}
/**
* Reenable auto creation of identities for the given table.
*
* @param string $tableName
*/
public function enablePrimaryKeys($tableName)
{
try {
$query = "SET IDENTITY_INSERT $tableName OFF";
$this->pdo->exec($query);
} catch (PDOException $e) {
// ignore the error here - can happen if primary key is not an identity
}
}
}

View File

@@ -0,0 +1,110 @@
<?php
/*
* This file is part of DbUnit.
*
* (c) Sebastian Bergmann <sebastian@phpunit.de>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace PHPUnit\DbUnit\Database\Metadata;
use PDO;
use PDOStatement;
/**
* Provides functionality to retrieve meta data from an Sqlite database.
*/
class Sqlite extends AbstractMetadata
{
protected $columns = [];
protected $keys = [];
protected $truncateCommand = 'DELETE FROM';
/**
* Returns an array containing the names of all the tables in the database.
*
* @return array
*/
public function getTableNames()
{
$query = "
SELECT name
FROM sqlite_master
WHERE
type='table' AND
name <> 'sqlite_sequence'
ORDER BY name
";
$result = $this->pdo->query($query);
$tableNames = [];
while ($tableName = $result->fetchColumn(0)) {
$tableNames[] = $tableName;
}
return $tableNames;
}
/**
* Returns an array containing the names of all the columns in the
* $tableName table,
*
* @param string $tableName
*
* @return array
*/
public function getTableColumns($tableName)
{
if (!isset($this->columns[$tableName])) {
$this->loadColumnInfo($tableName);
}
return $this->columns[$tableName];
}
/**
* Returns an array containing the names of all the primary key columns in
* the $tableName table.
*
* @param string $tableName
*
* @return array
*/
public function getTablePrimaryKeys($tableName)
{
if (!isset($this->keys[$tableName])) {
$this->loadColumnInfo($tableName);
}
return $this->keys[$tableName];
}
/**
* Loads column info from a sqlite database.
*
* @param string $tableName
*/
protected function loadColumnInfo($tableName)
{
$query = "PRAGMA table_info('{$tableName}')";
$statement = $this->pdo->query($query);
/* @var $statement PDOStatement */
$this->columns[$tableName] = [];
$this->keys[$tableName] = [];
while ($columnData = $statement->fetch(PDO::FETCH_NUM)) {
$this->columns[$tableName][] = $columnData[1];
if ((int) $columnData[5] !== 0) {
$this->keys[$tableName][] = $columnData[1];
}
}
}
}

View File

@@ -0,0 +1,26 @@
<?php
/*
* This file is part of DbUnit.
*
* (c) Sebastian Bergmann <sebastian@phpunit.de>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace PHPUnit\DbUnit\Database\Metadata;
use PHPUnit\DbUnit\DataSet\DefaultTableMetadata;
/**
* This class loads a table metadata object with database metadata.
*/
class Table extends DefaultTableMetadata
{
public function __construct($tableName, Metadata $databaseMetaData)
{
$this->tableName = $tableName;
$this->columns = $databaseMetaData->getTableColumns($tableName);
$this->primaryKeys = $databaseMetaData->getTablePrimaryKeys($tableName);
}
}

View File

@@ -0,0 +1,46 @@
<?php
/*
* This file is part of DbUnit.
*
* (c) Sebastian Bergmann <sebastian@phpunit.de>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace PHPUnit\DbUnit\Database;
use PDO;
use PDOStatement;
use PHPUnit\DbUnit\DataSet\AbstractTable;
use PHPUnit\DbUnit\DataSet\DefaultTableMetadata;
/**
* Provides the functionality to represent a database result set as a DBUnit
* table.
*
* @deprecated The PHPUnit_Extension_Database_DataSet_QueryTable should be used instead
* @see PHPUnit_Extension_Database_DataSet_QueryTable
* @see PHPUnit_Extension_Database_DataSet_QueryDataSet
*/
class ResultSetTable extends AbstractTable
{
/**
* Creates a new result set table.
*
* @param string $tableName
* @param PDOStatement $pdoStatement
*/
public function __construct($tableName, PDOStatement $pdoStatement)
{
$this->data = $pdoStatement->fetchAll(PDO::FETCH_ASSOC);
if (count($this->data)) {
$columns = array_keys($this->data[0]);
} else {
$columns = [];
}
$this->setTableMetaData(new DefaultTableMetadata($tableName, $columns));
}
}

View File

@@ -0,0 +1,36 @@
<?php
/*
* This file is part of DbUnit.
*
* (c) Sebastian Bergmann <sebastian@phpunit.de>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace PHPUnit\DbUnit\Database;
use PDO;
use PHPUnit\DbUnit\DataSet\AbstractTable;
use PHPUnit\DbUnit\DataSet\ITableMetadata;
/**
* Provides the functionality to represent a database table.
*/
class Table extends AbstractTable
{
/**
* Creates a new database table object.
*
* @param ITableMetadata $tableMetaData
* @param Connection $databaseConnection
*/
public function __construct(ITableMetadata $tableMetaData, Connection $databaseConnection)
{
$this->setTableMetaData($tableMetaData);
$pdoStatement = $databaseConnection->getConnection()->prepare(DataSet::buildTableSelect($tableMetaData, $databaseConnection));
$pdoStatement->execute();
$this->data = $pdoStatement->fetchAll(PDO::FETCH_ASSOC);
}
}

View File

@@ -0,0 +1,128 @@
<?php
/*
* This file is part of DbUnit.
*
* (c) Sebastian Bergmann <sebastian@phpunit.de>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace PHPUnit\DbUnit\Database;
use PHPUnit\DbUnit\DataSet\ITable;
use PHPUnit\DbUnit\DataSet\ITableIterator;
use PHPUnit\DbUnit\DataSet\ITableMetadata;
/**
* Provides iterative access to tables from a database instance.
*/
class TableIterator implements ITableIterator
{
/**
* An array of tablenames.
*
* @var array
*/
protected $tableNames;
/**
* If this property is true then the tables will be iterated in reverse
* order.
*
* @var bool
*/
protected $reverse;
/**
* The database dataset that this iterator iterates over.
*
* @var DataSet
*/
protected $dataSet;
public function __construct($tableNames, DataSet $dataSet, $reverse = false)
{
$this->tableNames = $tableNames;
$this->dataSet = $dataSet;
$this->reverse = $reverse;
$this->rewind();
}
/**
* Returns the current table.
*
* @return ITable
*/
public function getTable()
{
return $this->current();
}
/**
* Returns the current table's meta data.
*
* @return ITableMetadata
*/
public function getTableMetaData()
{
return $this->current()->getTableMetaData();
}
/**
* Returns the current table.
*
* @return ITable
*/
public function current()
{
$tableName = current($this->tableNames);
return $this->dataSet->getTable($tableName);
}
/**
* Returns the name of the current table.
*
* @return string
*/
public function key()
{
return $this->current()->getTableMetaData()->getTableName();
}
/**
* advances to the next element.
*/
public function next()
{
if ($this->reverse) {
prev($this->tableNames);
} else {
next($this->tableNames);
}
}
/**
* Rewinds to the first element
*/
public function rewind()
{
if ($this->reverse) {
end($this->tableNames);
} else {
reset($this->tableNames);
}
}
/**
* Returns true if the current index is valid
*
* @return bool
*/
public function valid()
{
return (current($this->tableNames) !== false);
}
}

View File

@@ -0,0 +1,24 @@
<?php
/*
* This file is part of DbUnit.
*
* (c) Sebastian Bergmann <sebastian@phpunit.de>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace PHPUnit\DbUnit;
/**
* An interface for classes that require a list of databases to operate.
*/
interface DatabaseListConsumer
{
/**
* Sets the database for the spec
*
* @param array $databases
*/
public function setDatabases(array $databases);
}

View File

@@ -0,0 +1,47 @@
<?php
/*
* This file is part of DbUnit.
*
* (c) Sebastian Bergmann <sebastian@phpunit.de>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace PHPUnit\DbUnit;
use PHPUnit\DbUnit\Database\Connection;
/**
* This is the default implementation of the database tester. It receives its
* connection object from the constructor.
*/
class DefaultTester extends AbstractTester
{
/**
* @var Connection
*/
protected $connection;
/**
* Creates a new default database tester using the given connection.
*
* @param Connection $connection
*/
public function __construct(Connection $connection)
{
parent::__construct();
$this->connection = $connection;
}
/**
* Returns the test database connection.
*
* @return Connection
*/
public function getConnection()
{
return $this->connection;
}
}

View File

@@ -0,0 +1,15 @@
<?php
/*
* This file is part of DbUnit.
*
* (c) Sebastian Bergmann <sebastian@phpunit.de>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace PHPUnit\DbUnit;
interface Exception
{
}

View File

@@ -0,0 +1,15 @@
<?php
/*
* This file is part of DbUnit.
*
* (c) Sebastian Bergmann <sebastian@phpunit.de>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace PHPUnit\DbUnit;
class InvalidArgumentException extends \InvalidArgumentException implements Exception
{
}

View File

@@ -0,0 +1,15 @@
<?php
/*
* This file is part of DbUnit.
*
* (c) Sebastian Bergmann <sebastian@phpunit.de>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace PHPUnit\DbUnit;
class RuntimeException extends \RuntimeException implements Exception
{
}

View File

@@ -0,0 +1,57 @@
<?php
/*
* This file is part of DbUnit.
*
* (c) Sebastian Bergmann <sebastian@phpunit.de>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace PHPUnit\DbUnit\Operation;
use PHPUnit\DbUnit\Database\Connection;
use PHPUnit\DbUnit\DataSet\IDataSet;
use PHPUnit\DbUnit\InvalidArgumentException;
/**
* This class facilitates combining database operations. To create a composite
* operation pass an array of classes that implement
* PHPUnit_Extensions_Database_Operation_IDatabaseOperation and they will be
* executed in that order against all data sets.
*/
class Composite implements Operation
{
/**
* @var array
*/
protected $operations = [];
/**
* Creates a composite operation.
*
* @param array $operations
*/
public function __construct(array $operations)
{
foreach ($operations as $operation) {
if ($operation instanceof Operation) {
$this->operations[] = $operation;
} else {
throw new InvalidArgumentException('Only database operation instances can be passed to a composite database operation.');
}
}
}
public function execute(Connection $connection, IDataSet $dataSet)
{
try {
foreach ($this->operations as $operation) {
/* @var $operation Operation */
$operation->execute($connection, $dataSet);
}
} catch (Exception $e) {
throw new Exception("COMPOSITE[{$e->getOperation()}]", $e->getQuery(), $e->getArgs(), $e->getTable(), $e->getError());
}
}
}

View File

@@ -0,0 +1,49 @@
<?php
/*
* This file is part of DbUnit.
*
* (c) Sebastian Bergmann <sebastian@phpunit.de>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace PHPUnit\DbUnit\Operation;
use PHPUnit\DbUnit\Database\Connection;
use PHPUnit\DbUnit\DataSet\ITable;
use PHPUnit\DbUnit\DataSet\ITableMetadata;
/**
* Deletes the rows in a given dataset using primary key columns.
*/
class Delete extends RowBased
{
protected $operationName = 'DELETE';
protected $iteratorDirection = self::ITERATOR_TYPE_REVERSE;
protected function buildOperationQuery(ITableMetadata $databaseTableMetaData, ITable $table, Connection $connection)
{
$keys = $databaseTableMetaData->getPrimaryKeys();
$whereStatement = 'WHERE ' . implode(' AND ', $this->buildPreparedColumnArray($keys, $connection));
$query = "
DELETE FROM {$connection->quoteSchemaObject($table->getTableMetaData()->getTableName())}
{$whereStatement}
";
return $query;
}
protected function buildOperationArguments(ITableMetadata $databaseTableMetaData, ITable $table, $row)
{
$args = [];
foreach ($databaseTableMetaData->getPrimaryKeys() as $columnName) {
$args[] = $table->getValue($row, $columnName);
}
return $args;
}
}

View File

@@ -0,0 +1,39 @@
<?php
/*
* This file is part of DbUnit.
*
* (c) Sebastian Bergmann <sebastian@phpunit.de>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace PHPUnit\DbUnit\Operation;
use PDOException;
use PHPUnit\DbUnit\Database\Connection;
use PHPUnit\DbUnit\DataSet\IDataSet;
use PHPUnit\DbUnit\DataSet\ITable;
/**
* Deletes all rows from all tables in a dataset.
*/
class DeleteAll implements Operation
{
public function execute(Connection $connection, IDataSet $dataSet)
{
foreach ($dataSet->getReverseIterator() as $table) {
/* @var $table ITable */
$query = "
DELETE FROM {$connection->quoteSchemaObject($table->getTableMetaData()->getTableName())}
";
try {
$connection->getConnection()->query($query);
} catch (PDOException $e) {
throw new Exception('DELETE_ALL', $query, [], $table, $e->getMessage());
}
}
}
}

View File

@@ -0,0 +1,91 @@
<?php
/*
* This file is part of DbUnit.
*
* (c) Sebastian Bergmann <sebastian@phpunit.de>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace PHPUnit\DbUnit\Operation;
use PHPUnit\DbUnit\DataSet\ITable;
use PHPUnit\DbUnit\RuntimeException;
/**
* Thrown for exceptions encountered with database operations. Provides
* information regarding which operations failed and the query (if any) it
* failed on.
*/
class Exception extends RuntimeException
{
/**
* @var string
*/
protected $operation;
/**
* @var string
*/
protected $preparedQuery;
/**
* @var array
*/
protected $preparedArgs;
/**
* @var ITable
*/
protected $table;
/**
* @var string
*/
protected $error;
/**
* Creates a new dbunit operation exception
*
* @param string $operation
* @param string $current_query
* @param ITable $current_table
* @param string $error
*/
public function __construct($operation, $current_query, $current_args, $current_table, $error)
{
parent::__construct("{$operation} operation failed on query: {$current_query} using args: " . print_r($current_args, true) . " [{$error}]");
$this->operation = $operation;
$this->preparedQuery = $current_query;
$this->preparedArgs = $current_args;
$this->table = $current_table;
$this->error = $error;
}
public function getOperation()
{
return $this->operation;
}
public function getQuery()
{
return $this->preparedQuery;
}
public function getTable()
{
return $this->table;
}
public function getArgs()
{
return $this->preparedArgs;
}
public function getError()
{
return $this->error;
}
}

View File

@@ -0,0 +1,98 @@
<?php
/*
* This file is part of DbUnit.
*
* (c) Sebastian Bergmann <sebastian@phpunit.de>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace PHPUnit\DbUnit\Operation;
/**
* A class factory to easily return database operations.
*/
class Factory
{
/**
* Returns a null database operation
*
* @return Operation
*/
public static function NONE()
{
return new None();
}
/**
* Returns a clean insert database operation. It will remove all contents
* from the table prior to re-inserting rows.
*
* @param bool $cascadeTruncates Set to true to force truncates to cascade on databases that support this.
*
* @return Operation
*/
public static function CLEAN_INSERT($cascadeTruncates = false)
{
return new Composite([
self::TRUNCATE($cascadeTruncates),
self::INSERT()
]);
}
/**
* Returns an insert database operation.
*
* @return Operation
*/
public static function INSERT()
{
return new Insert();
}
/**
* Returns a truncate database operation.
*
* @param bool $cascadeTruncates Set to true to force truncates to cascade on databases that support this.
*
* @return Operation
*/
public static function TRUNCATE($cascadeTruncates = false)
{
$truncate = new Truncate();
$truncate->setCascade($cascadeTruncates);
return $truncate;
}
/**
* Returns a delete database operation.
*
* @return Operation
*/
public static function DELETE()
{
return new Delete();
}
/**
* Returns a delete_all database operation.
*
* @return Operation
*/
public static function DELETE_ALL()
{
return new DeleteAll();
}
/**
* Returns an update database operation.
*
* @return Operation
*/
public static function UPDATE()
{
return new Update();
}
}

View File

@@ -0,0 +1,69 @@
<?php
/*
* This file is part of DbUnit.
*
* (c) Sebastian Bergmann <sebastian@phpunit.de>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace PHPUnit\DbUnit\Operation;
use PHPUnit\DbUnit\Database\Connection;
use PHPUnit\DbUnit\DataSet\ITable;
use PHPUnit\DbUnit\DataSet\ITableMetadata;
/**
* This class provides functionality for inserting rows from a dataset into a database.
*/
class Insert extends RowBased
{
protected $operationName = 'INSERT';
protected function buildOperationQuery(ITableMetadata $databaseTableMetaData, ITable $table, Connection $connection)
{
$columnCount = count($table->getTableMetaData()->getColumns());
if ($columnCount > 0) {
$placeHolders = implode(', ', array_fill(0, $columnCount, '?'));
$columns = '';
foreach ($table->getTableMetaData()->getColumns() as $column) {
$columns .= $connection->quoteSchemaObject($column) . ', ';
}
$columns = substr($columns, 0, -2);
$query = "
INSERT INTO {$connection->quoteSchemaObject($table->getTableMetaData()->getTableName())}
({$columns})
VALUES
({$placeHolders})
";
return $query;
} else {
return false;
}
}
protected function buildOperationArguments(ITableMetadata $databaseTableMetaData, ITable $table, $row)
{
$args = [];
foreach ($table->getTableMetaData()->getColumns() as $columnName) {
$args[] = $table->getValue($row, $columnName);
}
return $args;
}
protected function disablePrimaryKeys(ITableMetadata $databaseTableMetaData, ITable $table, Connection $connection)
{
if (count($databaseTableMetaData->getPrimaryKeys())) {
return true;
}
return false;
}
}

View File

@@ -0,0 +1,25 @@
<?php
/*
* This file is part of DbUnit.
*
* (c) Sebastian Bergmann <sebastian@phpunit.de>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace PHPUnit\DbUnit\Operation;
use PHPUnit\DbUnit\Database\Connection;
use PHPUnit\DbUnit\DataSet\IDataSet;
/**
* This class represents a null database operation.
*/
class None implements Operation
{
public function execute(Connection $connection, IDataSet $dataSet)
{
/* do nothing */
}
}

View File

@@ -0,0 +1,32 @@
<?php
/*
* This file is part of DbUnit.
*
* (c) Sebastian Bergmann <sebastian@phpunit.de>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace PHPUnit\DbUnit\Operation;
use PHPUnit\DbUnit\Database\Connection;
use PHPUnit\DbUnit\DataSet\IDataSet;
/**
* Provides a basic interface and functionality for executing database
* operations against a connection using a specific dataSet.
*/
interface Operation
{
/**
* Executes the database operation against the given $connection for the
* given $dataSet.
*
* @param Connection $connection
* @param IDataSet $dataSet
*
* @throws Exception
*/
public function execute(Connection $connection, IDataSet $dataSet);
}

View File

@@ -0,0 +1,104 @@
<?php
/*
* This file is part of DbUnit.
*
* (c) Sebastian Bergmann <sebastian@phpunit.de>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace PHPUnit\DbUnit\Operation;
use PHPUnit\DbUnit\Database\Connection;
use PHPUnit\DbUnit\DataSet\IDataSet;
use PHPUnit\DbUnit\DataSet\ITable;
use PHPUnit\DbUnit\DataSet\ITableMetadata;
/**
* Updates the rows in a given dataset using primary key columns.
*/
class Replace extends RowBased
{
protected $operationName = 'REPLACE';
protected function buildOperationQuery(ITableMetadata $databaseTableMetaData, ITable $table, Connection $connection)
{
$keys = $databaseTableMetaData->getPrimaryKeys();
$whereStatement = 'WHERE ' . implode(' AND ', $this->buildPreparedColumnArray($keys, $connection));
$query = "
SELECT COUNT(*)
FROM {$connection->quoteSchemaObject($table->getTableMetaData()->getTableName())}
{$whereStatement}
";
return $query;
}
protected function buildOperationArguments(ITableMetadata $databaseTableMetaData, ITable $table, $row)
{
$args = [];
foreach ($databaseTableMetaData->getPrimaryKeys() as $columnName) {
$args[] = $table->getValue($row, $columnName);
}
return $args;
}
/**
* @param Connection $connection
* @param IDataSet $dataSet
*/
public function execute(Connection $connection, IDataSet $dataSet)
{
$insertOperation = new Insert;
$updateOperation = new Update;
$databaseDataSet = $connection->createDataSet();
foreach ($dataSet as $table) {
/* @var $table ITable */
$databaseTableMetaData = $databaseDataSet->getTableMetaData($table->getTableMetaData()->getTableName());
$insertQuery = $insertOperation->buildOperationQuery($databaseTableMetaData, $table, $connection);
$updateQuery = $updateOperation->buildOperationQuery($databaseTableMetaData, $table, $connection);
$selectQuery = $this->buildOperationQuery($databaseTableMetaData, $table, $connection);
$insertStatement = $connection->getConnection()->prepare($insertQuery);
$updateStatement = $connection->getConnection()->prepare($updateQuery);
$selectStatement = $connection->getConnection()->prepare($selectQuery);
$rowCount = $table->getRowCount();
for ($i = 0; $i < $rowCount; $i++) {
$selectArgs = $this->buildOperationArguments($databaseTableMetaData, $table, $i);
$query = $selectQuery;
$args = $selectArgs;
try {
$selectStatement->execute($selectArgs);
if ($selectStatement->fetchColumn(0) > 0) {
$updateArgs = $updateOperation->buildOperationArguments($databaseTableMetaData, $table, $i);
$query = $updateQuery;
$args = $updateArgs;
$updateStatement->execute($updateArgs);
} else {
$insertArgs = $insertOperation->buildOperationArguments($databaseTableMetaData, $table, $i);
$query = $insertQuery;
$args = $insertArgs;
$insertStatement->execute($insertArgs);
}
} catch (Exception $e) {
throw new Exception(
$this->operationName, $query, $args, $table, $e->getMessage()
);
}
}
}
}
}

View File

@@ -0,0 +1,117 @@
<?php
/*
* This file is part of DbUnit.
*
* (c) Sebastian Bergmann <sebastian@phpunit.de>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace PHPUnit\DbUnit\Operation;
use PHPUnit\DbUnit\Database\Connection;
use PHPUnit\DbUnit\DataSet\IDataSet;
use PHPUnit\DbUnit\DataSet\ITable;
use PHPUnit\DbUnit\DataSet\ITableMetadata;
/**
* Provides basic functionality for row based operations.
*
* To create a row based operation you must create two functions. The first
* one, buildOperationQuery(), must return a query that will be used to create
* a prepared statement. The second one, buildOperationArguments(), should
* return an array containing arguments for each row.
*/
abstract class RowBased implements Operation
{
const ITERATOR_TYPE_FORWARD = 0;
const ITERATOR_TYPE_REVERSE = 1;
protected $operationName;
protected $iteratorDirection = self::ITERATOR_TYPE_FORWARD;
/**
* @return string|bool String containing the query or FALSE if a valid query cannot be constructed
*/
abstract protected function buildOperationQuery(ITableMetadata $databaseTableMetaData, ITable $table, Connection $connection);
abstract protected function buildOperationArguments(ITableMetadata $databaseTableMetaData, ITable $table, $row);
/**
* Allows an operation to disable primary keys if necessary.
*
* @param ITableMetadata $databaseTableMetaData
* @param ITable $table
* @param Connection $connection
*/
protected function disablePrimaryKeys(ITableMetadata $databaseTableMetaData, ITable $table, Connection $connection)
{
return false;
}
/**
* @param Connection $connection
* @param IDataSet $dataSet
*/
public function execute(Connection $connection, IDataSet $dataSet)
{
$databaseDataSet = $connection->createDataSet();
$dsIterator = $this->iteratorDirection == self::ITERATOR_TYPE_REVERSE ? $dataSet->getReverseIterator() : $dataSet->getIterator();
foreach ($dsIterator as $table) {
$rowCount = $table->getRowCount();
if ($rowCount == 0) {
continue;
}
/* @var $table ITable */
$databaseTableMetaData = $databaseDataSet->getTableMetaData($table->getTableMetaData()->getTableName());
$query = $this->buildOperationQuery($databaseTableMetaData, $table, $connection);
$disablePrimaryKeys = $this->disablePrimaryKeys($databaseTableMetaData, $table, $connection);
if ($query === false) {
if ($table->getRowCount() > 0) {
throw new Exception($this->operationName, '', [], $table, 'Rows requested for insert, but no columns provided!');
}
continue;
}
if ($disablePrimaryKeys) {
$connection->disablePrimaryKeys($databaseTableMetaData->getTableName());
}
$statement = $connection->getConnection()->prepare($query);
for ($i = 0; $i < $rowCount; $i++) {
$args = $this->buildOperationArguments($databaseTableMetaData, $table, $i);
try {
$statement->execute($args);
} catch (Exception $e) {
throw new Exception(
$this->operationName, $query, $args, $table, $e->getMessage()
);
}
}
if ($disablePrimaryKeys) {
$connection->enablePrimaryKeys($databaseTableMetaData->getTableName());
}
}
}
protected function buildPreparedColumnArray($columns, Connection $connection)
{
$columnArray = [];
foreach ($columns as $columnName) {
$columnArray[] = "{$connection->quoteSchemaObject($columnName)} = ?";
}
return $columnArray;
}
}

View File

@@ -0,0 +1,77 @@
<?php
/*
* This file is part of DbUnit.
*
* (c) Sebastian Bergmann <sebastian@phpunit.de>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace PHPUnit\DbUnit\Operation;
use PDO;
use PDOException;
use PHPUnit\DbUnit\Database\Connection;
use PHPUnit\DbUnit\DataSet\IDataSet;
use PHPUnit\DbUnit\DataSet\ITable;
/**
* Executes a truncate against all tables in a dataset.
*/
class Truncate implements Operation
{
protected $useCascade = false;
public function setCascade($cascade = true)
{
$this->useCascade = $cascade;
}
public function execute(Connection $connection, IDataSet $dataSet)
{
foreach ($dataSet->getReverseIterator() as $table) {
/* @var $table ITable */
$query = "
{$connection->getTruncateCommand()} {$connection->quoteSchemaObject($table->getTableMetaData()->getTableName())}
";
if ($this->useCascade && $connection->allowsCascading()) {
$query .= ' CASCADE';
}
try {
$this->disableForeignKeyChecksForMysql($connection);
$connection->getConnection()->query($query);
$this->enableForeignKeyChecksForMysql($connection);
} catch (\Exception $e) {
$this->enableForeignKeyChecksForMysql($connection);
if ($e instanceof PDOException) {
throw new Exception('TRUNCATE', $query, [], $table, $e->getMessage());
}
throw $e;
}
}
}
private function disableForeignKeyChecksForMysql(Connection $connection)
{
if ($this->isMysql($connection)) {
$connection->getConnection()->query('SET FOREIGN_KEY_CHECKS = 0');
}
}
private function enableForeignKeyChecksForMysql(Connection $connection)
{
if ($this->isMysql($connection)) {
$connection->getConnection()->query('SET FOREIGN_KEY_CHECKS = 1');
}
}
private function isMysql(Connection $connection)
{
return $connection->getConnection()->getAttribute(PDO::ATTR_DRIVER_NAME) == 'mysql';
}
}

View File

@@ -0,0 +1,62 @@
<?php
/*
* This file is part of DbUnit.
*
* (c) Sebastian Bergmann <sebastian@phpunit.de>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace PHPUnit\DbUnit\Operation;
use PHPUnit\DbUnit\Database\Connection;
use PHPUnit\DbUnit\DataSet\ITable;
use PHPUnit\DbUnit\DataSet\ITableMetadata;
/**
* Updates the rows in a given dataset using primary key columns.
*/
class Update extends RowBased
{
protected $operationName = 'UPDATE';
protected function buildOperationQuery(ITableMetadata $databaseTableMetaData, ITable $table, Connection $connection)
{
$keys = $databaseTableMetaData->getPrimaryKeys();
$columns = $table->getTableMetaData()->getColumns();
$whereStatement = 'WHERE ' . implode(' AND ', $this->buildPreparedColumnArray($keys, $connection));
$setStatement = 'SET ' . implode(', ', $this->buildPreparedColumnArray($columns, $connection));
$query = "
UPDATE {$connection->quoteSchemaObject($table->getTableMetaData()->getTableName())}
{$setStatement}
{$whereStatement}
";
return $query;
}
protected function buildOperationArguments(ITableMetadata $databaseTableMetaData, ITable $table, $row)
{
$args = [];
foreach ($table->getTableMetaData()->getColumns() as $columnName) {
$args[] = $table->getValue($row, $columnName);
}
foreach ($databaseTableMetaData->getPrimaryKeys() as $columnName) {
$args[] = $table->getValue($row, $columnName);
}
return $args;
}
protected function disablePrimaryKeys(ITableMetadata $databaseTableMetaData, ITable $table, Connection $connection)
{
if (count($databaseTableMetaData->getPrimaryKeys())) {
return true;
}
return false;
}
}

20
vendor/phpunit/dbunit/src/TestCase.php vendored Normal file
View File

@@ -0,0 +1,20 @@
<?php
/*
* This file is part of DbUnit.
*
* (c) Sebastian Bergmann <sebastian@phpunit.de>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace PHPUnit\DbUnit;
/**
* A TestCase extension that provides functionality for testing and asserting
* against a real database.
*/
abstract class TestCase extends \PHPUnit\Framework\TestCase
{
use TestCaseTrait;
}

View File

@@ -0,0 +1,273 @@
<?php
/*
* This file is part of DbUnit.
*
* (c) Sebastian Bergmann <sebastian@phpunit.de>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace PHPUnit\DbUnit;
use PDO;
use PHPUnit\DbUnit\Constraint\DataSetIsEqual;
use PHPUnit\DbUnit\Constraint\TableIsEqual;
use PHPUnit\DbUnit\Constraint\TableRowCount;
use PHPUnit\DbUnit\Database\Connection;
use PHPUnit\DbUnit\Database\DefaultConnection;
use PHPUnit\DbUnit\DataSet\ArrayDataSet;
use PHPUnit\DbUnit\DataSet\FlatXmlDataSet;
use PHPUnit\DbUnit\DataSet\IDataSet;
use PHPUnit\DbUnit\DataSet\ITable;
use PHPUnit\DbUnit\DataSet\MysqlXmlDataSet;
use PHPUnit\DbUnit\DataSet\XmlDataSet;
use PHPUnit\DbUnit\Operation\Factory;
use PHPUnit\DbUnit\Operation\Operation;
trait TestCaseTrait
{
/**
* @var Tester
*/
protected $databaseTester;
/**
* Closes the specified connection.
*
* @param Connection $connection
*/
protected function closeConnection(Connection $connection)
{
$this->getDatabaseTester()->closeConnection($connection);
}
/**
* Returns the test database connection.
*
* @return Connection
*/
abstract protected function getConnection();
/**
* Gets the IDatabaseTester for this testCase. If the IDatabaseTester is
* not set yet, this method calls newDatabaseTester() to obtain a new
* instance.
*
* @return Tester
*/
protected function getDatabaseTester()
{
if (empty($this->databaseTester)) {
$this->databaseTester = $this->newDatabaseTester();
}
return $this->databaseTester;
}
/**
* Returns the test dataset.
*
* @return IDataSet
*/
abstract protected function getDataSet();
/**
* Returns the database operation executed in test setup.
*
* @return Operation
*/
protected function getSetUpOperation()
{
return Factory::CLEAN_INSERT();
}
/**
* Returns the database operation executed in test cleanup.
*
* @return Operation
*/
protected function getTearDownOperation()
{
return Factory::NONE();
}
/**
* Creates a IDatabaseTester for this testCase.
*
* @return Tester
*/
protected function newDatabaseTester()
{
return new DefaultTester($this->getConnection());
}
/**
* Creates a new DefaultDatabaseConnection using the given PDO connection
* and database schema name.
*
* @param PDO $connection
* @param string $schema
*
* @return DefaultConnection
*/
protected function createDefaultDBConnection(PDO $connection, $schema = '')
{
return new DefaultConnection($connection, $schema);
}
/**
* Creates a new ArrayDataSet with the given array.
* The array parameter is an associative array of tables where the key is
* the table name and the value an array of rows. Each row is an associative
* array by itself with keys representing the field names and the values the
* actual data.
* For example:
* array(
* "addressbook" => array(
* array("id" => 1, "name" => "...", "address" => "..."),
* array("id" => 2, "name" => "...", "address" => "...")
* )
* )
*
* @param array $data
*
* @return ArrayDataSet
*/
protected function createArrayDataSet(array $data)
{
return new ArrayDataSet($data);
}
/**
* Creates a new FlatXmlDataSet with the given $xmlFile. (absolute path.)
*
* @param string $xmlFile
*
* @return FlatXmlDataSet
*/
protected function createFlatXMLDataSet($xmlFile)
{
return new FlatXmlDataSet($xmlFile);
}
/**
* Creates a new XMLDataSet with the given $xmlFile. (absolute path.)
*
* @param string $xmlFile
*
* @return XmlDataSet
*/
protected function createXMLDataSet($xmlFile)
{
return new XmlDataSet($xmlFile);
}
/**
* Create a a new MysqlXmlDataSet with the given $xmlFile. (absolute path.)
*
* @param string $xmlFile
*
* @return MysqlXmlDataSet
*/
protected function createMySQLXMLDataSet($xmlFile)
{
return new MysqlXmlDataSet($xmlFile);
}
/**
* Returns an operation factory instance that can be used to instantiate
* new operations.
*
* @return Factory
*/
protected function getOperations()
{
return new Factory();
}
/**
* Performs operation returned by getSetUpOperation().
*/
protected function setUp()
{
parent::setUp();
$this->databaseTester = null;
$this->getDatabaseTester()->setSetUpOperation($this->getSetUpOperation());
$this->getDatabaseTester()->setDataSet($this->getDataSet());
$this->getDatabaseTester()->onSetUp();
}
/**
* Performs operation returned by getTearDownOperation().
*/
protected function tearDown()
{
$this->getDatabaseTester()->setTearDownOperation($this->getTearDownOperation());
$this->getDatabaseTester()->setDataSet($this->getDataSet());
$this->getDatabaseTester()->onTearDown();
/*
* Destroy the tester after the test is run to keep DB connections
* from piling up.
*/
$this->databaseTester = null;
}
/**
* Asserts that two given tables are equal.
*
* @param ITable $expected
* @param ITable $actual
* @param string $message
*/
public static function assertTablesEqual(ITable $expected, ITable $actual, $message = '')
{
$constraint = new TableIsEqual($expected);
self::assertThat($actual, $constraint, $message);
}
/**
* Asserts that two given datasets are equal.
*
* @param ITable $expected
* @param ITable $actual
* @param string $message
*/
public static function assertDataSetsEqual(IDataSet $expected, IDataSet $actual, $message = '')
{
$constraint = new DataSetIsEqual($expected);
self::assertThat($actual, $constraint, $message);
}
/**
* Assert that a given table has a given amount of rows
*
* @param string $tableName Name of the table
* @param int $expected Expected amount of rows in the table
* @param string $message Optional message
*/
public function assertTableRowCount($tableName, $expected, $message = '')
{
$constraint = new TableRowCount($tableName, $expected);
$actual = $this->getConnection()->getRowCount($tableName);
self::assertThat($actual, $constraint, $message);
}
/**
* Asserts that a given table contains a given row
*
* @param array $expectedRow Row expected to find
* @param ITable $table Table to look into
* @param string $message Optional message
*/
public function assertTableContains(array $expectedRow, ITable $table, $message = '')
{
self::assertThat($table->assertContainsRow($expectedRow), self::isTrue(), $message);
}
}

82
vendor/phpunit/dbunit/src/Tester.php vendored Normal file
View File

@@ -0,0 +1,82 @@
<?php
/*
* This file is part of DbUnit.
*
* (c) Sebastian Bergmann <sebastian@phpunit.de>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace PHPUnit\DbUnit;
use PHPUnit\DbUnit\Database\Connection;
use PHPUnit\DbUnit\DataSet\IDataSet;
use PHPUnit\DbUnit\Operation\Operation;
/**
* This is the interface for DatabaseTester objects. These objects are used to
* add database testing to existing test cases using composition instead of
* extension.
*/
interface Tester
{
/**
* Closes the specified connection.
*
* @param Connection $connection
*/
public function closeConnection(Connection $connection);
/**
* Returns the test database connection.
*
* @return Connection
*/
public function getConnection();
/**
* Returns the test dataset.
*
* @return IDataSet
*/
public function getDataSet();
/**
* TestCases must call this method inside setUp().
*/
public function onSetUp();
/**
* TestCases must call this method inside tearDown().
*/
public function onTearDown();
/**
* Sets the test dataset to use.
*
* @param IDataSet $dataSet
*/
public function setDataSet(IDataSet $dataSet);
/**
* Sets the schema value.
*
* @param string $schema
*/
public function setSchema($schema);
/**
* Sets the DatabaseOperation to call when starting the test.
*
* @param Operation $setUpOperation
*/
public function setSetUpOperation(Operation $setUpOperation);
/**
* Sets the DatabaseOperation to call when stopping the test.
*
* @param Operation $tearDownOperation
*/
public function setTearDownOperation(Operation $tearDownOperation);
}