Commit d036d2f5 by Carsten Brandt

add support for array valued attr relations to unlink and link

parent cc38e9c7
...@@ -239,7 +239,7 @@ trait ActiveRelationTrait ...@@ -239,7 +239,7 @@ trait ActiveRelationTrait
$link = array_values(isset($viaQuery) ? $viaQuery->link : $this->link); $link = array_values(isset($viaQuery) ? $viaQuery->link : $this->link);
foreach ($primaryModels as $i => $primaryModel) { 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 = []; $value = [];
foreach ($keys as $key) { foreach ($keys as $key) {
if (isset($buckets[$key])) { if (isset($buckets[$key])) {
......
...@@ -1282,9 +1282,17 @@ abstract class BaseActiveRecord extends Model implements ActiveRecordInterface ...@@ -1282,9 +1282,17 @@ abstract class BaseActiveRecord extends Model implements ActiveRecordInterface
} }
$delete ? $model->delete() : $model->save(false); $delete ? $model->delete() : $model->save(false);
} elseif ($p1) { } elseif ($p1) {
foreach ($relation->link as $b) { 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; $this->$b = null;
} }
}
$delete ? $this->delete() : $this->save(false); $delete ? $this->delete() : $this->save(false);
} else { } else {
throw new InvalidCallException('Unable to unlink models: the link does not involve any primary key.'); throw new InvalidCallException('Unable to unlink models: the link does not involve any primary key.');
...@@ -1354,6 +1362,11 @@ abstract class BaseActiveRecord extends Model implements ActiveRecordInterface ...@@ -1354,6 +1362,11 @@ abstract class BaseActiveRecord extends Model implements ActiveRecordInterface
} else { } else {
/* @var $relatedModel ActiveRecordInterface */ /* @var $relatedModel ActiveRecordInterface */
$relatedModel = $relation->modelClass; $relatedModel = $relation->modelClass;
if (!$delete && count($relation->link) == 1 && is_array($this->{$b = reset($relation->link)})) {
// relation via array valued attribute
$this->$b = [];
$this->save(false);
} else {
$nulls = []; $nulls = [];
$condition = []; $condition = [];
foreach ($relation->link as $a => $b) { foreach ($relation->link as $a => $b) {
...@@ -1366,6 +1379,7 @@ abstract class BaseActiveRecord extends Model implements ActiveRecordInterface ...@@ -1366,6 +1379,7 @@ abstract class BaseActiveRecord extends Model implements ActiveRecordInterface
$relatedModel::updateAll($nulls, $condition); $relatedModel::updateAll($nulls, $condition);
} }
} }
}
unset($this->_related[$name]); unset($this->_related[$name]);
} }
...@@ -1383,8 +1397,12 @@ abstract class BaseActiveRecord extends Model implements ActiveRecordInterface ...@@ -1383,8 +1397,12 @@ abstract class BaseActiveRecord extends Model implements ActiveRecordInterface
if ($value === null) { if ($value === null) {
throw new InvalidCallException('Unable to link models: the primary key of ' . get_class($primaryModel) . ' is null.'); throw new InvalidCallException('Unable to link models: the primary key of ' . get_class($primaryModel) . ' is null.');
} }
if (is_array($foreignModel->$fk)) { // relation via array valued attribute
$foreignModel->$fk = array_merge($foreignModel->$fk, [$value]);
} else {
$foreignModel->$fk = $value; $foreignModel->$fk = $value;
} }
}
$foreignModel->save(false); $foreignModel->save(false);
} }
......
...@@ -738,6 +738,7 @@ class ActiveRecordTest extends ElasticSearchTestCase ...@@ -738,6 +738,7 @@ class ActiveRecordTest extends ElasticSearchTestCase
/* @var $order Order */ /* @var $order Order */
$order = Order::find()->with('itemsByArrayValue')->where(['id' => 2])->one(); $order = Order::find()->with('itemsByArrayValue')->where(['id' => 2])->one();
$this->assertTrue($order->isRelationPopulated('itemsByArrayValue'));
$items = $order->itemsByArrayValue; $items = $order->itemsByArrayValue;
$this->assertEquals(3, count($items)); $this->assertEquals(3, count($items));
$this->assertTrue(isset($items[3])); $this->assertTrue(isset($items[3]));
...@@ -748,5 +749,81 @@ class ActiveRecordTest extends ElasticSearchTestCase ...@@ -748,5 +749,81 @@ class ActiveRecordTest extends ElasticSearchTestCase
$this->assertTrue($items[5] instanceof Item); $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 // 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