19
19
class Bucket
20
20
{
21
21
private $ databaseName ;
22
+ private $ collectionsWrapper ;
22
23
private $ options ;
23
- private $ filesCollection ;
24
- private $ chunksCollection ;
25
- private $ ensuredIndexes = false ;
26
24
/**
27
25
* Constructs a GridFS bucket.
28
26
*
@@ -50,122 +48,124 @@ public function __construct(Manager $manager, $databaseName, array $options = []
50
48
'bucketName ' => 'fs ' ,
51
49
'chunkSizeBytes ' => 261120 ,
52
50
];
53
- if (isset ($ options ['bucketName ' ]) && ! is_string ($ options ['bucketName ' ])) {
54
- throw new InvalidArgumentTypeException ('"bucketName" option ' , $ options ['bucketName ' ], 'string ' );
55
- }
56
- if (isset ($ options ['chunkSizeBytes ' ]) && ! is_integer ($ options ['chunkSizeBytes ' ])) {
57
- throw new InvalidArgumentTypeException ('"chunkSizeBytes" option ' , $ options ['chunkSizeBytes ' ], 'integer ' );
58
- }
59
- if (isset ($ options ['readPreference ' ])) {
60
- if (! $ options ['readPreference ' ] instanceof ReadPreference) {
61
- throw new InvalidArgumentTypeException ('"readPreference" option ' , $ options ['readPreference ' ], 'MongoDB\Driver\ReadPreference ' );
62
- } else {
63
- $ collectionOptions ['readPreference ' ] = $ options ['readPreference ' ];
64
- }
65
- }
66
- if (isset ($ options ['writeConcern ' ])) {
67
- if (! $ options ['writeConcern ' ] instanceof WriteConcern) {
68
- throw new InvalidArgumentTypeException ('"writeConcern" option ' , $ options ['writeConcern ' ], 'MongoDB\Driver\WriteConcern ' );
69
- } else {
70
- $ collectionOptions ['writeConcern ' ] = $ options ['writeConcern ' ];
71
- }
72
- }
73
51
$ this ->databaseName = (string ) $ databaseName ;
74
52
$ this ->options = $ options ;
75
-
76
- $ this ->filesCollection = new Collection (
77
- $ manager ,
78
- sprintf ('%s.%s.files ' , $ this ->databaseName , $ options ['bucketName ' ]),
79
- $ collectionOptions
80
- );
81
- $ this ->chunksCollection = new Collection (
82
- $ manager ,
83
- sprintf ('%s.%s.chunks ' , $ this ->databaseName , $ options ['bucketName ' ]),
84
- $ collectionOptions
85
- );
53
+ $ this ->collectionsWrapper = new GridFSCollectionsWrapper ($ manager , $ databaseName , $ options );
86
54
}
55
+
87
56
/**
88
- * Return the chunkSizeBytes option for this Bucket .
57
+ * Opens a Stream for writing the contents of a file .
89
58
*
90
- * @return integer
59
+ * @param string $filename file to upload
60
+ * @param array $options Stream Options
61
+ * @return Stream uploadStream
91
62
*/
92
- public function getChunkSizeBytes ()
93
- {
94
- return $ this ->options ['chunkSizeBytes ' ];
95
- }
96
-
97
- public function getDatabaseName ()
63
+ public function openUploadStream ($ filename , array $ options = [])
98
64
{
99
- return $ this ->databaseName ;
65
+ $ options += ['chunkSizeBytes ' => $ this ->options ['chunkSizeBytes ' ]];
66
+ $ streamOptions = [
67
+ 'collectionsWrapper ' => $ this ->collectionsWrapper ,
68
+ 'uploadOptions ' => $ options
69
+ ];
70
+ $ context = stream_context_create (['gridfs ' => $ streamOptions ]);
71
+ return fopen (sprintf ('gridfs://%s/%s ' , $ this ->databaseName , $ filename ), 'w ' , false , $ context );
100
72
}
101
- public function getFilesCollection ()
102
- {
103
- return $ this ->filesCollection ;
104
- }
105
-
106
- public function getChunksCollection ()
107
- {
108
- return $ this ->chunksCollection ;
109
- }
110
- public function getBucketName ()
73
+ /**
74
+ * Upload a file to this bucket by specifying the source stream file
75
+ *
76
+ * @param String $filename Filename To Insert
77
+ * @param Stream $source Source Stream
78
+ * @param array $options Stream Options
79
+ * @return ObjectId
80
+ */
81
+ public function uploadFromStream ($ filename , $ source , array $ options = [])
111
82
{
112
- return $ this ->options ['bucketName ' ];
83
+ $ options ['chunkSizeBytes ' ] = $ this ->options ['chunkSizeBytes ' ];
84
+ $ gridFsStream = new GridFsUpload ($ this ->collectionsWrapper , $ filename , $ options );
85
+ return $ gridFsStream ->uploadFromStream ($ source );
113
86
}
114
- public function getReadConcern ()
87
+ /**
88
+ * Opens a Stream for reading the contents of a file specified by ID.
89
+ *
90
+ * @param ObjectId $id
91
+ * @return Stream
92
+ */
93
+ public function openDownloadStream (\MongoDB \BSON \ObjectId $ id )
115
94
{
116
- if ( isset ( $ this -> options [ ' readPreference ' ])) {
117
- return $ this ->options [ ' readPreference ' ];
118
- } else {
119
- return null ;
120
- }
95
+ $ options = [
96
+ ' collectionsWrapper ' => $ this ->collectionsWrapper
97
+ ];
98
+ $ context = stream_context_create ([ ' gridfs ' => $ options ]) ;
99
+ return fopen ( sprintf ( ' gridfs://%s/%s ' , $ this -> databaseName , $ id ), ' r ' , false , $ context );
121
100
}
122
- public function getWriteConcern ()
101
+ /**
102
+ * Downloads the contents of the stored file specified by id and writes
103
+ * the contents to the destination Stream.
104
+ * @param ObjectId $id GridFS File Id
105
+ * @param Stream $destination Destination Stream
106
+ */
107
+ public function downloadToStream (\MongoDB \BSON \ObjectId $ id , $ destination )
123
108
{
124
- if (isset ($ this ->options ['writeConcern ' ])) {
125
- return $ this ->options ['writeConcern ' ];
126
- } else {
127
- return null ;
128
- }
109
+ $ gridFsStream = new GridFsDownload ($ this ->collectionsWrapper , $ id );
110
+ $ gridFsStream ->downloadToStream ($ destination );
129
111
}
130
-
131
- private function ensureIndexes ()
112
+ /**
113
+ * Delete a file from the GridFS bucket. If the file collection entry is not found, still attempts to delete orphaned chunks
114
+ *
115
+ * @param ObjectId $id file id
116
+ * @throws GridFSFileNotFoundException
117
+ */
118
+ public function delete (\MongoDB \BSON \ObjectId $ id )
132
119
{
133
- if ($ this ->ensuredIndexes ) {
134
- return ;
135
- }
136
- if ( ! $ this ->isFilesCollectionEmpty ()) {
137
- return ;
120
+ $ file = $ this ->collectionsWrapper ->getFilesCollection ()->findOne (['_id ' => $ id ]);
121
+ $ this ->collectionsWrapper ->getChunksCollection ()->deleteMany (['files_id ' => $ id ]);
122
+ if (is_null ($ file )) {
123
+ throw new \MongoDB \Exception \GridFSFileNotFoundException ($ id , $ this ->collectionsWrapper ->getFilesCollection ()->getNameSpace ());
138
124
}
139
- $ this ->ensureFilesIndex ();
140
- $ this ->ensureChunksIndex ();
141
- $ this ->ensuredIndexes = true ;
125
+
126
+ $ this ->collectionsWrapper ->getFilesCollection ()->deleteOne (['_id ' => $ id ]);
142
127
}
143
- private function ensureChunksIndex ()
128
+ /**
129
+ * Open a stream to download a file from the GridFS bucket. Searches for the file by the specified name then returns a stream to the specified file
130
+ * @param string $filename name of the file to download
131
+ * @param int $revision the revision of the file to download
132
+ * @throws GridFSFileNotFoundException
133
+ */
134
+ public function openDownloadStreamByName ($ filename , $ revision = -1 )
144
135
{
145
- foreach ( $ this ->chunksCollection -> listIndexes () as $ index ) {
146
- if ( $ index -> isUnique () && $ index -> getKey () === ['files_id ' => 1 , ' n ' => 1 ]) {
147
- return ;
148
- }
149
- }
150
- $ this ->chunksCollection -> createIndex ([ ' files_id ' => 1 , 'n ' => 1 ], [ ' unique ' => true ] );
136
+ $ file = $ this ->bucket -> findFileRevision ( $ filename , $ revision );
137
+ $ options = ['bucket ' => $ this -> bucket ,
138
+ ' file ' => $ file
139
+ ];
140
+ $ context = stream_context_create ([ ' gridfs ' => $ options ]);
141
+ return fopen ( sprintf ( ' gridfs://%s/%s ' , $ this ->bucket -> getDatabaseName (), $ filename ) , 'r ' , false , $ context );
151
142
}
152
- private function ensureFilesIndex ()
143
+ /**
144
+ * Download a file from the GridFS bucket by name. Searches for the file by the specified name then loads data into the stream
145
+ *
146
+ * @param string $filename name of the file to download
147
+ * @param int $revision the revision of the file to download
148
+ * @throws GridFSFileNotFoundException
149
+ */
150
+ public function downloadToStreamByName ($ filename , $ destination , $ revision =-1 )
153
151
{
154
- foreach ($ this ->filesCollection ->listIndexes () as $ index ) {
155
- if ($ index ->getKey () === ['filename ' => 1 , 'uploadDate ' => 1 ]) {
156
- return ;
157
- }
158
- }
159
- $ this ->filesCollection ->createIndex (['filename ' => 1 , 'uploadDate ' => 1 ]);
152
+ $ file = $ this ->findFileRevision ($ filename , $ revision );
153
+ $ gridFsStream = new GridFsDownload ($ this ->collectionsWrapper , null , $ file );
154
+ $ gridFsStream ->downloadToStream ($ destination );
160
155
}
161
- private function isFilesCollectionEmpty ()
156
+ /**
157
+ * Find files from the GridFS bucket files collection.
158
+ *
159
+ * @param array $filter filter to find by
160
+ * @param array $options options to
161
+ */
162
+ public function find ($ filter , array $ options =[])
162
163
{
163
- return null === $ this ->filesCollection ->findOne ([], [
164
- 'readPreference ' => new ReadPreference (ReadPreference::RP_PRIMARY ),
165
- 'projection ' => ['_id ' => 1 ],
166
- ]);
164
+ return $ this ->collectionsWrapper ->getFilesCollection ()->find ($ filter , $ options );
167
165
}
168
- public function findFileRevision ($ filename , $ revision )
166
+
167
+
168
+ private function findFileRevision ($ filename , $ revision )
169
169
{
170
170
if ($ revision < 0 ) {
171
171
$ skip = abs ($ revision ) -1 ;
@@ -174,10 +174,15 @@ public function findFileRevision($filename, $revision)
174
174
$ skip = $ revision ;
175
175
$ sortOrder = 1 ;
176
176
}
177
- $ file = $ this ->filesCollection ->findOne (["filename " => $ filename ], ["sort " => ["uploadDate " => $ sortOrder ], "limit " =>1 , "skip " => $ skip ]);
177
+ $ filesCollection = $ this ->collectionsWrapper ->getFilesCollection ();
178
+ $ file = $ filesCollection ->findOne (["filename " => $ filename ], ["sort " => ["uploadDate " => $ sortOrder ], "limit " =>1 , "skip " => $ skip ]);
178
179
if (is_null ($ file )) {
179
- throw new \MongoDB \Exception \GridFSFileNotFoundException ($ filename , $ this -> getBucketName (), $ this -> getDatabaseName ()); ;
180
+ throw new \MongoDB \Exception \GridFSFileNotFoundException ($ filename , $ filesCollection -> getNameSpace ()) ;
180
181
}
181
182
return $ file ;
182
183
}
184
+ public function getCollectionsWrapper ()
185
+ {
186
+ return $ this ->collectionsWrapper ;
187
+ }
183
188
}
0 commit comments