/** * Execute the update query and persist its GridFSFile if necessary. * * @see Collection::doFindOne() * @param array $query * @param array $newObj * @param array $options * @return array|null */ protected function doUpdate(array $query, array $newObj, array $options = []) { $file = isset($newObj['$set']['file']) ? $newObj['$set']['file'] : null; unset($newObj['$set']['file']); if ($file === null) { $file = isset($newObj['file']) ? $newObj['file'] : null; unset($newObj['file']); } /* Before we inspect $newObj, remove an empty $set operator we may have * left behind due to extracting the file field above. */ if (empty($newObj['$set'])) { unset($newObj['$set']); } /* Determine if $newObj includes atomic modifiers, which will tell us if * we can get by with a storeFile() in some situations or if a two-step * storeFile() and update() is necessary. */ $newObjHasModifiers = false; foreach (array_keys($newObj) as $key) { if ('$' === $key[0]) { $newObjHasModifiers = true; } } // Is there a file in need of persisting? if (isset($file) && $file->isDirty()) { /* It is impossible to overwrite a file's chunks in GridFS so we * must remove it and re-persist a new file with the same data. * * First, use findAndRemove() to remove the file metadata and chunks * prior to storing the file again below. Exclude metadata fields * from the result, since those will be reset later. */ $document = $this->findAndRemove($query, ['fields' => ['filename' => 0, 'length' => 0, 'chunkSize' => 0, 'uploadDate' => 0, 'md5' => 0, 'file' => 0]]); /* If findAndRemove() returned nothing (no match or removal), create * a new document with the query's "_id" if available. */ if (!isset($document)) { /* If $newObj had modifiers, we'll need to do an update later, * so default to an empty array for now. Otherwise, we can do * without that update and store $newObj now. */ $document = $newObjHasModifiers ? [] : $newObj; /* If the document has no "_id" but there was one in the query * or $newObj, we can use that instead of having storeFile() * generate one. */ if (!isset($document['_id']) && isset($query['_id'])) { $document['_id'] = $query['_id']; } if (!isset($document['_id']) && isset($newObj['_id'])) { $document['_id'] = $newObj['_id']; } } // Document will definitely have an "_id" after storing the file. $this->storeFile($file, $document); if (!$newObjHasModifiers) { /* TODO: MongoCollection::update() would return a boolean if * $newObj was not empty, or an array describing the update * operation. Improvise, since we only stored the file and that * returns the "_id" field. */ return true; } } // Now send the original update bringing the file up to date $options = isset($options['safe']) ? $this->convertWriteConcern($options) : $options; return $this->mongoCollection->update($query, $newObj, $options); }
/** * update. */ public function update($criteria, $newobj, array $options = array()) { $this->time->start(); $return = parent::update($criteria, $newobj, $options); $time = $this->time->stop(); $this->log(array('type' => 'update', 'criteria' => $criteria, 'newobj' => $newobj, 'options' => $options, 'time' => $time)); return $return; }
/** * Move file into another parent dir. * Return new file path or false. * * @param string $source source file path * @param string $target target dir path * @param string $name file name * @return string **/ protected function _move($source, $targetDir, $name) { $targetDir = preg_replace('~/$~', '', $targetDir); $this->db->update(array('filename' => $this->_basename($source), 'metadata.path' => $this->_dirname($source)), array('$set' => array('filename' => (string) $name, 'metadata.path' => $targetDir))); return $targetDir; }