/**
  * Destroys the relationship between two models.
  *
  * The model with the foreign key of the relationship will be deleted if `$delete` is true.
  * Otherwise, the foreign key will be set null and the model will be saved without validation.
  *
  * @param string $name the case sensitive name of the relationship.
  * @param ActiveRecord $model the model to be unlinked from the current one.
  * @param boolean $delete whether to delete the model that contains the foreign key.
  * If false, the model's foreign key will be set null and saved.
  * If true, the model containing the foreign key will be deleted.
  * @throws InvalidCallException if the models cannot be unlinked
  */
 public function unlink($name, $model, $delete = false)
 {
     $relation = $this->getRelation($name);
     if ($relation->via !== null) {
         if (is_array($relation->via)) {
             /** @var ActiveRelation $viaRelation */
             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};
         }
         if (is_array($relation->via)) {
             /** @var $viaClass ActiveRecord */
             if ($delete) {
                 $viaClass::deleteAll($columns);
             } else {
                 $nulls = [];
                 foreach (array_keys($columns) as $a) {
                     $nulls[$a] = null;
                 }
                 $viaClass::updateAll($nulls, $columns);
             }
         } else {
             /** @var $viaTable string */
             $command = static::getDb()->createCommand();
             if ($delete) {
                 $command->delete($viaTable, $columns)->execute();
             } else {
                 $nulls = [];
                 foreach (array_keys($columns) as $a) {
                     $nulls[$a] = null;
                 }
                 $command->update($viaTable, $nulls, $columns)->execute();
             }
         }
     } else {
         $p1 = $model->isPrimaryKey(array_keys($relation->link));
         $p2 = $this->isPrimaryKey(array_values($relation->link));
         if ($p1 && $p2 || $p2) {
             foreach ($relation->link as $a => $b) {
                 $model->{$a} = null;
             }
             $delete ? $model->delete() : $model->save(false);
         } elseif ($p1) {
             foreach ($relation->link as $b) {
                 $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 ActiveRecord $b */
         foreach ($this->_related[$name] as $a => $b) {
             if ($model->getPrimaryKey() == $b->getPrimaryKey()) {
                 unset($this->_related[$name][$a]);
             }
         }
     }
 }
 /**
  * @param string $name relation name
  * @param ActiveRecord $model
  * @param array $extraColumns
  * @throws \yii\db\Exception
  */
 public function link($name, $model, $extraColumns = [])
 {
     $relation = $this->getOwnerRelation($name);
     if ($relation->via !== null) {
         if ($this->owner->getIsNewRecord() || $model->getIsNewRecord()) {
             throw new InvalidCallException('Unable to link models: both models must NOT be newly created.');
         }
         if (is_array($relation->via)) {
             /* @var $viaRelation ActiveQuery */
             list($viaName, $viaRelation) = $relation->via;
             $viaClass = $viaRelation->modelClass;
             // unset $viaName so that it can be reloaded to reflect the change
             //                unset($this->_related[$viaName]);
         } else {
             $viaRelation = $relation->via;
             $viaTable = reset($relation->via->from);
         }
         $columns = [];
         foreach ($viaRelation->link as $a => $b) {
             $columns[$a] = $this->owner->{$b};
         }
         foreach ($relation->link as $a => $b) {
             $columns[$b] = $model->{$a};
         }
         foreach ($extraColumns as $k => $v) {
             $columns[$k] = $v;
         }
         if (is_array($relation->via)) {
             /* @var $viaClass ActiveRecordInterface */
             /* @var $record ActiveRecordInterface */
             $record = new $viaClass();
             foreach ($columns as $column => $value) {
                 $record->{$column} = $value;
             }
             $record->insert(false);
         } else {
             /* @var $viaTable string */
             ActiveRecord::getDb()->createCommand()->insert($viaTable, $columns)->execute();
         }
     } else {
         $p1 = $model->isPrimaryKey(array_keys($relation->link));
         $p2 = $this->owner->isPrimaryKey(array_values($relation->link));
         if ($p1 && $p2) {
             if ($this->owner->getIsNewRecord() && $model->getIsNewRecord()) {
                 throw new InvalidCallException('Unable to link models: both models are newly created.');
             } elseif ($this->owner->getIsNewRecord()) {
                 $this->bindModels(array_flip($relation->link), $this->owner, $model);
             } else {
                 $this->bindModels($relation->link, $model, $this->owner);
             }
         } elseif ($p1) {
             $this->bindModels(array_flip($relation->link), $this->owner, $model);
         } elseif ($p2) {
             $this->bindModels($relation->link, $model, $this->owner);
         } else {
             throw new InvalidCallException('Unable to link models: the link does not involve any primary key.');
         }
     }
     //        // update lazily loaded related objects
     //        if (!$relation->multiple) {
     //            $this->_related[$name] = $model;
     //        } elseif (isset($this->_related[$name])) {
     //            if ($relation->indexBy !== null) {
     //                $indexBy = $relation->indexBy;
     //                $this->_related[$name][$model->$indexBy] = $model;
     //            } else {
     //                $this->_related[$name][] = $model;
     //            }
     //        }
 }