public function unlink($name, $model, $delete = false)
{
$relation = $this->getRelation($name);
if ($relation->via !== null) {
if (is_array($relation->via)) {
/* @var $viaRelation ActiveQuery */
list($viaName, $viaRelation) = $relation->via;
$viaClass = $viaRelation->modelClass;
unset($this->_related[$viaName]);
} else {
$viaRelation = $relation->via;
$viaTable = reset($relation->via->from);
}
$columns = [];
foreach ($viaRelation->link as $a => $b) {
$columns[$a] = $this->{$b};
}
foreach ($relation->link as $a => $b) {
$columns[$b] = $model->{$a};
}
$nulls = [];
foreach (array_keys($columns) as $a) {
$nulls[$a] = null;
}
if (is_array($relation->via)) {
/* @var $viaClass ActiveRecordInterface */
if ($delete) {
$viaClass::deleteAll($columns);
} else {
$viaClass::updateAll($nulls, $columns);
}
} else {
/* @var $viaTable string */
/* @var $command Command */
$command = static::getDb()->createCommand();
if ($delete) {
$command->delete($viaTable, $columns)->execute();
} else {
$command->update($viaTable, $nulls, $columns)->execute();
}
}
} else {
$p1 = $model->isPrimaryKey(array_keys($relation->link));
$p2 = static::isPrimaryKey(array_values($relation->link));
if ($p2) {
if ($delete) {
$model->delete();
} else {
foreach ($relation->link as $a => $b) {
$model->{$a} = null;
}
$model->save(false);
}
} elseif ($p1) {
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} = array_values($values);
}
} else {
$this->{$b} = null;
}
}
$delete ? $this->delete() : $this->save(false);
} else {
throw new InvalidCallException('Unable to unlink models: the link does not involve any primary key.');
}
}
if (!$relation->multiple) {
unset($this->_related[$name]);
} elseif (isset($this->_related[$name])) {
/* @var $b ActiveRecordInterface */
foreach ($this->_related[$name] as $a => $b) {
if ($model->getPrimaryKey() === $b->getPrimaryKey()) {
unset($this->_related[$name][$a]);
}
}
}
}