Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit 478aff4

Browse files
committed
wip
1 parent ed4cfa1 commit 478aff4

File tree

4 files changed

+398
-1
lines changed

4 files changed

+398
-1
lines changed

‎composer.json‎

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,8 @@
1111
],
1212
"require": {
1313
"php": ">=5.4",
14-
"ext-mongodb": "^1.0.0"
14+
"ext-mongodb": "^1.0.0",
15+
"ext-hash": "*"
1516
},
1617
"autoload": {
1718
"psr-4": { "MongoDB\\": "src/" },

‎src/GridFS/Bucket.php‎

Lines changed: 171 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,171 @@
1+
<?php
2+
3+
namespace MongoDB\GridFS;
4+
5+
use MongoDB\Collection;
6+
use MongoDB\Database;
7+
use MongoDB\BSON\ObjectId;
8+
use MongoDB\Driver\ReadPreference;
9+
use MongoDB\Driver\WriteConcern;
10+
use MongoDB\Exception\InvalidArgumentException;
11+
use MongoDB\Exception\InvalidArgumentTypeException;
12+
use MongoDB\Exception\RuntimeException;
13+
use MongoDB\Exception\UnexpectedValueException;
14+
15+
/**
16+
* Bucket abstracts the GridFS files and chunks collections.
17+
*
18+
* @api
19+
*/
20+
class Bucket
21+
{
22+
private $manager;
23+
private $databaseName;
24+
private $options;
25+
26+
private $filesCollection;
27+
private $chunksCollection;
28+
29+
private $ensuredIndexes = false;
30+
31+
/**
32+
* Constructs a GridFS bucket.
33+
*
34+
* Supported options:
35+
*
36+
* * bucketName (string): The bucket name, which will be used as a prefix
37+
* for the files and chunks collections. Defaults to "fs".
38+
*
39+
* * chunkSizeBytes (integer): The chunk size in bytes. Defaults to
40+
* 261120 (i.e. 255 KiB).
41+
*
42+
* * readPreference (MongoDB\Driver\ReadPreference): Read preference.
43+
*
44+
* * writeConcern (MongoDB\Driver\WriteConcern): Write concern.
45+
*
46+
* @param Manager $manager Manager instance from the driver
47+
* @param string $databaseName Database name
48+
* @param array $options Bucket options
49+
* @throws InvalidArgumentException
50+
*/
51+
public function __construct(Manager $manager, $databaseName, array $options = [])
52+
{
53+
$options += [
54+
'bucketName' => 'fs',
55+
'chunkSizeBytes' => 261120,
56+
];
57+
58+
if (isset($options['bucketName']) && ! is_string($options['bucketName'])) {
59+
throw new InvalidArgumentTypeException('"bucketName" option', $options['bucketName'], 'string');
60+
}
61+
62+
if (isset($options['chunkSizeBytes']) && ! is_integer($options['chunkSizeBytes'])) {
63+
throw new InvalidArgumentTypeException('"chunkSizeBytes" option', $options['chunkSizeBytes'], 'integer');
64+
}
65+
66+
if (isset($options['readPreference']) && ! $options['readPreference'] instanceof ReadPreference) {
67+
throw new InvalidArgumentTypeException('"readPreference" option', $options['readPreference'], 'MongoDB\Driver\ReadPreference');
68+
}
69+
70+
if (isset($options['writeConcern']) && ! $options['writeConcern'] instanceof WriteConcern) {
71+
throw new InvalidArgumentTypeException('"writeConcern" option', $options['writeConcern'], 'MongoDB\Driver\WriteConcern');
72+
}
73+
74+
$this->manager = $manager;
75+
$this->databaseName = (string) $databaseName;
76+
$this->options = $options;
77+
78+
$this->filesCollection = new Collection(
79+
$manager,
80+
sprintf('%s.%s.files', $this->databaseName, $options['bucketName']),
81+
isset($options['writeConcern']) ? $options['writeConcern'] : null,
82+
isset($options['readPreference']) ? $options['readPreference'] : null,
83+
);
84+
85+
$this->chunksCollection = new Collection(
86+
$manager,
87+
sprintf('%s.%s.chunks', $this->databaseName, $options['bucketName']),
88+
isset($options['writeConcern']) ? $options['writeConcern'] : null,
89+
isset($options['readPreference']) ? $options['readPreference'] : null,
90+
);
91+
}
92+
93+
/**
94+
* Opens a Stream for reading the contents of a file specified by ID.
95+
*
96+
* @param ObjectId $id
97+
* @return Stream
98+
*/
99+
public function openDownloadStream(ObjectId $id)
100+
{
101+
102+
}
103+
104+
/**
105+
* Return the chunkSizeBytes option for this Bucket.
106+
*
107+
* @return integer
108+
*/
109+
public function getChunkSizeBytes()
110+
{
111+
return $this->options['chunkSizeBytes'];
112+
}
113+
114+
/**
115+
* Opens a Stream for writing the contents of a file.
116+
*
117+
* @param ObjectId $id
118+
* @return Stream
119+
*/
120+
public function openUploadStream($filename, array $options = [])
121+
{
122+
123+
}
124+
125+
private function ensureIndexes()
126+
{
127+
// Indexes should only be ensured once before the first write operation
128+
if ($this->ensuredIndexes) {
129+
return;
130+
}
131+
132+
if ( ! $this->isFilesCollectionEmpty()) {
133+
return;
134+
}
135+
136+
$this->ensureFilesIndex();
137+
$this->ensureChunksIndex();
138+
139+
$this->ensuredIndexes = true;
140+
}
141+
142+
private function ensureChunksIndex()
143+
{
144+
foreach ($this->chunksCollection->listIndexes() as $index) {
145+
if ($index->isUnique() && $index->getKey() === ['files_id' => 1, 'n' => 1]) {
146+
return;
147+
}
148+
}
149+
150+
$this->chunksCollection->createIndex(['files_id' => 1, 'n' => 1], ['unique' => true]);
151+
}
152+
153+
private function ensureFilesIndex()
154+
{
155+
foreach ($this->filesCollection->listIndexes() as $index) {
156+
if ($index->getKey() === ['filename' => 1, 'uploadDate' => 1]) {
157+
return;
158+
}
159+
}
160+
161+
$this->filesCollection->createIndex(['filename' => 1, 'uploadDate' => 1]);
162+
}
163+
164+
private function isFilesCollectionEmpty()
165+
{
166+
return null === $this->filesCollection->findOne([], [
167+
'readPreference' => new ReadPreference(ReadPreference::RP_PRIMARY),
168+
'projection' => ['_id' => 1],
169+
]);
170+
}
171+
}

‎src/GridFS/StreamWrapper.php‎

Lines changed: 123 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,123 @@
1+
<?php
2+
3+
namespace MongoDB\GridFS;
4+
5+
use MongoDB\Driver\Server;
6+
use MongoDB\Exception\InvalidArgumentException;
7+
use MongoDB\Exception\InvalidArgumentTypeException;
8+
use MongoDB\Exception\RuntimeException;
9+
use MongoDB\Exception\UnexpectedValueException;
10+
11+
/**
12+
* Stream wrapper for reading and writing a GridFS file.
13+
*
14+
* @internal
15+
* @see MongoDB\GridFS\Bucket::openUploadStream()
16+
*/
17+
class StreamWrapper
18+
{
19+
private $bucket;
20+
private $filename;
21+
private $options;
22+
23+
private $at;
24+
private $hashContext;
25+
26+
/**
27+
* Register the GridFS stream wrapper.
28+
*
29+
* @param Manager $manager Manager instance from the driver
30+
* @param string $protocol Protocol to register
31+
*/
32+
public static function register(Manager $manager, $protocol = 'gridfs')
33+
{
34+
if (in_array($protocol, stream_get_wrappers())) {
35+
stream_wrapper_unregister($protocol);
36+
}
37+
38+
// Set the client passed in as the default stream context client
39+
stream_wrapper_register($protocol, get_called_class(), STREAM_IS_URL);
40+
$default = stream_context_get_options(stream_context_get_default());
41+
$default[$protocol]['manager'] = $manager;
42+
stream_context_set_default($default);
43+
}
44+
45+
public function stream_open($path, $mode, $options, &$openedPath)
46+
47+
/**
48+
* Constructs a writable upload stream.
49+
*
50+
* Supported options:
51+
*
52+
* * chunkSizeBytes (integer): The number of bytes per chunk of this file.
53+
* Defaults to the chunkSizeBytes of the Bucket.
54+
*
55+
* * metadata (document): User data for the "metadata" field of the files
56+
* collection document.
57+
*
58+
* The following options are deprecated:
59+
*
60+
* * aliases (string[]): An array of aliases (i.e. filenames). Applications
61+
* wishing to store aliases should add an aliases field to the metadata
62+
* document instead.
63+
*
64+
* * contentType (string): A valid MIME type. Applications wishing to store
65+
* a contentType should add a contentType field to the metadata document
66+
* instead.
67+
*
68+
* @param Bucket $bucket Database name
69+
* @param string $filename Filename
70+
* @param array $options Upload options
71+
* @throws InvalidArgumentException
72+
*/
73+
public function __construct(Bucket $bucket, $filename, array $options = [])
74+
{
75+
$options += [
76+
'chunkSizeBytes' => $bucket->getChunkSizeBytes(),
77+
];
78+
79+
if (isset($options['chunkSizeBytes']) && ! is_integer($options['chunkSizeBytes'])) {
80+
throw new InvalidArgumentTypeException('"chunkSizeBytes" option', $options['chunkSizeBytes'], 'integer');
81+
}
82+
83+
if (isset($options['metadata']) && ! is_array($options['metadata']) && ! is_object($options['metadata'])) {
84+
throw new InvalidArgumentTypeException('"metadata" option', $options['metadata'], 'array or object');
85+
}
86+
87+
if (isset($options['aliases'])) {
88+
if ( ! is_array($options['aliases'])) {
89+
throw new InvalidArgumentTypeException('"aliases" option', $options['aliases'], 'array or object');
90+
}
91+
92+
$expectedIndex = 0;
93+
94+
foreach ($options['aliases'] as $i => $alias) {
95+
if ($i !== $expectedIndex) {
96+
throw new InvalidArgumentException(sprintf('"aliases" option is not a list (unexpected index: "%s")', $i));
97+
}
98+
99+
if ( ! is_string($alias)) {
100+
throw new InvalidArgumentTypeException(sprintf('$options["aliases"][%d]', $i), $alias, 'string');
101+
}
102+
103+
$expectedIndex += 1;
104+
}
105+
}
106+
107+
if (isset($options['contentType']) && ! is_string($options['contentType'])) {
108+
throw new InvalidArgumentTypeException('"contentType" option', $options['contentType'], 'string');
109+
}
110+
111+
$this->bucket = $bucket;
112+
$this->filename = (string) $filename;
113+
$this->options = $options;
114+
$this->hashContext = hash_init('md5');
115+
}
116+
117+
function stream_write($data)
118+
{
119+
hash_update($this->hashContext, $data);
120+
121+
fopen('php://memory', )
122+
}
123+
}

0 commit comments

Comments
(0)

AltStyle によって変換されたページ (->オリジナル) /