Commit d036d2f5 by Carsten Brandt

add support for array valued attr relations to unlink and link

parent cc38e9c7
......@@ -239,7 +239,7 @@ trait ActiveRelationTrait
$link = array_values(isset($viaQuery) ? $viaQuery->link : $this->link);
foreach ($primaryModels as $i => $primaryModel) {
if ($this->multiple && count($link) < 2 && is_array($keys = $primaryModel->{reset($link)})) {
if ($this->multiple && count($link) == 1 && is_array($keys = $primaryModel->{reset($link)})) {
$value = [];
foreach ($keys as $key) {
if (isset($buckets[$key])) {
......
......@@ -1282,8 +1282,16 @@ abstract class BaseActiveRecord extends Model implements ActiveRecordInterface
}
$delete ? $model->delete() : $model->save(false);
} elseif ($p1) {
foreach ($relation->link as $b) {
$this->$b = null;
foreach ($relation->link as $a => $b) {
if (is_array($this->$b)) { // relation via array valued attribute
if (($key = array_search($model->$a, $this->$b, false)) !== false) {
$values = $this->$b;
unset($values[$key]);
$this->$b = $values;
}
} else {
$this->$b = null;
}
}
$delete ? $this->delete() : $this->save(false);
} else {
......@@ -1354,16 +1362,22 @@ abstract class BaseActiveRecord extends Model implements ActiveRecordInterface
} else {
/* @var $relatedModel ActiveRecordInterface */
$relatedModel = $relation->modelClass;
$nulls = [];
$condition = [];
foreach ($relation->link as $a => $b) {
$nulls[$a] = null;
$condition[$a] = $this->$b;
}
if ($delete) {
$relatedModel::deleteAll($condition);
if (!$delete && count($relation->link) == 1 && is_array($this->{$b = reset($relation->link)})) {
// relation via array valued attribute
$this->$b = [];
$this->save(false);
} else {
$relatedModel::updateAll($nulls, $condition);
$nulls = [];
$condition = [];
foreach ($relation->link as $a => $b) {
$nulls[$a] = null;
$condition[$a] = $this->$b;
}
if ($delete) {
$relatedModel::deleteAll($condition);
} else {
$relatedModel::updateAll($nulls, $condition);
}
}
}
......@@ -1383,7 +1397,11 @@ abstract class BaseActiveRecord extends Model implements ActiveRecordInterface
if ($value === null) {
throw new InvalidCallException('Unable to link models: the primary key of ' . get_class($primaryModel) . ' is null.');
}
$foreignModel->$fk = $value;
if (is_array($foreignModel->$fk)) { // relation via array valued attribute
$foreignModel->$fk = array_merge($foreignModel->$fk, [$value]);
} else {
$foreignModel->$fk = $value;
}
}
$foreignModel->save(false);
}
......
......@@ -738,6 +738,7 @@ class ActiveRecordTest extends ElasticSearchTestCase
/* @var $order Order */
$order = Order::find()->with('itemsByArrayValue')->where(['id' => 2])->one();
$this->assertTrue($order->isRelationPopulated('itemsByArrayValue'));
$items = $order->itemsByArrayValue;
$this->assertEquals(3, count($items));
$this->assertTrue(isset($items[3]));
......@@ -748,5 +749,81 @@ class ActiveRecordTest extends ElasticSearchTestCase
$this->assertTrue($items[5] instanceof Item);
}
public function testArrayAttributeRelationLink()
{
/* @var $order Order */
$order = Order::find()->where(['id' => 1])->one();
$items = $order->itemsByArrayValue;
$this->assertEquals(2, count($items));
$this->assertTrue(isset($items[1]));
$this->assertTrue(isset($items[2]));
$item = Item::get(5);
$order->link('itemsByArrayValue', $item);
$this->afterSave();
$items = $order->itemsByArrayValue;
$this->assertEquals(3, count($items));
$this->assertTrue(isset($items[1]));
$this->assertTrue(isset($items[2]));
$this->assertTrue(isset($items[5]));
// check also after refresh
$this->assertTrue($order->refresh());
$items = $order->itemsByArrayValue;
$this->assertEquals(3, count($items));
$this->assertTrue(isset($items[1]));
$this->assertTrue(isset($items[2]));
$this->assertTrue(isset($items[5]));
}
public function testArrayAttributeRelationUnLink()
{
/* @var $order Order */
$order = Order::find()->where(['id' => 1])->one();
$items = $order->itemsByArrayValue;
$this->assertEquals(2, count($items));
$this->assertTrue(isset($items[1]));
$this->assertTrue(isset($items[2]));
$item = Item::get(2);
$order->unlink('itemsByArrayValue', $item);
$this->afterSave();
$items = $order->itemsByArrayValue;
$this->assertEquals(1, count($items));
$this->assertTrue(isset($items[1]));
$this->assertFalse(isset($items[2]));
// check also after refresh
$this->assertTrue($order->refresh());
$items = $order->itemsByArrayValue;
$this->assertEquals(1, count($items));
$this->assertTrue(isset($items[1]));
$this->assertFalse(isset($items[2]));
}
public function testArrayAttributeRelationUnLinkAll()
{
/* @var $order Order */
$order = Order::find()->where(['id' => 1])->one();
$items = $order->itemsByArrayValue;
$this->assertEquals(2, count($items));
$this->assertTrue(isset($items[1]));
$this->assertTrue(isset($items[2]));
$order->unlinkAll('itemsByArrayValue');
$this->afterSave();
$items = $order->itemsByArrayValue;
$this->assertEquals(0, count($items));
// check also after refresh
$this->assertTrue($order->refresh());
$items = $order->itemsByArrayValue;
$this->assertEquals(0, count($items));
}
// TODO test AR with not mapped PK
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment