/** * @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; }
protected function afterAdd(Result $result, array $data, Cond $cond = null) { if (!$result->isError() && $result->getResult()) { $parentId = isset($data['parent_id']) ? $data['parent_id'] : null; $parent = $this->getById($parentId); $updateData = array('tree_path' => trim($parent->getTreePath() . ',' . $result->getResult(), ',')); $this->updateById($updateData, $result->getResult()); } return $result; }