Skip to content

Commit

Permalink
Refactor references NS to use consistent and explicit variable and me…
Browse files Browse the repository at this point in the history
…thod names (#675)

* [refactor] use consistent and explicit variable and method names

* [update] cleanup Reference\HasOne::ref

* [update] introdice initTableAlias

* [update] simplify HasOneSql::addFields
  • Loading branch information
georgehristov authored Jul 27, 2020
1 parent ef60d01 commit bc82230
Show file tree
Hide file tree
Showing 7 changed files with 252 additions and 232 deletions.
10 changes: 5 additions & 5 deletions src/Model.php
Original file line number Diff line number Diff line change
Expand Up @@ -1985,11 +1985,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 @@ -2000,7 +2000,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
{
'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) {
$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)
{
$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

0 comments on commit bc82230

Please sign in to comment.