55use DateTimeImmutable ;
66use Doctrine \DBAL \Connection ;
77use Doctrine \DBAL \ParameterType ;
8+ use Doctrine \DBAL \Platforms \SQLServerPlatform ;
89use Doctrine \DBAL \Types \Types ;
910use League \Flysystem \Config ;
1011use League \Flysystem \DirectoryAttributes ;
@@ -78,23 +79,23 @@ public function fileExists(string $path): bool
7879
7980 public function directoryExists (string $ path ): bool
8081 {
81- return $ this ->exists ($ this ->prefixer ->prefixPath ($ path ), self ::TYPE_DIR );
82+ return $ this ->exists ($ this ->prefixer ->prefixDirectoryPath ($ path ), self ::TYPE_DIR );
8283 }
8384
8485 private function exists (string $ prefixedPath , string $ type ): bool
8586 {
8687 return (bool ) $ this ->connection ->executeQuery (<<<SQL
87- SELECT EXISTS (
88+ SELECT CASE WHEN EXISTS (
8889 SELECT
8990 1
9091 FROM {$ this ->table }
9192 WHERE
9293 path = :path AND
9394 type = :type
94- )
95+ ) THEN 1 ELSE 0 END
9596SQL ,
9697 [
97- 'path ' => $ prefixedPath ,
98+ 'path ' => rtrim ( $ prefixedPath, '\\ / ' ) ,
9899 'type ' => $ type ,
99100 ],
100101 [
@@ -116,9 +117,6 @@ public function write(string $path, string $contents, Config $config): void
116117 $ this ->writeStream ($ path , $ resource , $ config );
117118 }
118119
119- /**
120- * {@inheritDoc}
121- */
122120 public function writeStream (string $ path , $ contents , Config $ config ): void
123121 {
124122 try {
@@ -130,31 +128,31 @@ public function writeStream(string $path, $contents, Config $config): void
130128 * UPDATE if file exists
131129 * INSERT if not
132130 */
131+ $ pathPrefixed = $ this ->prefixer ->prefixPath ($ path );
133132 if ($ this ->fileExists ($ path )) {
134- $ path = $ this ->prefixer ->prefixPath ($ path );
135133 $ this ->connection ->update ($ this ->table ,
136134 [
137135 'contents ' => $ contents ,
138136 'timestamp ' => $ config ->get ('timestamp ' , time ()),
139137 'visibility ' => $ config ->get (Config::OPTION_VISIBILITY , Visibility::PUBLIC ),
140138 ],
141139 [
142- 'path ' => $ path ,
140+ 'path ' => $ pathPrefixed ,
143141 ],
144142 [
145143 'contents ' => Types::BINARY ,
146144 'timestamp ' => Types::INTEGER ,
147- ]);
145+ ]
146+ );
148147 } else {
149- $ path = $ this ->prefixer ->prefixPath ($ path );
150148 /* @var int|string $timestamp */
151149 $ this ->connection ->insert ($ this ->table , [
152- 'path ' => $ path ,
150+ 'path ' => $ pathPrefixed ,
153151 'type ' => self ::TYPE_FILE ,
154152 'timestamp ' => $ config ->get ('timestamp ' , time ()),
155- 'level ' => $ this ->directoryLevel ($ path ),
153+ 'level ' => $ this ->directoryLevel ($ pathPrefixed ),
156154 'contents ' => $ contents ,
157- 'mimetype ' => $ this ->mimeTypeDetector ->detectMimeType ($ path , $ contents ),
155+ 'mimetype ' => $ this ->mimeTypeDetector ->detectMimeType ($ pathPrefixed , $ contents ),
158156 'visibility ' => $ config ->get (Config::OPTION_VISIBILITY , Visibility::PUBLIC ),
159157 ], [
160158 'path ' => ParameterType::STRING ,
@@ -167,16 +165,23 @@ public function writeStream(string $path, $contents, Config $config): void
167165 ]);
168166 }
169167
170- $ this ->connection ->executeStatement (<<<SQL
168+ if ($ this ->connection ->getDatabasePlatform () instanceof SQLServerPlatform) {
169+ $ lengthFnName = 'LEN ' ;
170+ } else {
171+ $ lengthFnName = 'LENGTH ' ;
172+ }
173+
174+ $ this ->connection ->executeStatement (
175+ <<<SQL
171176UPDATE
172177 {$ this ->table }
173178SET
174- size = LENGTH (contents)
179+ size = { $ lengthFnName } (contents)
175180WHERE
176181 path = :path
177182SQL ,
178183 [
179- 'path ' => $ path ,
184+ 'path ' => $ pathPrefixed ,
180185 ],
181186 [
182187 'path ' => ParameterType::STRING ,
@@ -210,9 +215,6 @@ public function read(string $path): string
210215 }
211216 }
212217
213- /**
214- * {@inheritDoc}
215- */
216218 public function readStream (string $ path ): mixed
217219 {
218220 try {
@@ -254,7 +256,7 @@ public function delete(string $path): void
254256 ->delete (
255257 $ this ->table ,
256258 [
257- 'path ' => $ path ,
259+ 'path ' => $ this -> prefixer -> prefixPath ( $ path) ,
258260 'type ' => self ::TYPE_FILE ,
259261 ],
260262 );
@@ -402,7 +404,8 @@ public function fileSize(string $path): FileAttributes
402404
403405 public function listContents (string $ path , bool $ deep ): iterable
404406 {
405- $ path = $ this ->prefixer ->prefixPath ($ path );
407+ $ prefixedPath = $ this ->prefixer ->prefixPath ($ path );
408+ $ fixedPathForQuery = rtrim ($ prefixedPath , '\\/ ' );
406409
407410 try {
408411 $ queryBuilder = $ this ->connection ->createQueryBuilder ()
@@ -415,25 +418,39 @@ public function listContents(string $path, bool $deep): iterable
415418 $ queryBuilder
416419 ->andWhere (
417420 $ expressionBuilder ->or (
418- $ expressionBuilder ->eq ('path ' , $ queryBuilder ->createNamedParameter ($ path )),
419- $ expressionBuilder ->like ('path ' , $ queryBuilder ->createNamedParameter ($ path .'/% ' ))
421+ $ expressionBuilder ->eq ('path ' , $ queryBuilder ->createNamedParameter ($ fixedPathForQuery )),
422+ $ expressionBuilder ->like ('path ' , $ queryBuilder ->createNamedParameter ($ fixedPathForQuery .'/% ' ))
420423 )
421424 );
422425 if ($ deep ) {
423426 $ queryBuilder ->andWhere (
424- 'level >= ' .$ queryBuilder ->createNamedParameter ($ this ->directoryLevel ($ path ) + 1 ,
427+ 'level >= ' .$ queryBuilder ->createNamedParameter ($ this ->directoryLevel ($ fixedPathForQuery ) + 1 ,
425428 ParameterType::INTEGER ),
426429 );
427430 } else {
428431 $ queryBuilder ->andWhere (
429- 'level = ' .$ queryBuilder ->createNamedParameter ($ this ->directoryLevel ($ path ) + 1 ,
432+ 'level = ' .$ queryBuilder ->createNamedParameter ($ this ->directoryLevel ($ fixedPathForQuery ) + 1 ,
430433 ParameterType::INTEGER ),
431434 );
432435 }
433- } else {
436+ } elseif (!empty ($ prefixedPath )) {
437+ $ expressionBuilder = $ this ->connection ->createExpressionBuilder ();
438+
439+ $ queryBuilder
440+ ->andWhere (
441+ $ expressionBuilder ->or (
442+ $ expressionBuilder ->eq ('path ' , $ queryBuilder ->createNamedParameter ($ fixedPathForQuery )),
443+ $ expressionBuilder ->like ('path ' , $ queryBuilder ->createNamedParameter ($ fixedPathForQuery .'/% ' ))
444+ )
445+ );
434446 if (!$ deep ) {
435- $ queryBuilder ->andWhere ('level = 0 ' );
447+ $ queryBuilder ->andWhere ('level = 1 ' );
448+ } else {
449+ // exclude prefix directory
450+ $ queryBuilder ->andWhere ('level != 0 ' );
436451 }
452+ } elseif (!$ deep ) {
453+ $ queryBuilder ->andWhere ('level = 0 ' );
437454 }
438455 $ queryBuilder ->orderBy ('path ' , 'ASC ' );
439456
0 commit comments