Skip to content
This repository has been archived by the owner on Jul 25, 2022. It is now read-only.

Commit

Permalink
Added support for containsOne / containsMany
Browse files Browse the repository at this point in the history
  • Loading branch information
romaninsh committed Jul 19, 2015
1 parent 0687688 commit 4053588
Show file tree
Hide file tree
Showing 9 changed files with 438 additions and 0 deletions.
20 changes: 20 additions & 0 deletions lib/Model.php
Expand Up @@ -964,6 +964,26 @@ public function hasMany($model, $their_field = UNDEFINED, $our_field = UNDEFINED

return null;
}
/** Defines contained model for field */
function containsOne($field, $model) {
if(is_array($field) && $field[0]) {
$field['name'] = $field[0];
unset($field[0]);
}
if($e = $this->hasElement(is_string($field)?$field:$field['name']))$e->destroy();
$this->add('Relation_ContainsOne', $field)
->setModel($model);
}
/** Defines multiple contained models for field */
function containsMany($field, $model) {
if(is_array($field) && $field[0]) {
$field['name'] = $field[0];
unset($field[0]);
}
if($e = $this->hasElement(is_string($field)?$field:$field['name']))$e->destroy();
$this->add('Relation_ContainsMany', $field)
->setModel($model);
}
/**
* Traverses reference of relation
*
Expand Down
48 changes: 48 additions & 0 deletions lib/Relation/ContainsMany.php
@@ -0,0 +1,48 @@
<?php
class Relation_ContainsMany extends Field {
public $auto_track_element=true;
public $json = false;
public $encode = null;
public $decode = null;

function init(){
parent::init();

if($this->json){
$this->encode = function($t){ return json_encode($t); };
$this->decode = function($t){ return json_decode($t,true); };
}
}

function ref(){

// create new instance
$model = $this->getModel();

if(is_callable($model)){
call_user_func($model, $model = $this->add('Model'));
}elseif(is_string($model)){
$model = $this->app->normalizeClassName($model,'Model');

$model = $this->add($model);
}

$data = $this->owner[$this->short_name]?:[];

if($this->decode)$data = call_user_func($this->decode,$data);

$model->setSource('Array',$data);

$self = $this;
$model->addHook('afterSave', function($m)use($self,$data){
$e = $m->_table[$m->controller->short_name];
if($this->encode)$e = call_user_func($this->encode,$e);
$self->owner[$self->short_name] = $e;
$self->owner->saveLater();
});


return $model;
}

}
45 changes: 45 additions & 0 deletions lib/Relation/ContainsOne.php
@@ -0,0 +1,45 @@
<?php
class Relation_ContainsOne extends Field {
public $auto_track_element=true;
public $json = false;
public $encode = null;
public $decode = null;

function init(){
parent::init();

if($this->json){
$this->encode = function($t){ return json_encode($t); };
$this->decode = function($t){ return json_decode($t,true); };
}
}

function ref(){

// create new instance
$model = $this->getModel();

if(is_callable($model)){
call_user_func($model, $model = $this->add('Model'));
}elseif(is_string($model)){
$model = $this->app->normalizeClassName($model,'Model');

$model = $this->add($model);
}

$model->data = $this->owner[$this->short_name];
if($this->decode)$model->data = call_user_func($this->decode,$model->data);

$self = $this;
$model->addHook('beforeSave', function($m)use($self){
$e = $m->data;
if($this->encode)$e = call_user_func($this->encode,$e);
$self->owner[$self->short_name] = $e;
$self->owner->saveLater();
});


return $model;
}

}
20 changes: 20 additions & 0 deletions lib/SQL/Model.php
Expand Up @@ -254,6 +254,26 @@ function hasMany($model,$their_field=null,$our_field=null,$as_field=null){
->set($model,$their_field,$our_field);
return $rel;
}
/** Defines contained model for field */
function containsOne($field, $model) {
if(is_array($field) && $field[0]) {
$field['name'] = $field[0];
unset($field[0]);
}
if($e = $this->hasElement(is_string($field)?$field:$field['name']))$e->destroy();
$this->add('Relation_ContainsOne', $field)
->setModel($model);
}
/** Defines multiple contained models for field */
function containsMany($field, $model) {
if(is_array($field) && $field[0]) {
$field['name'] = $field[0];
unset($field[0]);
}
if($e = $this->hasElement(is_string($field)?$field:$field['name']))$e->destroy();
$this->add('Relation_ContainsMany', $field)
->setModel($model);
}
/** Traverses references. Use field name for hasOne() relations. Use model name for hasMany() */
function ref($name,$load=null){
if(!$name)return $this;
Expand Down
85 changes: 85 additions & 0 deletions tests/atk43_model_relations/00basic.php
@@ -0,0 +1,85 @@
<?php
class loan_tester extends AbstractController {
function prepare(){
return [$this->add('Model')];
}
function test_create($m)
{
$m->containsOne('test', 'MyModel');
return $m->getElement('test')->short_name;
}

function test_ref($m)
{
$m->containsOne('test', 'MyModel');
return $m->ref('test')->get('name');
}

function test_refsave($m)
{
$m->containsOne('test', 'MyModel');
$m->ref('test')->set('name','boss')->save();

$this->tmp1 = $m->data;
return json_encode($m['test']);
}

function test_refload($m)
{
$m->data = array ( 'test' => array ( 'name' => 'boss', ), );
$m->containsOne('test', 'MyModel');

return json_encode($m->ref('test')->get('name'));
}

function test_set($m)
{
$m->containsOne('test', 'MyModel');
$m->set('test', ['name'=>'ok']);

return json_encode($m->ref('test')->get('name'));
}
function test_setcustom($m)
{
$m->containsOne('test', function($m){
$m->addField('name');
$m->addField('surname');
});
$m->set('test', ['name'=>'ok']);

return json_encode($m->ref('test')->get('name'));
}

function test_destroy($m)
{
$m->addField('test');
$m->set('test', ['name'=>'ok']);

$m->containsOne('test', function($m){
$m->addField('name');
$m->addField('surname');
});

return json_encode($m->ref('test')->get('name'));
}

public $proper_responses=array(
"Test_create"=>'test',
"Test_ref"=>'smith',
"Test_refsave"=>'{"name":"boss"}',
"Test_refload"=>'"boss"',
"Test_set"=>'"ok"',
"Test_setcustom"=>'"ok"',
"Test_destroy"=>'"ok"',
);

}

class Model_MyModel extends Model {
function init() {
parent::init();

$this->addField('name')->defaultValue('smith');
$this->addField('surname');
}
}
61 changes: 61 additions & 0 deletions tests/atk43_model_relations/01json.php
@@ -0,0 +1,61 @@
<?php
class loan_tester extends AbstractController {
function prepare(){
return [$this->add('Model')];
}
function test_create($m)
{
$m->containsOne(['test','json'=>true], 'MyModel');
return $m->getElement('test')->short_name;
}

function test_ref($m)
{
$m->containsOne(['test','json'=>true], 'MyModel');
return $m->ref('test')->get('name');
}

function test_refsave($m)
{
$m->containsOne(['test','json'=>true], 'MyModel');
$m->ref('test')->set('name','boss')->save();

$this->tmp1 = $m->data;
return $m['test'];
}

function test_refload($m)
{
$m->data = array ( 'test' => '{"name":"boss"}', );
$m->containsOne(['test','json'=>true], 'MyModel');

return json_encode($m->ref('test')->get('name'));
}

function test_set($m)
{
$m->containsOne(['test','json'=>true], 'MyModel');
$m->set('test', '{"name":"ok"}');

return json_encode($m->ref('test')->get('name'));
}


public $proper_responses=array(
"Test_create"=>'test',
"Test_ref"=>'smith',
"Test_refsave"=>'{"name":"boss"}',
"Test_refload"=>'"boss"',
"Test_set"=>'"ok"',
);

}

class Model_MyModel extends Model {
function init() {
parent::init();

$this->addField('name')->defaultValue('smith');
$this->addField('surname');
}
}
95 changes: 95 additions & 0 deletions tests/atk43_model_relations/02many-basic.php
@@ -0,0 +1,95 @@
<?php
class loan_tester extends AbstractController {
function prepare(){
return [$this->add('Model')];
}
function test_create($m)
{
$m->containsMany('test', 'MyModel');
return $m->getElement('test')->short_name;
}

function test_ref($m)
{
$m->containsMany('test', 'MyModel');
return $m->ref('test')->get('name');
}

function test_refsave($m)
{
$m->containsMany('test', 'MyModel');
$m->ref('test')->set('name','boss')->save();

$this->tmp1 = $m->data;
return json_encode($m['test']);
}

function test_refsave2($m)
{
$m->containsMany('test', 'MyModel');
$mm = $m->ref('test')->set('name','boss')->saveAndUnload();
$mm['name']='qq';
$mm->save();

$this->tmp1 = $m->data;
return json_encode($m['test']);
}

function test_refload($m)
{
$m->data = array ( 'test' => [ 1 => array ( 'name' => 'boss', ), ], );
$m->containsMany('test', 'MyModel');

return json_encode($m->ref('test')->load(1)->get('name'));
}

function test_set($m)
{
$m->containsMany('test', 'MyModel');
$m->set('test',[ ['name'=>'ok'] ]);

return json_encode($m->ref('test')->tryLoadAny()->get('name'));
}
function test_setcustom($m)
{
$m->containsMany('test', function($m){
$m->addField('name');
$m->addField('surname');
});
$m->set('test', [ ['name'=>'ok'] ] );

return json_encode($m->ref('test')->loadAny()->get('name'));
}

function test_destroy($m)
{
$m->addField('test');
$m->set('test', [ ['name'=>'ok'] ]);

$m->containsMany('test', function($m){
$m->addField('name');
$m->addField('surname');
});

return json_encode($m->ref('test')->loadAny()->get('name'));
}

public $proper_responses=array(
"Test_create"=>'test',
"Test_ref"=>'smith',
"Test_refload"=>'"boss"',
"Test_set"=>'"ok"',
"Test_setcustom"=>'"ok"',
"Test_destroy"=>'"ok"',
);

}

class Model_MyModel extends Model {
function init() {
parent::init();

$this->addField('name')->defaultValue('smith');
$this->addField('surname');
}
}

0 comments on commit 4053588

Please sign in to comment.