Commit 5ffd0503 authored by Jeremy Mikola's avatar Jeremy Mikola

Merge pull request #189

parents c3e4774e c560e14e
<?php
namespace MongoDB\Exception;
class GridFSCorruptFileException extends \MongoDB\Driver\Exception\RuntimeException implements Exception
{
}
<?php
namespace MongoDB\Exception;
class GridFSFileNotFoundException extends \MongoDB\Driver\Exception\RuntimeException implements Exception
{
public function __construct($filename, $namespace)
{
parent::__construct(sprintf('Unable to find file "%s" in namespace "%s"', $filename, $namespace));
}
}
This diff is collapsed.
...@@ -3,19 +3,22 @@ ...@@ -3,19 +3,22 @@
namespace MongoDB\GridFS; namespace MongoDB\GridFS;
use MongoDB\Collection; use MongoDB\Collection;
use MongoDB\UpdateResult;
use MongoDB\Driver\Cursor;
use MongoDB\Driver\Manager; use MongoDB\Driver\Manager;
use MongoDB\Driver\ReadPreference; use MongoDB\Driver\ReadPreference;
use MongoDB\Driver\WriteConcern; use IteratorIterator;
use stdClass;
/** /**
* GridFSCollectionsWrapper abstracts the GridFS files and chunks collections. * CollectionWrapper abstracts the GridFS files and chunks collections.
* *
* @internal * @internal
*/ */
class GridFSCollectionsWrapper class CollectionWrapper
{ {
private $chunksCollection; private $chunksCollection;
private $ensuredIndexes = false; private $checkedIndexes = false;
private $filesCollection; private $filesCollection;
/** /**
...@@ -34,33 +37,183 @@ class GridFSCollectionsWrapper ...@@ -34,33 +37,183 @@ class GridFSCollectionsWrapper
$this->chunksCollection = new Collection($manager, $databaseName, sprintf('%s.chunks', $bucketName), $collectionOptions); $this->chunksCollection = new Collection($manager, $databaseName, sprintf('%s.chunks', $bucketName), $collectionOptions);
} }
public function dropCollections(){ /**
$this->filesCollection-> drop(); * Deletes all GridFS chunks for a given file ID.
*
* @param mixed $id
*/
public function deleteChunksByFilesId($id)
{
$this->chunksCollection->deleteMany(['files_id' => $id]);
}
/**
* Deletes a GridFS file and related chunks by ID.
*
* @param mixed $id
*/
public function deleteFileAndChunksById($id)
{
$this->filesCollection->deleteOne(['_id' => $id]);
$this->chunksCollection->deleteMany(['files_id' => $id]);
}
/**
* Drops the GridFS files and chunks collections.
*/
public function dropCollections()
{
$this->filesCollection->drop();
$this->chunksCollection->drop(); $this->chunksCollection->drop();
} }
/**
* Finds a GridFS file document for a given filename and revision.
*
* Revision numbers are defined as follows:
*
* * 0 = the original stored file
* * 1 = the first revision
* * 2 = the second revision
* * etc…
* * -2 = the second most recent revision
* * -1 = the most recent revision
*
* @see Bucket::downloadToStreamByName()
* @see Bucket::openDownloadStreamByName()
* @param string $filename
* @param integer $revision
* @return stdClass|null
*/
public function findFileByFilenameAndRevision($filename, $revision)
{
$filename = (string) $filename;
$revision = (integer) $revision;
if ($revision < 0) {
$skip = abs($revision) - 1;
$sortOrder = -1;
} else {
$skip = $revision;
$sortOrder = 1;
}
return $this->filesCollection->findOne(
['filename' => $filename],
[
'skip' => $skip,
'sort' => ['uploadDate' => $sortOrder],
'typeMap' => ['root' => 'stdClass'],
]
);
}
/**
* Finds a GridFS file document for a given ID.
*
* @param mixed $id
* @return stdClass|null
*/
public function findFileById($id)
{
return $this->filesCollection->findOne(
['_id' => $id],
['typeMap' => ['root' => 'stdClass']]
);
}
/**
* Finds documents from the GridFS bucket's files collection.
*
* @see Find::__construct() for supported options
* @param array|object $filter Query by which to filter documents
* @param array $options Additional options
* @return Cursor
*/
public function findFiles($filter, array $options = [])
{
return $this->filesCollection->find($filter, $options);
}
// TODO: Remove this
public function getChunksCollection() public function getChunksCollection()
{ {
return $this->chunksCollection; return $this->chunksCollection;
} }
/**
* Returns a chunks iterator for a given file ID.
*
* @param mixed $id
* @return IteratorIterator
*/
public function getChunksIteratorByFilesId($id)
{
$cursor = $this->chunksCollection->find(
['files_id' => $id],
[
'sort' => ['n' => 1],
'typeMap' => ['root' => 'stdClass'],
]
);
return new IteratorIterator($cursor);
}
// TODO: Remove this
public function getFilesCollection() public function getFilesCollection()
{ {
return $this->filesCollection; return $this->filesCollection;
} }
/**
* Inserts a document into the chunks collection.
*
* @param array|object $chunk Chunk document
*/
public function insertChunk($chunk) public function insertChunk($chunk)
{ {
$this->ensureIndexes(); if ( ! $this->checkedIndexes) {
$this->ensureIndexes();
}
$this->chunksCollection->insertOne($chunk); $this->chunksCollection->insertOne($chunk);
} }
/**
* Inserts a document into the files collection.
*
* The file document should be inserted after all chunks have been inserted.
*
* @param array|object $file File document
*/
public function insertFile($file) public function insertFile($file)
{ {
$this->ensureIndexes(); if ( ! $this->checkedIndexes) {
$this->ensureIndexes();
}
$this->filesCollection->insertOne($file); $this->filesCollection->insertOne($file);
} }
/**
* Updates the filename field in the file document for a given ID.
*
* @param mixed $id
* @param string $filename
* @return UpdateResult
*/
public function updateFilenameForId($id, $filename)
{
return $this->filesCollection->updateOne(
['_id' => $id],
['$set' => ['filename' => (string) $filename]]
);
}
/**
* Create an index on the chunks collection if it does not already exist.
*/
private function ensureChunksIndex() private function ensureChunksIndex()
{ {
foreach ($this->chunksCollection->listIndexes() as $index) { foreach ($this->chunksCollection->listIndexes() as $index) {
...@@ -72,6 +225,9 @@ class GridFSCollectionsWrapper ...@@ -72,6 +225,9 @@ class GridFSCollectionsWrapper
$this->chunksCollection->createIndex(['files_id' => 1, 'n' => 1], ['unique' => true]); $this->chunksCollection->createIndex(['files_id' => 1, 'n' => 1], ['unique' => true]);
} }
/**
* Create an index on the files collection if it does not already exist.
*/
private function ensureFilesIndex() private function ensureFilesIndex()
{ {
foreach ($this->filesCollection->listIndexes() as $index) { foreach ($this->filesCollection->listIndexes() as $index) {
...@@ -83,21 +239,33 @@ class GridFSCollectionsWrapper ...@@ -83,21 +239,33 @@ class GridFSCollectionsWrapper
$this->filesCollection->createIndex(['filename' => 1, 'uploadDate' => 1]); $this->filesCollection->createIndex(['filename' => 1, 'uploadDate' => 1]);
} }
/**
* Ensure indexes on the files and chunks collections exist.
*
* This method is called once before the first write operation on a GridFS
* bucket. Indexes are only be created if the files collection is empty.
*/
private function ensureIndexes() private function ensureIndexes()
{ {
if ($this->ensuredIndexes) { if ($this->checkedIndexes) {
return; return;
} }
$this->checkedIndexes = true;
if ( ! $this->isFilesCollectionEmpty()) { if ( ! $this->isFilesCollectionEmpty()) {
return; return;
} }
$this->ensureFilesIndex(); $this->ensureFilesIndex();
$this->ensureChunksIndex(); $this->ensureChunksIndex();
$this->ensuredIndexes = true;
} }
/**
* Returns whether the files collection is empty.
*
* @return boolean
*/
private function isFilesCollectionEmpty() private function isFilesCollectionEmpty()
{ {
return null === $this->filesCollection->findOne([], [ return null === $this->filesCollection->findOne([], [
......
<?php
namespace MongoDB\GridFS\Exception;
use MongoDB\Exception\RuntimeException;
class CorruptFileException extends RuntimeException
{
/**
* Thrown when a chunk is not found for an expected index.
*
* @param integer $expectedIndex Expected index number
* @return self
*/
public static function missingChunk($expectedIndex)
{
return new static(sprintf('Chunk not found for index "%d"', $expectedIndex));
}
/**
* Thrown when a chunk has an unexpected index number.
*
* @param integer $index Actual index number (i.e. "n" field)
* @param integer $expectedIndex Expected index number
* @return self
*/
public static function unexpectedIndex($index, $expectedIndex)
{
return new static(sprintf('Expected chunk to have index "%d" but found "%d"', $expectedIndex, $index));
}
/**
* Thrown when a chunk has an unexpected data size.
*
* @param integer $size Actual size (i.e. "data" field length)
* @param integer $expectedSize Expected size
* @return self
*/
public static function unexpectedSize($size, $expectedSize)
{
return new static(sprintf('Expected chunk to have size "%d" but found "%d"', $expectedSize, $size));
}
}
<?php
namespace MongoDB\GridFS\Exception;
use MongoDB\Exception\RuntimeException;
class FileNotFoundException extends RuntimeException
{
/**
* Thrown when a file cannot be found by its filename and revision.
*
* @param string $filename Filename
* @param integer $revision Revision
* @param string $namespace Namespace for the files collection
* @return self
*/
public static function byFilenameAndRevision($filename, $revision, $namespace)
{
return new static(sprintf('File with name "%s" and revision "%d" not found in "%s"', $filename, $revision, $namespace));
}
/**
* Thrown when a file cannot be found by its ID.
*
* @param mixed $id File ID
* @param string $namespace Namespace for the files collection
* @return self
*/
public static function byId($id, $namespace)
{
$json = \MongoDB\BSON\toJSON(\MongoDB\BSON\fromPHP(['_id' => $id]));
return new static(sprintf('File "%s" not found in "%s"', $json, $namespace));
}
}
...@@ -3,53 +3,41 @@ ...@@ -3,53 +3,41 @@
namespace MongoDB\GridFS; namespace MongoDB\GridFS;
use MongoDB\Driver\Exception\Exception; use MongoDB\Driver\Exception\Exception;
use MongoDB\Exception\GridFSCorruptFileException; use MongoDB\GridFS\Exception\CorruptFileException;
use stdClass; use stdClass;
/** /**
* GridFSDownload abstracts the process of reading a GridFS file. * ReadableStream abstracts the process of reading a GridFS file.
* *
* @internal * @internal
*/ */
class GridFSDownload class ReadableStream
{ {
private $buffer; private $buffer;
private $bufferEmpty = true; private $bufferEmpty;
private $bufferFresh = true; private $bufferFresh;
private $bytesSeen = 0; private $bytesSeen = 0;
private $chunkOffset = 0; private $chunkOffset = 0;
private $chunksIterator; private $chunksIterator;
private $collectionsWrapper;
private $file; private $file;
private $firstCheck = true; private $firstCheck = true;
private $iteratorEmpty = false; private $iteratorEmpty = false;
private $numChunks; private $numChunks;
/** /**
* Constructs a GridFS download stream. * Constructs a readable GridFS stream.
* *
* @param GridFSCollectionsWrapper $collectionsWrapper GridFS collections wrapper * @param CollectionWrapper $collectionWrapper GridFS collection wrapper
* @param stdClass $file GridFS file document * @param stdClass $file GridFS file document
* @throws GridFSCorruptFileException * @throws CorruptFileException
*/ */
public function __construct(GridFSCollectionsWrapper $collectionsWrapper, stdClass $file) public function __construct(CollectionWrapper $collectionWrapper, stdClass $file)
{ {
$this->collectionsWrapper = $collectionsWrapper;
$this->file = $file; $this->file = $file;
try { $this->chunksIterator = $collectionWrapper->getChunksIteratorByFilesId($this->file->_id);
$cursor = $this->collectionsWrapper->getChunksCollection()->find(
['files_id' => $this->file->_id],
['sort' => ['n' => 1]]
);
} catch (Exception $e) {
// TODO: Why do we replace a driver exception with GridFSCorruptFileException here?
throw new GridFSCorruptFileException();
}
$this->chunksIterator = new \IteratorIterator($cursor);
$this->numChunks = ($file->length >= 0) ? ceil($file->length / $file->chunkSize) : 0; $this->numChunks = ($file->length >= 0) ? ceil($file->length / $file->chunkSize) : 0;
$this->buffer = fopen('php://temp', 'w+'); $this->initEmptyBuffer();
} }
public function close() public function close()
...@@ -57,32 +45,35 @@ class GridFSDownload ...@@ -57,32 +45,35 @@ class GridFSDownload
fclose($this->buffer); fclose($this->buffer);
} }
public function downloadNumBytes($numToRead) /**
* Read bytes from the stream.
*
* Note: this method may return a string smaller than the requested length
* if data is not available to be read.
*
* @param integer $numBytes Number of bytes to read
* @return string
*/
public function downloadNumBytes($numBytes)
{ {
$output = "";
if ($this->bufferFresh) { if ($this->bufferFresh) {
rewind($this->buffer); rewind($this->buffer);
$this->bufferFresh = false; $this->bufferFresh = false;
} }
// TODO: Should we be checking for fread errors here? // TODO: Should we be checking for fread errors here?
$output = fread($this->buffer, $numToRead); $output = fread($this->buffer, $numBytes);
if (strlen($output) == $numToRead) { if (strlen($output) == $numBytes) {
return $output; return $output;
} }
fclose($this->buffer); $this->initEmptyBuffer();
$this->buffer = fopen("php://temp", "w+");
$this->bufferFresh = true;
$this->bufferEmpty = true;
$bytesLeft = $numToRead - strlen($output); $bytesLeft = $numBytes - strlen($output);
while (strlen($output) < $numToRead && $this->advanceChunks()) { while (strlen($output) < $numBytes && $this->advanceChunks()) {
$bytesLeft = $numToRead - strlen($output); $bytesLeft = $numBytes - strlen($output);
$output .= substr($this->chunksIterator->current()->data->getData(), 0, $bytesLeft); $output .= substr($this->chunksIterator->current()->data->getData(), 0, $bytesLeft);
} }
...@@ -94,8 +85,18 @@ class GridFSDownload ...@@ -94,8 +85,18 @@ class GridFSDownload
return $output; return $output;
} }
/**
* Writes the contents of this GridFS file to a writable stream.
*
* @param resource $destination Writable stream
* @throws InvalidArgumentException
*/
public function downloadToStream($destination) public function downloadToStream($destination)
{ {
if ( ! is_resource($destination) || get_resource_type($destination) != "stream") {
throw InvalidArgumentException::invalidType('$destination', $destination, 'resource');
}
while ($this->advanceChunks()) { while ($this->advanceChunks()) {
// TODO: Should we be checking for fwrite errors here? // TODO: Should we be checking for fwrite errors here?
fwrite($destination, $this->chunksIterator->current()->data->getData()); fwrite($destination, $this->chunksIterator->current()->data->getData());
...@@ -138,11 +139,11 @@ class GridFSDownload ...@@ -138,11 +139,11 @@ class GridFSDownload
} }
if ( ! $this->chunksIterator->valid()) { if ( ! $this->chunksIterator->valid()) {
throw new GridFSCorruptFileException(); throw CorruptFileException::missingChunk($this->chunkOffset);
} }
if ($this->chunksIterator->current()->n != $this->chunkOffset) { if ($this->chunksIterator->current()->n != $this->chunkOffset) {
throw new GridFSCorruptFileException(); throw CorruptFileException::unexpectedIndex($this->chunksIterator->current()->n, $this->chunkOffset);
} }
$actualChunkSize = strlen($this->chunksIterator->current()->data->getData()); $actualChunkSize = strlen($this->chunksIterator->current()->data->getData());
...@@ -152,7 +153,7 @@ class GridFSDownload ...@@ -152,7 +153,7 @@ class GridFSDownload
: $this->file->chunkSize; : $this->file->chunkSize;
if ($actualChunkSize != $expectedChunkSize) { if ($actualChunkSize != $expectedChunkSize) {
throw new GridFSCorruptFileException(); throw CorruptFileException::unexpectedSize($actualChunkSize, $expectedChunkSize);
} }
$this->bytesSeen += $actualChunkSize; $this->bytesSeen += $actualChunkSize;
...@@ -160,4 +161,15 @@ class GridFSDownload ...@@ -160,4 +161,15 @@ class GridFSDownload
return true; return true;
} }
private function initEmptyBuffer()
{
if (isset($this->buffer)) {
fclose($this->buffer);
}
$this->buffer = fopen("php://temp", "w+");
$this->bufferEmpty = true;
$this->bufferFresh = true;
}
} }
...@@ -11,96 +11,130 @@ namespace MongoDB\GridFS; ...@@ -11,96 +11,130 @@ namespace MongoDB\GridFS;
*/ */
class StreamWrapper class StreamWrapper
{ {
/**
* @var resource|null Stream context (set by PHP)
*/
public $context; public $context;
private $collectionsWrapper;
private $gridFSStream;
private $id;
private $mode; private $mode;
private $protocol;
private $stream;
public function getId() public function getId()
{ {
return $this->id; return $this->stream->getId();
}
public function openReadStream()
{
$context = stream_context_get_options($this->context);
$this->gridFSStream = new GridFSDownload($this->collectionsWrapper, $context['gridfs']['file']);
$this->id = $this->gridFSStream->getId();
return true;
}
public function openWriteStream()
{
$context = stream_context_get_options($this->context);
$options = $context['gridfs']['uploadOptions'];
$this->gridFSStream = new GridFSUpload($this->collectionsWrapper, $this->identifier, $options);
$this->id = $this->gridFSStream->getId();
return true;
} }
/** /**
* Register the GridFS stream wrapper. * Register the GridFS stream wrapper.
*
* @param string $protocol Protocol to use for stream_wrapper_register()
*/ */
public static function register() public static function register($protocol = 'gridfs')
{ {
if (in_array('gridfs', stream_get_wrappers())) { if (in_array($protocol, stream_get_wrappers())) {
stream_wrapper_unregister('gridfs'); stream_wrapper_unregister($protocol);
} }
stream_wrapper_register('gridfs', get_called_class(), \STREAM_IS_URL); stream_wrapper_register($protocol, get_called_class(), \STREAM_IS_URL);
} }
/**
* Closes the stream.
*
* @see http://php.net/manual/en/streamwrapper.stream-close.php
*/
public function stream_close() public function stream_close()
{ {
$this->gridFSStream->close(); $this->stream->close();
} }
/**
* Returns whether the file pointer is at the end of the stream.
*
* @see http://php.net/manual/en/streamwrapper.stream-eof.php
* @return boolean
*/
public function stream_eof() public function stream_eof()
{ {
return $this->gridFSStream->isEOF(); return $this->stream->isEOF();
} }
/**
* Opens the stream.
*
* @see http://php.net/manual/en/streamwrapper.stream-open.php
* @param string $path Path to the file resource
* @param string $mode Mode used to open the file (only "r" and "w" are supported)
* @param integer $options Additional flags set by the streams API
* @param string $openedPath Not used
*/
public function stream_open($path, $mode, $options, &$openedPath) public function stream_open($path, $mode, $options, &$openedPath)
{ {
$this->initProtocol($path); $this->initProtocol($path);
$context = stream_context_get_options($this->context);
$this->collectionsWrapper = $context['gridfs']['collectionsWrapper'];
$this->mode = $mode; $this->mode = $mode;
switch ($this->mode) { if ($mode === 'r') {
case 'r': return $this->openReadStream(); return $this->initReadableStream();
case 'w': return $this->openWriteStream(); }
default: return false;
if ($mode === 'w') {
return $this->initWritableStream();
} }
return false;
} }
/**
* Read bytes from the stream.
*
* Note: this method may return a string smaller than the requested length
* if data is not available to be read.
*
* @see http://php.net/manual/en/streamwrapper.stream-read.php
* @param integer $count Number of bytes to read
* @return string
*/
public function stream_read($count) public function stream_read($count)
{ {
return $this->gridFSStream->downloadNumBytes($count); // TODO: Ensure that $this->stream is a ReadableStream
return $this->stream->downloadNumBytes($count);
} }
/**
* Return information about the stream.
*
* @see http://php.net/manual/en/streamwrapper.stream-stat.php
* @return array
*/
public function stream_stat() public function stream_stat()
{ {
$stat = $this->getStatTemplate(); $stat = $this->getStatTemplate();
$stat[7] = $stat['size'] = $this->gridFSStream->getSize();
$stat[2] = $stat['mode'] = $this->mode;
$stat[7] = $stat['size'] = $this->stream->getSize();
return $stat; return $stat;
} }
/**
* Write bytes to the stream.
*
* @see http://php.net/manual/en/streamwrapper.stream-write.php
* @param string $data Data to write
* @return integer The number of bytes successfully stored
*/
public function stream_write($data) public function stream_write($data)
{ {
$this->gridFSStream->insertChunks($data); // TODO: Ensure that $this->stream is a WritableStream
$this->stream->insertChunks($data);
return strlen($data); return strlen($data);
} }
/** /**
* Gets a URL stat template with default values * Returns a stat template with default values.
* from https://github.com/aws/aws-sdk-php/blob/master/src/S3/StreamWrapper.php *
* @return array * @return array
*/ */
private function getStatTemplate() private function getStatTemplate()
...@@ -122,9 +156,52 @@ class StreamWrapper ...@@ -122,9 +156,52 @@ class StreamWrapper
]; ];
} }
/**
* Initialize the protocol from the given path.
*
* @see StreamWrapper::stream_open()
* @param string $path
*/
private function initProtocol($path) private function initProtocol($path)
{ {
$parsed_path = parse_url($path); $parts = explode('://', $path, 2);
$this->identifier = substr($parsed_path['path'], 1); $this->protocol = $parts[0] ?: 'gridfs';
}
/**
* Initialize the internal stream for reading.
*
* @see StreamWrapper::stream_open()
* @return boolean
*/
private function initReadableStream()
{
$context = stream_context_get_options($this->context);
$this->stream = new ReadableStream(
$context[$this->protocol]['collectionWrapper'],
$context[$this->protocol]['file']
);
return true;
}
/**
* Initialize the internal stream for writing.
*
* @see StreamWrapper::stream_open()
* @return boolean
*/
private function initWritableStream()
{
$context = stream_context_get_options($this->context);
$this->stream = new WritableStream(
$context[$this->protocol]['collectionWrapper'],
$context[$this->protocol]['filename'],
$context[$this->protocol]['options']
);
return true;
} }
} }
...@@ -5,32 +5,35 @@ namespace MongoDB\GridFS; ...@@ -5,32 +5,35 @@ namespace MongoDB\GridFS;
use MongoDB\BSON\Binary; use MongoDB\BSON\Binary;
use MongoDB\BSON\ObjectId; use MongoDB\BSON\ObjectId;
use MongoDB\BSON\UTCDateTime; use MongoDB\BSON\UTCDateTime;
use MongoDB\Driver\Exception\Exception; use MongoDB\Driver\Exception\Exception as DriverException;
use MongoDB\Exception\InvalidArgumentException; use MongoDB\Exception\InvalidArgumentException;
/** /**
* GridFSUpload abstracts the process of writing a GridFS file. * WritableStream abstracts the process of writing a GridFS file.
* *
* @internal * @internal
*/ */
class GridFSUpload class WritableStream
{ {
private static $defaultChunkSizeBytes = 261120;
private $buffer; private $buffer;
private $bufferLength = 0; private $bufferLength = 0;
private $chunkOffset = 0; private $chunkOffset = 0;
private $chunkSize; private $chunkSize;
private $collectionsWrapper; private $collectionWrapper;
private $ctx; private $ctx;
private $file; private $file;
private $indexChecker;
private $isClosed = false; private $isClosed = false;
private $length = 0; private $length = 0;
/** /**
* Constructs a GridFS upload stream. * Constructs a writable GridFS stream.
* *
* Supported options: * Supported options:
* *
* * _id (mixed): File document identifier. Defaults to a new ObjectId.
*
* * aliases (array of strings): DEPRECATED An array of aliases. * * aliases (array of strings): DEPRECATED An array of aliases.
* Applications wishing to store aliases should add an aliases field to * Applications wishing to store aliases should add an aliases field to
* the metadata document instead. * the metadata document instead.
...@@ -44,19 +47,26 @@ class GridFSUpload ...@@ -44,19 +47,26 @@ class GridFSUpload
* * metadata (document): User data for the "metadata" field of the files * * metadata (document): User data for the "metadata" field of the files
* collection document. * collection document.
* *
* @param GridFSCollectionsWrapper $collectionsWrapper GridFS collections wrapper * @param CollectionWrapper $collectionWrapper GridFS collection wrapper
* @param string $filename File name * @param string $filename File name
* @param array $options Upload options * @param array $options Upload options
* @throws InvalidArgumentException * @throws InvalidArgumentException
*/ */
public function __construct(GridFSCollectionsWrapper $collectionsWrapper, $filename, array $options = []) public function __construct(CollectionWrapper $collectionWrapper, $filename, array $options = [])
{ {
$options += ['chunkSizeBytes' => 261120]; $options += [
'_id' => new ObjectId,
'chunkSizeBytes' => self::$defaultChunkSizeBytes,
];
if (isset($options['aliases']) && ! \MongoDB\is_string_array($options['aliases'])) { if (isset($options['aliases']) && ! \MongoDB\is_string_array($options['aliases'])) {
throw InvalidArgumentException::invalidType('"aliases" option', $options['aliases'], 'array of strings'); throw InvalidArgumentException::invalidType('"aliases" option', $options['aliases'], 'array of strings');
} }
if (isset($options['chunkSizeBytes']) && ! is_integer($options['chunkSizeBytes'])) {
throw InvalidArgumentException::invalidType('"chunkSizeBytes" option', $options['chunkSizeBytes'], 'integer');
}
if (isset($options['contentType']) && ! is_string($options['contentType'])) { if (isset($options['contentType']) && ! is_string($options['contentType'])) {
throw InvalidArgumentException::invalidType('"contentType" option', $options['contentType'], 'string'); throw InvalidArgumentException::invalidType('"contentType" option', $options['contentType'], 'string');
} }
...@@ -66,15 +76,16 @@ class GridFSUpload ...@@ -66,15 +76,16 @@ class GridFSUpload
} }
$this->chunkSize = $options['chunkSizeBytes']; $this->chunkSize = $options['chunkSizeBytes'];
$this->collectionsWrapper = $collectionsWrapper; $this->collectionWrapper = $collectionWrapper;
$this->buffer = fopen('php://temp', 'w+'); $this->buffer = fopen('php://temp', 'w+');
$this->ctx = hash_init('md5'); $this->ctx = hash_init('md5');
$this->file = [ $this->file = [
'_id' => new ObjectId(), '_id' => $options['_id'],
'chunkSize' => $this->chunkSize, 'chunkSize' => $this->chunkSize,
'filename' => (string) $filename, 'filename' => (string) $filename,
'uploadDate' => $this->createUploadDate(), // TODO: This is necessary until PHPC-536 is implemented
'uploadDate' => new UTCDateTime(floor(microtime(true) * 1000)),
] + array_intersect_key($options, ['aliases' => 1, 'contentType' => 1, 'metadata' => 1]); ] + array_intersect_key($options, ['aliases' => 1, 'contentType' => 1, 'metadata' => 1]);
} }
...@@ -133,7 +144,7 @@ class GridFSUpload ...@@ -133,7 +144,7 @@ class GridFSUpload
* reset. * reset.
* *
* @param string $toWrite Binary data to write * @param string $toWrite Binary data to write
* @return int * @return integer
*/ */
public function insertChunks($toWrite) public function insertChunks($toWrite)
{ {
...@@ -171,6 +182,7 @@ class GridFSUpload ...@@ -171,6 +182,7 @@ class GridFSUpload
* *
* @param resource $source Readable stream * @param resource $source Readable stream
* @return ObjectId * @return ObjectId
* @throws InvalidArgumentException
*/ */
public function uploadFromStream($source) public function uploadFromStream($source)
{ {
...@@ -178,8 +190,6 @@ class GridFSUpload ...@@ -178,8 +190,6 @@ class GridFSUpload
throw InvalidArgumentException::invalidType('$source', $source, 'resource'); throw InvalidArgumentException::invalidType('$source', $source, 'resource');
} }
$streamMetadata = stream_get_meta_data($source);
while ($data = $this->readChunk($source)) { while ($data = $this->readChunk($source)) {
$this->insertChunk($data); $this->insertChunk($data);
} }
...@@ -189,20 +199,10 @@ class GridFSUpload ...@@ -189,20 +199,10 @@ class GridFSUpload
private function abort() private function abort()
{ {
$this->collectionsWrapper->getChunksCollection()->deleteMany(['files_id' => $this->file['_id']]); $this->collectionWrapper->deleteChunksByFilesId($this->file['_id']);
$this->collectionsWrapper->getFilesCollection()->deleteOne(['_id' => $this->file['_id']]);
$this->isClosed = true; $this->isClosed = true;
} }
// From: http://stackoverflow.com/questions/3656713/how-to-get-current-time-in-milliseconds-in-php
private function createUploadDate()
{
$parts = explode(' ', microtime());
$milliseconds = sprintf('%d%03d', $parts[1], $parts[0] * 1000);
return new UTCDateTime($milliseconds);
}
private function fileCollectionInsert() private function fileCollectionInsert()
{ {
if ($this->isClosed) { if ($this->isClosed) {
...@@ -215,7 +215,7 @@ class GridFSUpload ...@@ -215,7 +215,7 @@ class GridFSUpload
$this->file['length'] = $this->length; $this->file['length'] = $this->length;
$this->file['md5'] = $md5; $this->file['md5'] = $md5;
$this->collectionsWrapper->insertFile($this->file); $this->collectionWrapper->insertFile($this->file);
return $this->file['_id']; return $this->file['_id'];
} }
...@@ -235,7 +235,7 @@ class GridFSUpload ...@@ -235,7 +235,7 @@ class GridFSUpload
hash_update($this->ctx, $data); hash_update($this->ctx, $data);
$this->collectionsWrapper->insertChunk($toUpload); $this->collectionWrapper->insertChunk($toUpload);
$this->length += strlen($data); $this->length += strlen($data);
$this->chunkOffset++; $this->chunkOffset++;
} }
...@@ -244,7 +244,7 @@ class GridFSUpload ...@@ -244,7 +244,7 @@ class GridFSUpload
{ {
try { try {
$data = fread($source, $this->chunkSize); $data = fread($source, $this->chunkSize);
} catch (Exception $e) { } catch (DriverException $e) {
$this->abort(); $this->abort();
throw $e; throw $e;
} }
......
...@@ -63,8 +63,8 @@ class BucketFunctionalTest extends FunctionalTestCase ...@@ -63,8 +63,8 @@ class BucketFunctionalTest extends FunctionalTestCase
$id = $this->bucket->uploadFromStream("test_filename", $this->generateStream("hello world")); $id = $this->bucket->uploadFromStream("test_filename", $this->generateStream("hello world"));
$contents = stream_get_contents($this->bucket->openDownloadStream($id)); $contents = stream_get_contents($this->bucket->openDownloadStream($id));
$this->assertEquals("hello world", $contents); $this->assertEquals("hello world", $contents);
$this->assertEquals(1, $this->bucket->getCollectionsWrapper()->getFilesCollection()->count()); $this->assertEquals(1, $this->bucket->getCollectionWrapper()->getFilesCollection()->count());
$this->assertEquals(1, $this->bucket->getCollectionsWrapper()->getChunksCollection()->count()); $this->assertEquals(1, $this->bucket->getCollectionWrapper()->getChunksCollection()->count());
$this->bucket->delete($id); $this->bucket->delete($id);
$error=null; $error=null;
...@@ -73,19 +73,19 @@ class BucketFunctionalTest extends FunctionalTestCase ...@@ -73,19 +73,19 @@ class BucketFunctionalTest extends FunctionalTestCase
} catch(\MongoDB\Exception\Exception $e) { } catch(\MongoDB\Exception\Exception $e) {
$error = $e; $error = $e;
} }
$fileNotFound = '\MongoDB\Exception\GridFSFileNotFoundException'; $fileNotFound = '\MongoDB\GridFS\Exception\FileNotFoundException';
$this->assertTrue($error instanceof $fileNotFound); $this->assertTrue($error instanceof $fileNotFound);
$this->assertEquals(0, $this->bucket->getCollectionsWrapper()->getFilesCollection()->count()); $this->assertEquals(0, $this->bucket->getCollectionWrapper()->getFilesCollection()->count());
$this->assertEquals(0, $this->bucket->getCollectionsWrapper()->getChunksCollection()->count()); $this->assertEquals(0, $this->bucket->getCollectionWrapper()->getChunksCollection()->count());
} }
public function testMultiChunkDelete() public function testMultiChunkDelete()
{ {
$id = $this->bucket->uploadFromStream("test_filename", $this->generateStream("hello"), ['chunkSizeBytes'=>1]); $id = $this->bucket->uploadFromStream("test_filename", $this->generateStream("hello"), ['chunkSizeBytes'=>1]);
$this->assertEquals(1, $this->bucket->getCollectionsWrapper()->getFilesCollection()->count()); $this->assertEquals(1, $this->bucket->getCollectionWrapper()->getFilesCollection()->count());
$this->assertEquals(5, $this->bucket->getCollectionsWrapper()->getChunksCollection()->count()); $this->assertEquals(5, $this->bucket->getCollectionWrapper()->getChunksCollection()->count());
$this->bucket->delete($id); $this->bucket->delete($id);
$this->assertEquals(0, $this->bucket->getCollectionsWrapper()->getFilesCollection()->count()); $this->assertEquals(0, $this->bucket->getCollectionWrapper()->getFilesCollection()->count());
$this->assertEquals(0, $this->bucket->getCollectionsWrapper()->getChunksCollection()->count()); $this->assertEquals(0, $this->bucket->getCollectionWrapper()->getChunksCollection()->count());
} }
public function testEmptyFile() public function testEmptyFile()
...@@ -93,10 +93,10 @@ class BucketFunctionalTest extends FunctionalTestCase ...@@ -93,10 +93,10 @@ class BucketFunctionalTest extends FunctionalTestCase
$id = $this->bucket->uploadFromStream("test_filename",$this->generateStream("")); $id = $this->bucket->uploadFromStream("test_filename",$this->generateStream(""));
$contents = stream_get_contents($this->bucket->openDownloadStream($id)); $contents = stream_get_contents($this->bucket->openDownloadStream($id));
$this->assertEquals("", $contents); $this->assertEquals("", $contents);
$this->assertEquals(1, $this->bucket->getCollectionsWrapper()->getFilesCollection()->count()); $this->assertEquals(1, $this->bucket->getCollectionWrapper()->getFilesCollection()->count());
$this->assertEquals(0, $this->bucket->getCollectionsWrapper()->getChunksCollection()->count()); $this->assertEquals(0, $this->bucket->getCollectionWrapper()->getChunksCollection()->count());
$raw = $this->bucket->getCollectionsWrapper()->getFilesCollection()->findOne(); $raw = $this->bucket->getCollectionWrapper()->getFilesCollection()->findOne();
$this->assertEquals(0, $raw->length); $this->assertEquals(0, $raw->length);
$this->assertEquals($id, $raw->_id); $this->assertEquals($id, $raw->_id);
$this->assertTrue($raw->uploadDate instanceof \MongoDB\BSON\UTCDateTime); $this->assertTrue($raw->uploadDate instanceof \MongoDB\BSON\UTCDateTime);
...@@ -107,7 +107,7 @@ class BucketFunctionalTest extends FunctionalTestCase ...@@ -107,7 +107,7 @@ class BucketFunctionalTest extends FunctionalTestCase
{ {
$id = $this->bucket->uploadFromStream("test_filename", $this->generateStream("foobar")); $id = $this->bucket->uploadFromStream("test_filename", $this->generateStream("foobar"));
$this->collectionsWrapper->getChunksCollection()->updateOne(['files_id' => $id], $this->collectionWrapper->getChunksCollection()->updateOne(['files_id' => $id],
['$set' => ['data' => new \MongoDB\BSON\Binary('foo', \MongoDB\BSON\Binary::TYPE_GENERIC)]]); ['$set' => ['data' => new \MongoDB\BSON\Binary('foo', \MongoDB\BSON\Binary::TYPE_GENERIC)]]);
$error = null; $error = null;
try{ try{
...@@ -116,14 +116,14 @@ class BucketFunctionalTest extends FunctionalTestCase ...@@ -116,14 +116,14 @@ class BucketFunctionalTest extends FunctionalTestCase
} catch(\MongoDB\Exception\Exception $e) { } catch(\MongoDB\Exception\Exception $e) {
$error = $e; $error = $e;
} }
$corruptFileError = '\MongoDB\Exception\GridFSCOrruptFileException'; $corruptFileError = '\MongoDB\GridFS\Exception\CorruptFileException';
$this->assertTrue($error instanceof $corruptFileError); $this->assertTrue($error instanceof $corruptFileError);
} }
public function testErrorsOnMissingChunk() public function testErrorsOnMissingChunk()
{ {
$id = $this->bucket->uploadFromStream("test_filename", $this->generateStream("hello world,abcdefghijklmnopqrstuv123456789"), ["chunkSizeBytes" => 1]); $id = $this->bucket->uploadFromStream("test_filename", $this->generateStream("hello world,abcdefghijklmnopqrstuv123456789"), ["chunkSizeBytes" => 1]);
$this->collectionsWrapper->getChunksCollection()->deleteOne(['files_id' => $id, 'n' => 7]); $this->collectionWrapper->getChunksCollection()->deleteOne(['files_id' => $id, 'n' => 7]);
$error = null; $error = null;
try{ try{
$download = $this->bucket->openDownloadStream($id); $download = $this->bucket->openDownloadStream($id);
...@@ -131,13 +131,13 @@ class BucketFunctionalTest extends FunctionalTestCase ...@@ -131,13 +131,13 @@ class BucketFunctionalTest extends FunctionalTestCase
} catch(\MongoDB\Exception\Exception $e) { } catch(\MongoDB\Exception\Exception $e) {
$error = $e; $error = $e;
} }
$corruptFileError = '\MongoDB\Exception\GridFSCOrruptFileException'; $corruptFileError = '\MongoDB\GridFS\Exception\CorruptFileException';
$this->assertTrue($error instanceof $corruptFileError); $this->assertTrue($error instanceof $corruptFileError);
} }
public function testUploadEnsureIndexes() public function testUploadEnsureIndexes()
{ {
$chunks = $this->bucket->getCollectionsWrapper()->getChunksCollection(); $chunks = $this->bucket->getCollectionWrapper()->getChunksCollection();
$files = $this->bucket->getCollectionsWrapper()->getFilesCollection(); $files = $this->bucket->getCollectionWrapper()->getFilesCollection();
$this->bucket->uploadFromStream("filename", $this->generateStream("junk")); $this->bucket->uploadFromStream("filename", $this->generateStream("junk"));
$chunksIndexed = false; $chunksIndexed = false;
...@@ -177,7 +177,7 @@ class BucketFunctionalTest extends FunctionalTestCase ...@@ -177,7 +177,7 @@ class BucketFunctionalTest extends FunctionalTestCase
} catch(\MongoDB\Exception\Exception $e) { } catch(\MongoDB\Exception\Exception $e) {
$error = $e; $error = $e;
} }
$fileNotFound = '\MongoDB\Exception\GridFSFileNotFoundException'; $fileNotFound = '\MongoDB\GridFS\Exception\FileNotFoundException';
$this->assertTrue($error instanceof $fileNotFound); $this->assertTrue($error instanceof $fileNotFound);
} }
public function testGetVersion() public function testGetVersion()
...@@ -194,7 +194,7 @@ class BucketFunctionalTest extends FunctionalTestCase ...@@ -194,7 +194,7 @@ class BucketFunctionalTest extends FunctionalTestCase
$this->assertEquals("bar", stream_get_contents($this->bucket->openDownloadStreamByName("test", ['revision' => -2]))); $this->assertEquals("bar", stream_get_contents($this->bucket->openDownloadStreamByName("test", ['revision' => -2])));
$this->assertEquals("foo", stream_get_contents($this->bucket->openDownloadStreamByName("test", ['revision' => -3]))); $this->assertEquals("foo", stream_get_contents($this->bucket->openDownloadStreamByName("test", ['revision' => -3])));
$fileNotFound = '\MongoDB\Exception\GridFSFileNotFoundException'; $fileNotFound = '\MongoDB\GridFS\Exception\FileNotFoundException';
$error = null; $error = null;
try{ try{
$this->bucket->openDownloadStreamByName("test", ['revision' => 3]); $this->bucket->openDownloadStreamByName("test", ['revision' => 3]);
...@@ -238,7 +238,7 @@ class BucketFunctionalTest extends FunctionalTestCase ...@@ -238,7 +238,7 @@ class BucketFunctionalTest extends FunctionalTestCase
public function testGridInNonIntChunksize() public function testGridInNonIntChunksize()
{ {
$id = $this->bucket->uploadFromStream("f",$this->generateStream("data")); $id = $this->bucket->uploadFromStream("f",$this->generateStream("data"));
$this->bucket->getCollectionsWrapper()->getFilesCollection()->updateOne(["filename"=>"f"], $this->bucket->getCollectionWrapper()->getFilesCollection()->updateOne(["filename"=>"f"],
['$set'=> ['chunkSize' => 100.00]]); ['$set'=> ['chunkSize' => 100.00]]);
$this->assertEquals("data", stream_get_contents($this->bucket->openDownloadStream($id))); $this->assertEquals("data", stream_get_contents($this->bucket->openDownloadStream($id)));
} }
...@@ -278,7 +278,7 @@ class BucketFunctionalTest extends FunctionalTestCase ...@@ -278,7 +278,7 @@ class BucketFunctionalTest extends FunctionalTestCase
} catch(\MongoDB\Exception\Exception $e) { } catch(\MongoDB\Exception\Exception $e) {
$error = $e; $error = $e;
} }
$fileNotFound = '\MongoDB\Exception\GridFSFileNotFoundException'; $fileNotFound = '\MongoDB\GridFS\Exception\FileNotFoundException';
$this->assertTrue($error instanceof $fileNotFound); $this->assertTrue($error instanceof $fileNotFound);
$this->assertEquals("testing", stream_get_contents($this->bucket->openDownloadStreamByName("second_name"))); $this->assertEquals("testing", stream_get_contents($this->bucket->openDownloadStreamByName("second_name")));
...@@ -288,7 +288,7 @@ class BucketFunctionalTest extends FunctionalTestCase ...@@ -288,7 +288,7 @@ class BucketFunctionalTest extends FunctionalTestCase
$id = $this->bucket->uploadFromStream("test_filename", $this->generateStream("hello world")); $id = $this->bucket->uploadFromStream("test_filename", $this->generateStream("hello world"));
$this->bucket->drop(); $this->bucket->drop();
$id = $this->bucket->uploadFromStream("test_filename", $this->generateStream("hello world")); $id = $this->bucket->uploadFromStream("test_filename", $this->generateStream("hello world"));
$this->assertEquals(1, $this->collectionsWrapper->getFilesCollection()->count()); $this->assertEquals(1, $this->collectionWrapper->getFilesCollection()->count());
} }
/** /**
*@dataProvider provideInsertChunks *@dataProvider provideInsertChunks
......
...@@ -12,7 +12,7 @@ use MongoDB\Tests\FunctionalTestCase as BaseFunctionalTestCase; ...@@ -12,7 +12,7 @@ use MongoDB\Tests\FunctionalTestCase as BaseFunctionalTestCase;
abstract class FunctionalTestCase extends BaseFunctionalTestCase abstract class FunctionalTestCase extends BaseFunctionalTestCase
{ {
protected $bucket; protected $bucket;
protected $collectionsWrapper; protected $collectionWrapper;
public function setUp() public function setUp()
{ {
...@@ -22,7 +22,7 @@ abstract class FunctionalTestCase extends BaseFunctionalTestCase ...@@ -22,7 +22,7 @@ abstract class FunctionalTestCase extends BaseFunctionalTestCase
$col->drop(); $col->drop();
} }
$this->bucket = new \MongoDB\GridFS\Bucket($this->manager, $this->getDatabaseName()); $this->bucket = new \MongoDB\GridFS\Bucket($this->manager, $this->getDatabaseName());
$this->collectionsWrapper = $this->bucket->getCollectionsWrapper(); $this->collectionWrapper = $this->bucket->getCollectionWrapper();
} }
public function tearDown() public function tearDown()
......
This diff is collapsed.
...@@ -52,11 +52,11 @@ class SpecificationTests extends FunctionalTestCase ...@@ -52,11 +52,11 @@ class SpecificationTests extends FunctionalTestCase
} catch(\MongoDB\Exception\Exception $e) { } catch(\MongoDB\Exception\Exception $e) {
$error = $e; $error = $e;
} }
$errors = ['FileNotFound' => '\MongoDB\Exception\GridFSFileNotFoundException', $errors = ['FileNotFound' => '\MongoDB\GridFS\Exception\FileNotFoundException',
'ChunkIsMissing' => '\MongoDB\Exception\GridFSCorruptFileException', 'ChunkIsMissing' => '\MongoDB\GridFS\Exception\CorruptFileException',
'ExtraChunk' => '\MongoDB\Exception\GridFSCorruptFileException', 'ExtraChunk' => '\MongoDB\GridFS\Exception\CorruptFileException',
'ChunkIsWrongSize' => '\MongoDB\Exception\GridFSCorruptFileException', 'ChunkIsWrongSize' => '\MongoDB\GridFS\Exception\CorruptFileException',
'RevisionNotFound' => '\MongoDB\Exception\GridFSFileNotFoundException' 'RevisionNotFound' => '\MongoDB\GridFS\Exception\FileNotFoundException'
]; ];
if (!isset($test['assert']['error'])) { if (!isset($test['assert']['error'])) {
$this->assertNull($error); $this->assertNull($error);
...@@ -78,9 +78,9 @@ class SpecificationTests extends FunctionalTestCase ...@@ -78,9 +78,9 @@ class SpecificationTests extends FunctionalTestCase
$fixedAssertTrue = $this->fixTypes($test['assert'], true); $fixedAssertTrue = $this->fixTypes($test['assert'], true);
if (isset($test['assert']['data'])) { if (isset($test['assert']['data'])) {
$this->runCommands($fixedAssertTrue['data'], $result); $this->runCommands($fixedAssertTrue['data'], $result);
$this->collectionsEqual($this->collections['expected.files'],$this->bucket->getCollectionsWrapper()->getFilesCollection()); $this->collectionsEqual($this->collections['expected.files'],$this->bucket->getCollectionWrapper()->getFilesCollection());
if(isset($this->collections['expected.chunks'])) { if(isset($this->collections['expected.chunks'])) {
$this->collectionsEqual($this->collections['expected.chunks'],$this->bucket->getCollectionsWrapper()->getChunksCollection()); $this->collectionsEqual($this->collections['expected.chunks'],$this->bucket->getCollectionWrapper()->getChunksCollection());
} }
} }
} }
...@@ -161,7 +161,7 @@ class SpecificationTests extends FunctionalTestCase ...@@ -161,7 +161,7 @@ class SpecificationTests extends FunctionalTestCase
$cmd['documents'][$docIndex] = $doc; $cmd['documents'][$docIndex] = $doc;
} }
} }
$collection = new Collection($this->manager, sprintf("%s.%s", $this->getDatabaseName(), $collectionName)); $collection = new Collection($this->manager, $this->getDatabaseName(), $collectionName);
$this->commands[$key]($collection, $this->fixTypes($cmd, true)); $this->commands[$key]($collection, $this->fixTypes($cmd, true));
$this->collections[$collectionName] = $collection; $this->collections[$collectionName] = $collection;
} }
...@@ -175,20 +175,20 @@ class SpecificationTests extends FunctionalTestCase ...@@ -175,20 +175,20 @@ class SpecificationTests extends FunctionalTestCase
$collectionsToDrop = ['fs.files','fs.chunks','expected.files','expected.chunks']; $collectionsToDrop = ['fs.files','fs.chunks','expected.files','expected.chunks'];
$data = $this->fixTypes($data, true); $data = $this->fixTypes($data, true);
foreach ($collectionsToDrop as $collectionName) { foreach ($collectionsToDrop as $collectionName) {
$collection = new Collection($this->manager, sprintf("%s.%s", $this->getDatabaseName(), $collectionName)); $collection = new Collection($this->manager, $this->getDatabaseName(), $collectionName);
$collection->drop(); $collection->drop();
} }
if (isset($data['files']) && count($data['files']) > 0) { if (isset($data['files']) && count($data['files']) > 0) {
$filesCollection = new Collection($this->manager, sprintf("%s.%s", $this->getDatabaseName(), "fs.files")); $filesCollection = new Collection($this->manager, $this->getDatabaseName(), "fs.files");
$filesCollection->insertMany($data['files']); $filesCollection->insertMany($data['files']);
$expectedFilesCollection = new Collection($this->manager, sprintf("%s.%s", $this->getDatabaseName(), "expected.files")); $expectedFilesCollection = new Collection($this->manager, $this->getDatabaseName(), "expected.files");
$expectedFilesCollection->insertMany($data['files']); $expectedFilesCollection->insertMany($data['files']);
$this->collections['expected.files'] = $expectedFilesCollection; $this->collections['expected.files'] = $expectedFilesCollection;
} }
if (isset($data['chunks']) && count($data['chunks']) > 0) { if (isset($data['chunks']) && count($data['chunks']) > 0) {
$chunksCollection = new Collection($this->manager, sprintf("%s.%s", $this->getDatabaseName(), "fs.chunks")); $chunksCollection = new Collection($this->manager, $this->getDatabaseName(), "fs.chunks");
$chunksCollection->insertMany($data['chunks']); $chunksCollection->insertMany($data['chunks']);
$expectedChunksCollection = new Collection($this->manager, sprintf("%s.%s", $this->getDatabaseName(), "expected.chunks")); $expectedChunksCollection = new Collection($this->manager, $this->getDatabaseName(), "expected.chunks");
$expectedChunksCollection->insertMany($data['chunks']); $expectedChunksCollection->insertMany($data['chunks']);
$this->collections['expected.chunks'] = $expectedChunksCollection; $this->collections['expected.chunks'] = $expectedChunksCollection;
...@@ -197,7 +197,7 @@ class SpecificationTests extends FunctionalTestCase ...@@ -197,7 +197,7 @@ class SpecificationTests extends FunctionalTestCase
foreach($test['arrange']['data'] as $cmd) { foreach($test['arrange']['data'] as $cmd) {
foreach($cmd as $key => $value) { foreach($cmd as $key => $value) {
if(isset($this->commands[$key])) { if(isset($this->commands[$key])) {
$collection = new Collection($this->manager, sprintf("%s.%s", $this->getDatabaseName(), $cmd[$key])); $collection = new Collection($this->manager, $this->getDatabaseName(), $cmd[$key]);
$this->commands[$key]($collection,$this->fixTypes($cmd, true)); $this->commands[$key]($collection,$this->fixTypes($cmd, true));
} }
} }
...@@ -217,8 +217,6 @@ class SpecificationTests extends FunctionalTestCase ...@@ -217,8 +217,6 @@ class SpecificationTests extends FunctionalTestCase
function downloadCommand($args) function downloadCommand($args)
{ {
$args = $this->fixTypes($args, false); $args = $this->fixTypes($args, false);
$streamWrapper = new \MongoDB\GridFS\StreamWrapper();
$streamWrapper->register($this->manager);
$stream = fopen('php://temp', 'w+'); $stream = fopen('php://temp', 'w+');
$this->bucket->downloadToStream($args['id'], $stream); $this->bucket->downloadToStream($args['id'], $stream);
rewind($stream); rewind($stream);
...@@ -234,11 +232,9 @@ class SpecificationTests extends FunctionalTestCase ...@@ -234,11 +232,9 @@ class SpecificationTests extends FunctionalTestCase
function download_by_nameCommand($args) function download_by_nameCommand($args)
{ {
$args = $this->fixTypes($args, false); $args = $this->fixTypes($args, false);
$streamWrapper = new \MongoDB\GridFS\StreamWrapper();
$streamWrapper->register($this->manager);
$stream = fopen('php://temp', 'w+'); $stream = fopen('php://temp', 'w+');
if(isset($args['options']['revision'])) { if(isset($args['options'])) {
$this->bucket->downloadToStreamByName($args['filename'], $stream, $args['options']['revision']); $this->bucket->downloadToStreamByName($args['filename'], $stream, $args['options']);
} else { } else {
$this->bucket->downloadToStreamByName($args['filename'], $stream); $this->bucket->downloadToStreamByName($args['filename'], $stream);
} }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment