Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
36 changes: 36 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
name: CI

on: [push]

jobs:
build:
runs-on: ubuntu-latest

steps:
- uses: actions/checkout@v3

- name: Composer install
uses: php-actions/composer@v6
with:
php_version: 8.1

- name: PHP Code Sniffer
uses: php-actions/phpcs@v1
with:
php_version: 8.1
path: src/
standard: PSR12
exclude: Generic.Files.LineLength

- name: PHPStan
uses: php-actions/phpstan@v3
with:
php_version: 8.1
path: src/
level: max

# Add a test script to composer.json, for instance: "test": "vendor/bin/phpunit"
# Docs: https://getcomposer.org/doc/articles/scripts.md

# - name: Run test suite
# run: composer run-script test
8 changes: 5 additions & 3 deletions composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -10,11 +10,13 @@
}
],
"require": {
"php": ">=5.5",
"nette/database": "~2.4"
"php": ">=8.0",
"ext-pdo": "*",
"nette/database": "~3.1"
},
"require-dev": {
"phpunit/phpunit": "^6.0",
"ramsey/uuid": "^4.7",
"phpunit/phpunit": "^9.5",
"squizlabs/php_codesniffer": "^3.0"
},
"autoload": {
Expand Down
226 changes: 98 additions & 128 deletions src/ActiveRow.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,25 +4,23 @@

namespace SimpleMapper;

use Nette\Database\Table\Selection as NetteDatabaseSelection;
use Nette\Database\Table\ActiveRow as NetteDatabaseActiveRow;
use ArrayIterator;
use Iterator;
use IteratorAggregate;
use Nette\Database\Table\ActiveRow as NetteDatabaseActiveRow;
use Nette\Database\Table\IRow;
use Nette\DeprecatedException;
use Nette\Database\Table\Selection as NetteDatabaseSelection;
use Nette\MemberAccessException;
use SimpleMapper\Exception\ActiveRowException;
use SimpleMapper\Exception\DeprecatedException;
use SimpleMapper\Structure\Structure;

class ActiveRow implements IteratorAggregate, IRow
{
/** @var NetteDatabaseActiveRow */
protected $record;
protected NetteDatabaseActiveRow $record;

/** @var Structure */
protected $structure;
protected Structure $structure;

/** @var ActiveRow|null */
protected $referencingRecord;
protected ?ActiveRow $referencingRecord = null;

/**
* @param NetteDatabaseActiveRow $record
Expand All @@ -34,106 +32,47 @@ public function __construct(NetteDatabaseActiveRow $record, Structure $structure
$this->structure = $structure;
}

/**
* @param string $name
* @return mixed|ActiveRow
*/
public function __get($name)
{
$result = $this->record->$name;
return $result instanceof IRow ? $this->prepareRecord($result) : $result;
}
/**********************************************************************\
* Wrapper function
\**********************************************************************/

/**
* @return NetteDatabaseActiveRow
* @throws ActiveRowException
*/
public function getRecord(): NetteDatabaseActiveRow
public function setTable(NetteDatabaseSelection $selection): void
{
return $this->record;
throw new ActiveRowException('Internal ActiveRow interface method');
}

/**
* @return NetteDatabaseSelection
*/
public function getTable(): NetteDatabaseSelection
{
return $this->record->getTable();
}

/**
* @param NetteDatabaseSelection $selection
* @throws ActiveRowException
*/
public function setTable(NetteDatabaseSelection $selection): void
{
throw new ActiveRowException('Internal IRow interface method');
}

/**********************************************************************\
* Wrapper function
\**********************************************************************/

/**
* @return string
*/
public function __toString(): string
{
return (string) $this->record;
}

/**
* @return array
*/
public function toArray(): array
{
return $this->record->toArray();
}

/**
* @param bool|true $need
* @return mixed
*/
public function getPrimary($need = true)
public function getPrimary(bool $throw = true): mixed
{
return $this->record->getPrimary($need);
return $this->record->getPrimary($throw);
}

/**
* @param bool|true $need
* @return string
*/
public function getSignature($need = true): string
public function getSignature(bool $throw = true): string
{
return $this->record->getSignature($need);
}

/**
* @param array|\Traversable $data
* @return bool
*/
public function update($data): bool
{
return $this->record->update($data);
}

/**
* @return int
*/
public function delete(): int
{
return $this->record->delete();
return $this->record->getSignature($throw);
}

/**
* Returns referenced row
* @param string $key
* @param string $throughColumn
* @return ActiveRow|null
*/
public function ref($key, $throughColumn = null): ?ActiveRow
public function ref(string $key, ?string $throughColumn = null): ?self
{
$row = $this->record->ref($key, $throughColumn);
if($row instanceof IRow) {
if ($row instanceof NetteDatabaseActiveRow) {
$result = $this->prepareRecord($row);
$result->setReferencingRecord($this);
return $result;
Expand All @@ -142,26 +81,26 @@ public function ref($key, $throughColumn = null): ?ActiveRow
return null;
}

/**
* Returns referencing rows
* @param string $key
* @param string $throughColumn
* @return Selection
*/
public function related($key, $throughColumn = null): ?Selection
public function related(string $key, ?string $throughColumn = null): Selection
{
return $this->prepareSelection($this->record->related($key, $throughColumn));
}

public function update(iterable $data): bool
{
$selection = $this->record->related($key, $throughColumn);
return $selection instanceof NetteDatabaseSelection ? $this->prepareSelection($selection) : null;
return $this->record->update($data);
}

public function delete(): int
{
return $this->record->delete();
}

/**********************************************************************\
* IteratorAggregate interface
\**********************************************************************/

/**
* @return ArrayIterator
*/
public function getIterator(): ArrayIterator
public function getIterator(): Iterator
{
return $this->record->getIterator();
}
Expand All @@ -171,45 +110,81 @@ public function getIterator(): ArrayIterator
\**********************************************************************/

/**
* Returns value of column
* @param string $key column name
* Stores value in column.
* @param string $column
* @param mixed $value
*/
public function offsetSet($column, $value): void
{
$this->record->offsetSet($column, $value);
}

/**
* Returns value of column.
* @param string $column
* @return mixed
*/
public function offsetGet($key)
#[\ReturnTypeWillChange]
public function offsetGet($column)
{
$result = $this->record->offsetGet($key);
return $result instanceof IRow ? $this->prepareRecord($result) : $result;
$result = $this->record->offsetGet($column);
return $result instanceof NetteDatabaseActiveRow ? $this->prepareRecord($result) : $result;
}

/**
* Tests if column exists
* @param string $key column name
* @return bool
* Tests if column exists.
* @param string $column
*/
public function offsetExists($key): bool
public function offsetExists($column): bool
{
return $this->record->offsetExists($key);
return $this->record->offsetExists($column);
}

/**
* Stores value in column
* @param string $key column name
* @param string $value
* Removes column from data.
* @param string $column
*/
public function offsetUnset($column): void
{
$this->record->offsetUnset($column);
}

/**********************************************************************\
* Magic accessors
\**********************************************************************/

/**
* @throws DeprecatedException
*/
public function offsetSet($key, $value): void
public function __set($column, $value)
{
throw new DeprecatedException('ActiveRow is read-only; use update() method instead.');
}

/**
* @return mixed|ActiveRow
* @throws MemberAccessException
*/
public function &__get(string $key)
{
$result = $this->record->$key;
if ($result instanceof NetteDatabaseActiveRow) {
$result = $this->prepareRecord($result);
}
return $result;
}

public function __isset($key)
{
$this->record->offsetSet($key, $value);
return isset($this->record->$key);
}

/**
* Removes column from data
* @param string $key column name
* @throws DeprecatedException
*/
public function offsetUnset($key): void
public function __unset($key)
{
$this->record->offsetUnset($key);
throw new DeprecatedException('ActiveRow is read-only.');
}

/**********************************************************************\
Expand All @@ -234,10 +209,6 @@ public function getReferencingRecord(): ?ActiveRow

/**
* Returns mm referencing rows
* @param Selection $selection
* @param string $ref
* @param string $refPrimary
* @return array
*/
protected function mmRelated(Selection $selection, string $ref, string $refPrimary = 'id'): array
{
Expand All @@ -252,25 +223,24 @@ protected function mmRelated(Selection $selection, string $ref, string $refPrima
* Build methods
\**********************************************************************/

/**
* Prepare one record
* @param IRow $row
* @return ActiveRow
*/
protected function prepareRecord(IRow $row): ActiveRow
protected function prepareRecord(NetteDatabaseActiveRow $row): ActiveRow
{
$recordClass = $this->structure->getActiveRowClass($row->getTable()->getName());
return new $recordClass($row, $this->structure);
}

/**
* Prepare selection
* @param NetteDatabaseSelection $selection
* @return Selection
*/
protected function prepareSelection(NetteDatabaseSelection $selection): Selection
{
$selectionClass = $this->structure->getSelectionClass($selection->getName());
return new $selectionClass($selection, $this->structure);
}

/**********************************************************************\
* Help methods
\**********************************************************************/

public function getRecord(): NetteDatabaseActiveRow
{
return $this->record;
}
}
Loading