/**
  * Обновление модели на основе данных, пришедших из json-контроллера
  *
  * @param $jsonString
  * @return array
  */
 public function updateWithJsonString($jsonString)
 {
     // данные модели
     $modelData = json_decode($jsonString, true);
     // убираем служебную инфу
     if (array_key_exists("_translation", $modelData)) {
         unset($modelData["_translation"]);
     }
     // попробуем сохранить данные, которые находятся в отношениях
     // многие-ко-многим
     foreach ($this->relations() as $field => $properties) {
         if ($properties["relationPower"] == RELATION_MANY_TO_MANY) {
             if (array_key_exists($field, $modelData)) {
                 $data = $modelData[$field];
                 // уберем их из модели
                 unset($modelData[$field]);
                 // уберем уже имеющиеся данные из связанной таблицы
                 /**
                  * @var CActiveRecord $ar
                  */
                 if (array_key_exists("id", $modelData)) {
                     foreach (CActiveRecordProvider::getWithCondition($properties["joinTable"], trim(CUtils::strLeft($properties["leftCondition"], "=")) . "=" . $modelData["id"])->getItems() as $ar) {
                         $ar->remove();
                     }
                 }
                 // добавим туда новые данные
                 foreach ($data as $value) {
                     $ar = new CActiveRecord(array($properties["rightKey"] => $value["id"], trim(CUtils::strLeft($properties["leftCondition"], "=")) => $modelData["id"], "id" => null));
                     $ar->setTable($properties["joinTable"]);
                     $ar->insert();
                 }
             }
         } elseif ($properties["relationPower"] == RELATION_HAS_MANY) {
             if (array_key_exists($field, $modelData)) {
                 $data = $modelData[$field];
                 // уберем данные из модели
                 unset($modelData[$field]);
                 // если в свойствах отношения указан целевой класс, то
                 // будем обновлять автоматом
                 if (array_key_exists("targetClass", $properties)) {
                     // получим список записей, которые уже есть
                     $targetClass = $properties["targetClass"];
                     /**
                      * @var CActiveModel $targetObj
                      */
                     $targetObj = new $targetClass();
                     $docsToRemove = array();
                     // его может не быть, если запись новая
                     if (array_key_exists("id", $modelData)) {
                         $items = CActiveRecordProvider::getWithCondition($targetObj->getTable(), trim(CUtils::strLeft($properties["storageCondition"], "=")) . "=" . $modelData["id"]);
                         /**
                          * @var CActiveRecord $item
                          */
                         foreach ($items->getItems() as $item) {
                             $docsToRemove[] = $item->getId();
                         }
                     }
                     /**
                      * @var string $item
                      */
                     foreach ($data as $item) {
                         // полученные данные обратно в json, чтобы
                         // можно было все сделать одинаково рекурсивно
                         $childJsonData = json_encode($item);
                         // создадим экземпляр целевого класса
                         /**
                          * @var CActiveModel $targetObj
                          */
                         $targetObj = new $targetClass();
                         $targetObj->updateWithJsonString($childJsonData);
                         $targetObj->save();
                         // уберем из списка добавленную запись
                         if (in_array($targetObj->getId(), $docsToRemove)) {
                             unset($docsToRemove[array_search($targetObj->getId(), $docsToRemove)]);
                         }
                     }
                     // удалим элементы из списка на удаление - мы
                     // их удалили и вместе с другими данными с клиента
                     // они не пришли
                     if (count($docsToRemove) > 0) {
                         CActiveRecordProvider::removeWithCondition($targetObj->getTable(), "id in (" . implode(", ", $docsToRemove) . ")");
                     }
                 }
             }
         }
     }
     // данные обратно в модель
     foreach ($modelData as $key => $value) {
         $this->{$key} = $value;
     }
     return $modelData;
 }