Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Refactor references NS to use consistent and explicit variable and method names #675

Merged
merged 8 commits into from
Jul 27, 2020
10 changes: 5 additions & 5 deletions src/Model.php
Original file line number Diff line number Diff line change
Expand Up @@ -1990,11 +1990,11 @@ public function leftJoin(string $foreign_table, $defaults = [])
/**
* Private method.
*
* @param string $c Class name
* @param string $link Link
* @param array|callable $defaults Properties which we will pass to Reference object constructor
* @param string $className Class name
* @param string $link Link
* @param array|callable $defaults Properties which we will pass to Reference object constructor
*/
protected function _hasReference($c, $link, $defaults = []): Reference
protected function _hasReference($className, $link, $defaults = []): Reference
{
if (!is_array($defaults)) {
$defaults = ['model' => $defaults ?: 'Model_' . $link];
Expand All @@ -2005,7 +2005,7 @@ protected function _hasReference($c, $link, $defaults = []): Reference

$defaults[0] = $link;

$obj = $this->factory($c, $defaults);
$obj = $this->factory($className, $defaults);

// if reference with such name already exists, then throw exception
if ($this->hasElement($name = $obj->getDesiredName())) {
Expand Down
104 changes: 61 additions & 43 deletions src/Reference.php
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
*
* It's possible to extend the basic reference with more meaningful references.
*
* @property Model $owner
* @property Model $owner definition of our model
*/
class Reference
{
Expand Down Expand Up @@ -41,7 +41,7 @@ class Reference
public $link;

/**
* Definition of the destination model, that can be either an object, a
* Definition of the destination their model, that can be either an object, a
* callback or a string. This can be defined during initialization and
* then used inside getModel() to fully populate and associate with
* persistence.
Expand Down Expand Up @@ -90,6 +90,8 @@ public function __construct($link)
public function init(): void
{
$this->_init();

$this->initTableAlias();
}

/**
Expand All @@ -100,59 +102,75 @@ public function getDesiredName(): string
return '#ref_' . $this->link;
}

public function getOurModel(): Model
{
return $this->owner;
}

/**
* @deprecated use getTheirModel instead - will be removed in dec-2020
*/
public function getModel($defaults = []): Model
mvorisek marked this conversation as resolved.
Show resolved Hide resolved
{
'trigger_error'('Method Reference::getModel is deprecated. Use Model::getTheirModel instead', E_USER_DEPRECATED);

return $this->getTheirModel($defaults);
}

/**
* Returns destination model that is linked through this reference. Will apply
* necessary conditions.
*
* @param array $defaults Properties
*/
public function getModel($defaults = []): Model
public function getTheirModel($defaults = []): Model
{
// set table_alias
if (!isset($defaults['table_alias'])) {
if (!$this->table_alias) {
$this->table_alias = $this->link;
$this->table_alias = preg_replace('/_' . ($this->owner->id_field ?: 'id') . '/', '', $this->table_alias);
$this->table_alias = preg_replace('/([a-zA-Z])[a-zA-Z]*[^a-zA-Z]*/', '\1', $this->table_alias);
if (isset($this->owner->table_alias)) {
$this->table_alias = $this->owner->table_alias . '_' . $this->table_alias;
}
}
$defaults['table_alias'] = $this->table_alias;
}

// if model is Closure, then call it and return model
if (is_object($this->model) && $this->model instanceof \Closure) {
$c = ($this->model)($this->owner, $this, $defaults);

return $this->addToPersistence($c, $defaults);
}
$defaults['table_alias'] = $defaults['table_alias'] ?? $this->table_alias;

// if model is set, then return clone of this model
if (is_object($this->model)) {
$c = clone $this->model;
if ($this->model instanceof \Closure) {
// if model is Closure, then call the closure and whci should return a model
$theirModel = ($this->model)($this->getOurModel(), $this, $defaults);
} else {
// if model is set, then use clone of this model
$theirModel = clone $this->model;
}

return $this->addToPersistence($c, $defaults);
return $this->addToPersistence($theirModel, $defaults);
}

// last effort - try to add model
// add model from seed
if (is_array($this->model)) {
$model = [$this->model[0]];
$md = $this->model;
unset($md[0]);
$modelDefaults = $this->model;
$theirModelSeed = [$modelDefaults[0]];

unset($modelDefaults[0]);

$defaults = array_merge($md, $defaults);
$defaults = array_merge($modelDefaults, $defaults);
} elseif (is_string($this->model)) {
$model = [$this->model];
$theirModelSeed = [$this->model];
} else {
$model = $this->model;
$theirModelSeed = $this->model;
}

if (!$model instanceof Model) {
$model = $this->factory($model, $defaults);
}
$theirModel = $this->factory($theirModelSeed, $defaults);

return $this->addToPersistence($theirModel, $defaults);
}

return $this->addToPersistence($model, $defaults);
protected function initTableAlias(): void
{
if (!$this->table_alias) {
georgehristov marked this conversation as resolved.
Show resolved Hide resolved
$ourModel = $this->getOurModel();

$this->table_alias = $this->link;
$this->table_alias = preg_replace('/_' . ($ourModel->id_field ?: 'id') . '/', '', $this->table_alias);
$this->table_alias = preg_replace('/([a-zA-Z])[a-zA-Z]*[^a-zA-Z]*/', '\1', $this->table_alias);
if (isset($ourModel->table_alias)) {
$this->table_alias = $ourModel->table_alias . '_' . $this->table_alias;
}
}
}

/**
Expand All @@ -163,8 +181,8 @@ public function getModel($defaults = []): Model
*/
protected function addToPersistence($model, $defaults = []): Model
{
if (!$model->persistence && $p = $this->getDefaultPersistence($model)) {
$p->add($model, $defaults);
if (!$model->persistence && $persistence = $this->getDefaultPersistence($model)) {
$persistence->add($model, $defaults);
}

// set model caption
Expand All @@ -184,16 +202,16 @@ protected function addToPersistence($model, $defaults = []): Model
*/
protected function getDefaultPersistence($model)
{
$m = $this->owner;
$ourModel = $this->getOurModel();

// this will be useful for containsOne/Many implementation in case when you have
// SQL_Model->containsOne()->hasOne() structure to get back to SQL persistence
// from Array persistence used in containsOne model
if ($m->contained_in_root_model && $m->contained_in_root_model->persistence) {
return $m->contained_in_root_model->persistence;
if ($ourModel->contained_in_root_model && $ourModel->contained_in_root_model->persistence) {
return $ourModel->contained_in_root_model->persistence;
}

return $m->persistence ?: false;
return $ourModel->persistence ?: false;
}

/**
Expand All @@ -204,7 +222,7 @@ protected function getDefaultPersistence($model)
*/
public function ref($defaults = []): Model
{
return $this->getModel($defaults);
return $this->getTheirModel($defaults);
}

/**
Expand All @@ -216,7 +234,7 @@ public function ref($defaults = []): Model
*/
public function refModel($defaults = []): Model
{
return $this->getModel($defaults);
return $this->getTheirModel($defaults);
}

// {{{ Debug Methods
Expand Down
33 changes: 15 additions & 18 deletions src/Reference/ContainsMany.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,8 @@

namespace atk4\data\Reference;

use atk4\data\Exception;
use atk4\data\Model;
use atk4\data\Persistence\ArrayOfStrings;
use atk4\data\Reference;
use atk4\data\Persistence;

/**
* ContainsMany reference.
Expand All @@ -25,28 +23,25 @@ class ContainsMany extends ContainsOne
*/
protected function getDefaultPersistence($model)
{
$m = $this->owner;
$ourModel = $this->getOurModel();

// model should be loaded
/* Imants: it looks that this is not actually required - disabling
if (!$m->loaded()) {
if (!$ourModel->loaded()) {
throw (new Exception('Model should be loaded!'))
->addMoreInfo('model', get_class($m));
->addMoreInfo('model', get_class($ourModel));
}
*/

// set data source of referenced array persistence
$rows = $m->get($this->our_field) ?: [];
$rows = $ourModel->get($this->our_field) ?: [];
/*
foreach ($rows as $id=>$row) {
$rows[$id] = $this->owner->persistence->typecastLoadRow($m, $row); // we need this typecasting because we set persistence data directly
$rows[$id] = $ourModel->persistence->typecastLoadRow($ourModel, $row); // we need this typecasting because we set persistence data directly
}
*/

$data = [$this->table_alias => $rows ?: []];
$p = new ArrayOfStrings($data);

return $p;
return new Persistence\ArrayOfStrings([$this->table_alias => $rows ?: []]);
}

/**
Expand All @@ -56,22 +51,24 @@ protected function getDefaultPersistence($model)
*/
public function ref($defaults = []): Model
{
$ourModel = $this->getOurModel();

// get model
// will not use ID field (no, sorry, will have to use it)
$m = $this->getModel(array_merge($defaults, [
'contained_in_root_model' => $this->owner->contained_in_root_model ?: $this->owner,
$theirModel = $this->getTheirModel(array_merge($defaults, [
'contained_in_root_model' => $ourModel->contained_in_root_model ?: $ourModel,
//'id_field' => false,
'table' => $this->table_alias,
]));

// set some hooks for ref_model
foreach ([Model::HOOK_AFTER_SAVE, Model::HOOK_AFTER_DELETE] as $spot) {
$m->onHook($spot, function ($model) {
$rows = $model->persistence->getRawDataByTable($this->table_alias);
$this->owner->save([$this->our_field => $rows ?: null]);
$theirModel->onHook($spot, function ($theirModel) {
$rows = $theirModel->persistence->getRawDataByTable($this->table_alias);
$this->getOurModel()->save([$this->our_field => $rows ?: null]);
});
}

return $m;
return $theirModel;
}
}
40 changes: 20 additions & 20 deletions src/Reference/ContainsOne.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,8 @@

namespace atk4\data\Reference;

use atk4\data\Exception;
use atk4\data\Model;
use atk4\data\Persistence\ArrayOfStrings;
use atk4\data\Persistence;
use atk4\data\Reference;

/**
Expand Down Expand Up @@ -60,8 +59,10 @@ public function init(): void
$this->our_field = $this->link;
}

if (!$this->owner->hasElement($this->our_field)) {
$this->owner->addField($this->our_field, [
$ourModel = $this->getOurModel();

if (!$ourModel->hasElement($this->our_field)) {
$ourModel->addField($this->our_field, [
'type' => $this->type,
'reference' => $this,
'system' => $this->system,
Expand All @@ -82,24 +83,21 @@ public function init(): void
*/
protected function getDefaultPersistence($model)
georgehristov marked this conversation as resolved.
Show resolved Hide resolved
{
$m = $this->owner;
$ourModel = $this->getOurModel();

// model should be loaded
/* Imants: it looks that this is not actually required - disabling
if (!$m->loaded()) {
if (!$ourModel->loaded()) {
throw (new Exception('Model should be loaded!'))
->addMoreInfo('model', get_class($m));
->addMoreInfo('model', get_class($ourModel));
}
*/

// set data source of referenced array persistence
$row = $m->get($this->our_field) ?: [];
//$row = $m->persistence->typecastLoadRow($m, $row); // we need this typecasting because we set persistence data directly

$data = [$this->table_alias => $row ? [1 => $row] : []];
$p = new ArrayOfStrings($data);
$row = $ourModel->get($this->our_field) ?: [];
//$row = $ourModel->persistence->typecastLoadRow($ourModel, $row); // we need this typecasting because we set persistence data directly

return $p;
return new Persistence\ArrayOfStrings([$this->table_alias => $row ? [1 => $row] : []]);
}

/**
Expand All @@ -109,26 +107,28 @@ protected function getDefaultPersistence($model)
*/
public function ref($defaults = []): Model
{
$ourModel = $this->getOurModel();

// get model
// will not use ID field
$m = $this->getModel(array_merge($defaults, [
'contained_in_root_model' => $this->owner->contained_in_root_model ?: $this->owner,
$theirModel = $this->getTheirModel(array_merge($defaults, [
'contained_in_root_model' => $ourModel->contained_in_root_model ?: $ourModel,
'id_field' => false,
'table' => $this->table_alias,
]));

// set some hooks for ref_model
foreach ([Model::HOOK_AFTER_SAVE, Model::HOOK_AFTER_DELETE] as $spot) {
$m->onHook($spot, function ($model) {
$row = $model->persistence->getRawDataByTable($this->table_alias);
$theirModel->onHook($spot, function ($theirModel) {
$row = $theirModel->persistence->getRawDataByTable($this->table_alias);
$row = $row ? array_shift($row) : null; // get first and only one record from array persistence
$this->owner->save([$this->our_field => $row]);
$this->getOurModel()->save([$this->our_field => $row]);
});
}

// try to load any (actually only one possible) record
$m->tryLoadAny();
$theirModel->tryLoadAny();

return $m;
return $theirModel;
}
}
Loading