/** * Save new item * * @param modelBase|array $itemData * @param bool $saveMode * * @return mixed * @throws \Exception * @throws \MongoException * @throws \MongoCursorTimeoutException * @throws \mpcmf\system\configuration\exception\configurationException * @throws \MongoCursorException * @throws \MongoConnectionException * @throws \InvalidArgumentException * @throws \mpcmf\modules\moduleBase\exceptions\modelException * @throws mapperException */ public function save(&$itemData, $saveMode = self::SAVE__MODE_DEFAULT) { if (!isset($this->key)) { $this->initializeRoleFields(); } // $changedFields = []; if ($itemData instanceof modelBase) { MPCMF_DEBUG && self::log()->addDebug('Input data is instance of modelBase', [__METHOD__]); $data = $itemData->export($saveMode === self::SAVE__MODE_CHANGES_ONLY); MPCMF_DEBUG && self::log()->addDebug('Data exported', [__METHOD__]); } else { MPCMF_DEBUG && self::log()->addDebug('Input data is an array', [__METHOD__]); $data =& $itemData; MPCMF_DEBUG && self::log()->addDebug('Variable linked', [__METHOD__]); } MPCMF_DEBUG && self::log()->addDebug('Input data prepared', [__METHOD__]); $primaryKey = $this->getKey(); if (isset($data['_id'])) { MPCMF_DEBUG && self::log()->addDebug('Input data has _id field', [__METHOD__]); if (!$data['_id'] instanceof \MongoId) { if (is_string($data['_id'])) { $data['_id'] = new \MongoId($data['_id']); } elseif (isset($data['_id']['$id'])) { $data['_id'] = new \MongoId($data['_id']['$id']); } } MPCMF_DEBUG && self::log()->addDebug('Input data has _id field, saving...', [__METHOD__]); try { if ($saveMode === self::SAVE__MODE_INSERT_ONLY) { return $this->_create($data); } elseif ($saveMode === self::SAVE__MODE_DEFAULT) { return $this->_save($data); } elseif ($saveMode === self::SAVE__MODE_CHANGES_ONLY) { return $this->updateBy(['_id' => $data['_id']], $data); } throw new mapperException('Unexpected save mode: ' . json_encode($saveMode)); } catch (storageException $storageException) { throw new mapperException('Some error in storage, request failed', $storageException->getCode(), $storageException); } } elseif ($this->keyGenerate) { if (!empty($data[$primaryKey])) { MPCMF_DEBUG && self::log()->addDebug('Input data has generated key field, updating...', [__METHOD__]); return $this->updateById($data[$primaryKey], $data); } $isMongoId = $primaryKey === '_id'; $needUpdateMongoId = !$isMongoId && !isset($data['_id']); $data[$primaryKey] = $isMongoId ? new \MongoId() : $this->generateId(); if ($needUpdateMongoId) { $data['_id'] = new \MongoId(); } try { if ($itemData instanceof modelBase) { $itemData->updateFields($data); } return $this->_create($data); } catch (\Exception $e) { throw new mapperException("Storage exception: {$e->getMessage()}", $e->getCode(), $e); } } elseif (isset($data[$primaryKey]) && !empty($data[$primaryKey])) { MPCMF_DEBUG && self::log()->addDebug('Input data has manually typed key field, updating...', [__METHOD__]); return $this->updateById($data[$primaryKey], $data, true); } throw new mapperException("Unable to save item without key field: {$primaryKey} (generate:off)"); }