Пример #1
0
 /**
  * @param      $data
  * @param Cond $cond
  *
  * @throws Exception\ErrorException
  * @throws \Model\Exception\ErrorException
  * @return $this|Result
  */
 public function import($data, Cond $cond = null)
 {
     $tableName = $this->getRawName();
     if (is_null($cond)) {
         $cond = $this->getCond($tableName, $tableName);
     } else {
         /** @var $cond \Model\Cond\AbstractCond */
         $cond = $this->prepareCond($cond);
     }
     $result = new Result();
     $data = $this->prepareData($data);
     $relatedData = array();
     if (empty($data)) {
         return $result->addError("Import {$tableName} failed; Import data is empty", "import_{$tableName}_failed");
     }
     $id = null;
     // Ищем по различным параметрам, может данные уже есть в базе
     // Ищем данные в базе по уникальным полям
     $existsCond = clone $cond;
     $id = $this->getExistedIdByUniqueIndex($data, $existsCond);
     // Идем по всем связям и ищем обязательные связи
     foreach ($this->getRelation() as $rel) {
         if (!$rel['required_link']) {
             continue;
         }
         // Каскад разрешен
         $cascadeAllowed = !$id || $cond->isCascadeAllowed();
         $foreignEntityName = $rel['foreign_entity'];
         $localColumnName = $rel['local_column'];
         /** @var $foreignModel \Model\Mysql\AbstractModel */
         $foreignModel = $rel['foreign_model'];
         if (isset($data) && array_key_exists($localColumnName, $data) && !isset($data['_' . $foreignEntityName])) {
             /**
              * Вложенная сущность сушествует
              */
             $relatedData[$localColumnName] = $data[$localColumnName];
         } elseif ($cascadeAllowed && isset($data['_' . $foreignEntityName])) {
             /**
              * Здесь мы проверяем наличие вложенной сущности,
              * и если она есть то импортируем ее и получаем
              * добавленный идентификатор
              */
             /** @var $foreignModelInstance \Model\Mysql\AbstractModel */
             $foreignModelInstance = $foreignModel::getInstance();
             $importChildResult = $foreignModelInstance->import($data['_' . $foreignEntityName], $cond->getChild($foreignEntityName));
             $result->addChild($foreignEntityName, $importChildResult);
             // Если есть ошибки, то выходим
             if ($importChildResult->isError() && $cond->isIgnoreErrors()) {
                 return $result;
             }
             if ($importChildResult->isValid()) {
                 $relatedData[$localColumnName] = $data[$localColumnName] = $importChildResult->getResult();
             }
             unset($data['_' . $foreignEntityName]);
         }
     }
     // $data могла поменятся ищем еще раз
     $id = $this->getExistedIdByUniqueIndex($data, $existsCond);
     // Если не нашли
     if (!$id) {
         try {
             /** @var $_result Result */
             $addResult = $this->add($data, $cond);
             // Передаем результат добавления в общий результат и берем значение
             $id = $result->setResult($addResult)->getResult();
         } catch (\PDOException $e) {
             // Если ошибка, то добавляем ошибку с кодом import_add_failed в global
             $result->addError('Import add operation failed: ' . $e->getMessage(), 'import_add_failed');
         }
     } elseif ($cond->isUpdateAllowed()) {
         try {
             // Если разрешено обновление, то обновляем данные
             $_cond = clone $cond;
             $_cond->where(array('`' . $this->getRawName() . '`.`id`' => $id));
             $updateAllowedResult = $this->update($data, $_cond);
             $result->setResult($updateAllowedResult);
             unset($_cond);
         } catch (\PDOException $e) {
             // Если ошибка, то добавляем ошибку с кодом import_update_failed в global
             $result->addError('Import update operation failed: ' . $e->getMessage(), 'import_update_failed');
         }
     }
     // relatedData - мы в первом проходе, смотрим,
     // какие связанные сущности есть
     //
     //
     if (!empty($relatedData) && $cond->isCascadeAllowed()) {
         // Если не разрешено обновление, и разрешен каскад, то обновляем только связи
         $_cond = clone $cond;
         $_cond->where(array('`' . $this->getRawName() . '`.`id`' => $id));
         $relatedDataUpdateResult = $this->update($relatedData, $_cond);
         if (!$relatedDataUpdateResult->isValid()) {
             $result->addErrorList($relatedDataUpdateResult->getErrorList());
         }
     }
     // Установить значение результата
     $result->setResult((string) $id);
     // Если ничего не добавилось и опция игнора ошибок отключена, то выходим
     if (!$result->getResult() && !$cond->isIgnoreErrors()) {
         return $result;
     }
     $isIgnoreErrors = $cond->isIgnoreErrors();
     if (($id || $isIgnoreErrors) && $cond->isCascadeAllowed()) {
         foreach ($this->getRelation() as $key => $rel) {
             /** @var $foreignModel \Model\Mysql\AbstractModel */
             $foreignModel = $rel['foreign_model'];
             /** @var $foreignModel \Model\Mysql\AbstractModel */
             $foreignModelInstance = $foreignModel::getInstance();
             $foreignEntityName = $key;
             $foreignColumnName = $rel['foreign_column'];
             if (isset($data['_' . $foreignEntityName])) {
                 $innerData = $this->prepareData($data['_' . $foreignEntityName]);
                 if (!isset($rel['link_table']) && $rel['local_column'] == 'id' && is_array($innerData) && $id) {
                     $innerData[$foreignColumnName] = $id;
                 }
                 $_result = null;
                 // Если основная сущность добавлена, а у вложенной стоит что нельзя добавлять связи,
                 // то эти связи нужно удалить
                 if ($id && !$cond->getChild($foreignEntityName)->isAppendLink()) {
                     // Удаляем связи перед обновлением
                     $unlinkMethod = $rel['unlink_method'];
                     /** @var $unlinkResult Result */
                     $unlinkResult = $this->{$unlinkMethod}($id);
                     if (!$unlinkResult->isValid()) {
                         $result->addChild($foreignEntityName, $unlinkResult);
                         if (!$isIgnoreErrors) {
                             return $result;
                         }
                     }
                 }
                 if ($id && $cond->getChild($foreignEntityName)->isAppendLink()) {
                     if (empty($innerData)) {
                         $result->addChild($foreignEntityName, new Result());
                     } else {
                         $importInnerDataResult = $foreignModelInstance->import($innerData, $cond->getChild($foreignEntityName));
                         $result->addChild($foreignEntityName, $importInnerDataResult);
                         // Если ошибка и пропускать их нельзя
                         if ($result->isError() && !$isIgnoreErrors) {
                             return $result;
                         }
                         // Если при импорте ошибок не было
                         // то линкуем данные с текущей сущностью
                         if (!$importInnerDataResult->isError()) {
                             $linkMethod = $rel['link_method'];
                             $this->{$linkMethod}(array($id), $importInnerDataResult->getResult(), $cond->getChild($foreignEntityName)->isAppendLink());
                         }
                     }
                 }
             }
             // Если связь много ко многим или один ко многим
             if (($rel['type'] = AbstractModel::MANY_TO_MANY || ($rel['type'] = AbstractModel::ONE_TO_MANY)) && isset($data['_' . $foreignEntityName . '_collection'])) {
                 $innerData = $this->prepareData($data['_' . $foreignEntityName . '_collection']);
                 // Если нет таблицы связи и существую данные для обработки
                 if (!isset($rel['link_table']) && is_array($innerData) && $id && is_array(reset($innerData))) {
                     foreach ($innerData as &$item) {
                         $item[$foreignColumnName] = $id;
                     }
                 }
                 // Если основная сущность добавлена, а у вложенной стоит что нельзя добавлять связи,
                 // то эти связи нужно удалить
                 if ($id && !$cond->getChild($foreignEntityName . '_collection')->isAppendLink()) {
                     $unlinkMethod = $rel['unlink_method'];
                     /** @var $_result Result */
                     $unlinkResult = $this->{$unlinkMethod}($id);
                     if ($unlinkResult->isError()) {
                         $result->addChild($foreignEntityName . '_collection', $_result);
                         if (!$cond->isIgnoreErrors()) {
                             return $result;
                         }
                     }
                 }
                 if ($id && $cond->getChild($foreignEntityName . '_collection')->isAppendLink()) {
                     if (empty($data['_' . $foreignEntityName . '_collection'])) {
                         $result->addChild($foreignEntityName . '_collection', new Result());
                     } else {
                         $importCollectionResult = $foreignModelInstance->importCollection($innerData, $cond->getChild($foreignEntityName . '_collection'));
                         $result->addChild($foreignEntityName . '_collection', $importCollectionResult);
                         // Если есть ошибки и допускать их нельзя выходим
                         if ($importCollectionResult->isError() && !$isIgnoreErrors) {
                             return $result;
                         }
                         if (isset($rel['link_table']) && $importCollectionResult->isValid()) {
                             $linkMethod = $rel['link_method'];
                             $this->{$linkMethod}(array($id), $importCollectionResult->getResult(), $cond->isAppendLink());
                         }
                     }
                 }
             }
         }
     }
     return $result;
 }