@@ -55,22 +55,52 @@ class LocalAdapter implements AdapterInterface
5555 */
5656 private $ filePath = null ;
5757
58+ /**
59+ * Should the adapter create a thumbnail for the image?
60+ *
61+ * @var boolean
62+ *
63+ * @since __DEPLOY_VERSION__
64+ */
65+ private $ thumbnails = false ;
66+
67+ /**
68+ * Thumbnail dimensions in pixels, [0] = width, [1] = height
69+ *
70+ * @var array
71+ *
72+ * @since __DEPLOY_VERSION__
73+ */
74+ private $ thumbnailSize = [200 , 200 ];
75+
5876 /**
5977 * The absolute root path in the local file system.
6078 *
61- * @param string $rootPath The root path
62- * @param string $filePath The file path of media folder
79+ * @param string $rootPath The root path
80+ * @param string $filePath The file path of media folder
81+ * @param boolean $thumbnails The thumbnails option
82+ * @param array $thumbnailSize The thumbnail dimensions in pixels
6383 *
6484 * @since 4.0.0
6585 */
66- public function __construct (string $ rootPath , string $ filePath )
86+ public function __construct (string $ rootPath , string $ filePath, bool $ thumbnails = false , array $ thumbnailSize = [ 200 , 200 ] )
6787 {
6888 if (!file_exists ($ rootPath )) {
6989 throw new \InvalidArgumentException (Text::_ ('COM_MEDIA_ERROR_MISSING_DIR ' ));
7090 }
7191
72- $ this ->rootPath = Path::clean (realpath ($ rootPath ), '/ ' );
73- $ this ->filePath = $ filePath ;
92+ $ this ->rootPath = Path::clean (realpath ($ rootPath ), '/ ' );
93+ $ this ->filePath = $ filePath ;
94+ $ this ->thumbnails = $ thumbnails ;
95+ $ this ->thumbnailSize = $ thumbnailSize ;
96+
97+ if ($ this ->thumbnails ) {
98+ $ dir = JPATH_ROOT . '/media/cache/com_media/thumbs/ ' . $ this ->filePath ;
99+
100+ if (!is_dir ($ dir )) {
101+ Folder::create ($ dir );
102+ }
103+ }
74104 }
75105
76106 /**
@@ -221,14 +251,24 @@ public function createFolder(string $name, string $path): string
221251 */
222252 public function createFile (string $ name , string $ path , $ data ): string
223253 {
224- $ name = $ this ->getSafeName ($ name );
225-
254+ $ name = $ this ->getSafeName ($ name );
226255 $ localPath = $ this ->getLocalPath ($ path . '/ ' . $ name );
227256
228257 $ this ->checkContent ($ localPath , $ data );
229258
230259 File::write ($ localPath , $ data );
231260
261+ if ($ this ->thumbnails && MediaHelper::isImage (pathinfo ($ localPath )['basename ' ])) {
262+ $ thumbnailPaths = $ this ->getLocalThumbnailPaths ($ localPath );
263+
264+ if (empty ($ thumbnailPaths )) {
265+ return $ name ;
266+ }
267+
268+ // Create the thumbnail
269+ $ this ->createThumbnail ($ localPath , $ thumbnailPaths ['fs ' ]);
270+ }
271+
232272 return $ name ;
233273 }
234274
@@ -255,6 +295,17 @@ public function updateFile(string $name, string $path, $data)
255295 $ this ->checkContent ($ localPath , $ data );
256296
257297 File::write ($ localPath , $ data );
298+
299+ if ($ this ->thumbnails && MediaHelper::isImage (pathinfo ($ localPath )['basename ' ])) {
300+ $ thumbnailPaths = $ this ->getLocalThumbnailPaths ($ localPath );
301+
302+ if (empty ($ thumbnailPaths ['fs ' ])) {
303+ return ;
304+ }
305+
306+ // Create the thumbnail
307+ $ this ->createThumbnail ($ localPath , $ thumbnailPaths ['fs ' ]);
308+ }
258309 }
259310
260311 /**
@@ -269,20 +320,29 @@ public function updateFile(string $name, string $path, $data)
269320 */
270321 public function delete (string $ path )
271322 {
272- $ localPath = $ this ->getLocalPath ($ path );
323+ $ localPath = $ this ->getLocalPath ($ path );
324+ $ thumbnailPaths = $ this ->getLocalThumbnailPaths ($ localPath );
273325
274326 if (is_file ($ localPath )) {
275327 if (!File::exists ($ localPath )) {
276328 throw new FileNotFoundException ();
277329 }
278330
331+ if ($ this ->thumbnails && !empty ($ thumbnailPaths ['fs ' ]) && is_file ($ thumbnailPaths ['fs ' ])) {
332+ File::delete ($ thumbnailPaths ['fs ' ]);
333+ }
334+
279335 $ success = File::delete ($ localPath );
280336 } else {
281337 if (!Folder::exists ($ localPath )) {
282338 throw new FileNotFoundException ();
283339 }
284340
285341 $ success = Folder::delete ($ localPath );
342+
343+ if ($ this ->thumbnails && !empty ($ thumbnailPaths ['fs ' ]) && is_dir ($ thumbnailPaths ['fs ' ])) {
344+ Folder::delete ($ thumbnailPaths ['fs ' ]);
345+ }
286346 }
287347
288348 if (!$ success ) {
@@ -303,7 +363,7 @@ public function delete(string $path)
303363 * - mime_type: The mime type
304364 * - width: The width, when available
305365 * - height: The height, when available
306- * - thumb_path The thumbnail path of file, when available
366+ * - thumb_path: The thumbnail path of file, when available
307367 *
308368 * @param string $path The folder
309369 *
@@ -351,8 +411,7 @@ private function getPathInformation(string $path): \stdClass
351411 $ obj ->width = $ props ->width ;
352412 $ obj ->height = $ props ->height ;
353413
354- // @todo : Change this path to an actual thumbnail path
355- $ obj ->thumb_path = $ this ->getUrl ($ obj ->path );
414+ $ obj ->thumb_path = $ this ->thumbnails ? $ this ->getThumbnail ($ path ) : $ this ->getUrl ($ obj ->path );
356415 } catch (UnparsableImageException $ e ) {
357416 // Ignore the exception - it's an image that we don't know how to parse right now
358417 }
@@ -689,7 +748,7 @@ private function rglob(string $pattern, int $flags = 0): array
689748 {
690749 $ files = glob ($ pattern , $ flags );
691750
692- foreach (glob (\ dirname ($ pattern ) . '/* ' , GLOB_ONLYDIR | GLOB_NOSORT ) as $ dir ) {
751+ foreach (glob (dirname ($ pattern ) . '/* ' , GLOB_ONLYDIR | GLOB_NOSORT ) as $ dir ) {
693752 $ files = array_merge ($ files , $ this ->rglob ($ dir . '/ ' . $ this ->getFileName ($ pattern ), $ flags ));
694753 }
695754
@@ -763,7 +822,7 @@ private function checkContent(string $localPath, string $mediaContent)
763822 $ helper = new MediaHelper ();
764823
765824 // @todo find a better way to check the input, by not writing the file to the disk
766- $ tmpFile = Path::clean (\ dirname ($ localPath ) . '/ ' . uniqid () . '. ' . File::getExt ($ name ));
825+ $ tmpFile = Path::clean (dirname ($ localPath ) . '/ ' . uniqid () . '. ' . File::getExt ($ name ));
767826
768827 if (!File::write ($ tmpFile , $ mediaContent )) {
769828 throw new \Exception (Text::_ ('JLIB_MEDIA_ERROR_UPLOAD_INPUT ' ), 500 );
@@ -819,4 +878,89 @@ private function getLocalPath(string $path): string
819878 throw new InvalidPathException ($ e ->getMessage ());
820879 }
821880 }
881+
882+ /**
883+ * Returns the local filesystem thumbnail path for the given path.
884+ *
885+ * Throws an InvalidPathException if the path is invalid.
886+ *
887+ * @param string $path The path
888+ *
889+ * @return array
890+ *
891+ * @since __DEPLOY_VERSION__
892+ * @throws InvalidPathException
893+ */
894+ private function getLocalThumbnailPaths (string $ path ): array
895+ {
896+ $ rootPath = str_replace (['\\' , '/ ' ], '/ ' , $ this ->rootPath );
897+ $ path = str_replace (['\\' , '/ ' ], '/ ' , $ path );
898+
899+ try {
900+ $ fs = Path::check (str_replace ($ rootPath , JPATH_ROOT . '/media/cache/com_media/thumbs/ ' . $ this ->filePath , $ path ));
901+ $ url = str_replace ($ rootPath , 'media/cache/com_media/thumbs/ ' . $ this ->filePath , $ path );
902+
903+ return [
904+ 'fs ' => $ fs ,
905+ 'url ' => $ url ,
906+ ];
907+ } catch (\Exception $ e ) {
908+ throw new InvalidPathException ($ e ->getMessage ());
909+ }
910+ }
911+
912+ /**
913+ * Returns the path for the thumbnail of the given image.
914+ * If the thumbnail does not exist, it will be created.
915+ *
916+ * @param string $path The path of the image
917+ *
918+ * @return string
919+ *
920+ * @since __DEPLOY_VERSION__
921+ */
922+ private function getThumbnail (string $ path ): string
923+ {
924+ $ thumbnailPaths = $ this ->getLocalThumbnailPaths ($ path );
925+
926+ if (empty ($ thumbnailPaths ['fs ' ])) {
927+ return $ this ->getUrl ($ path );
928+ }
929+
930+ $ dir = dirname ($ thumbnailPaths ['fs ' ]);
931+
932+ if (!is_dir ($ dir )) {
933+ Folder::create ($ dir );
934+ }
935+
936+ // Create the thumbnail
937+ if (!is_file ($ thumbnailPaths ['fs ' ]) && !$ this ->createThumbnail ($ path , $ thumbnailPaths ['fs ' ])) {
938+ return $ this ->getUrl ($ path );
939+ }
940+
941+ return Uri::root () . $ this ->getEncodedPath ($ thumbnailPaths ['url ' ]);
942+ }
943+
944+ /**
945+ * Create a thumbnail of the given image.
946+ *
947+ * @param string $path The path of the image
948+ * @param string $thumbnailPath The path of the thumbnail
949+ *
950+ * @return boolean
951+ *
952+ * @since __DEPLOY_VERSION__
953+ */
954+ private function createThumbnail (string $ path , string $ thumbnailPath ): bool
955+ {
956+ $ image = new Image ($ path );
957+
958+ try {
959+ $ image ->createThumbnails ([$ this ->thumbnailSize [0 ] . 'x ' . $ this ->thumbnailSize [1 ]], $ image ::SCALE_INSIDE , dirname ($ thumbnailPath ), true );
960+ } catch (\Exception $ e ) {
961+ return false ;
962+ }
963+
964+ return true ;
965+ }
822966}
0 commit comments