@@ -170,6 +170,87 @@ public function delete($file, $force = false)
170170 if (($ force || $ this ->getConfig ('delete ' ))) $ this ->filesystem ()->delete ($ file );
171171 }
172172
173+ /**
174+ * Delete all thumbnails for a given file path.
175+ *
176+ * @param string $filePath The original file path (e.g., "images/photo.jpg")
177+ * @return array List of deleted thumbnail paths
178+ */
179+ public function deleteThumbnails (string $ filePath ): array
180+ {
181+ $ thumbProfileName = $ this ->getConfig ('thumbnails ' );
182+ if (empty ($ thumbProfileName ) || $ thumbProfileName === false ) {
183+ return [];
184+ }
185+
186+ $ thumbProfile = $ this ->thumbProfile ();
187+ $ deletedPaths = [];
188+ $ profileDir = $ this ->name ;
189+
190+ try {
191+ $ contents = $ thumbProfile ->listContents ($ profileDir , true );
192+
193+ foreach ($ contents as $ item ) {
194+ if ($ item ['type ' ] !== 'file ' ) {
195+ continue ;
196+ }
197+
198+ if ($ this ->matchesThumbnailPath ($ item ['path ' ], $ filePath , $ profileDir )) {
199+ try {
200+ $ thumbProfile ->delete ($ item ['path ' ], true );
201+ $ deletedPaths [] = $ item ['path ' ];
202+ } catch (\Exception $ e ) {
203+ // Continue with other deletions
204+ }
205+ }
206+ }
207+ } catch (\Exception $ e ) {
208+ // listContents might fail on some adapters (e.g., External)
209+ }
210+
211+ return $ deletedPaths ;
212+ }
213+
214+ /**
215+ * Check if a thumbnail path corresponds to the given original file path.
216+ *
217+ * @param string $thumbnailPath Full thumbnail path
218+ * @param string $originalPath Original file path
219+ * @param string $profileName Profile name
220+ * @return bool
221+ */
222+ protected function matchesThumbnailPath (string $ thumbnailPath , string $ originalPath , string $ profileName ): bool
223+ {
224+ $ thumbnailPath = str_replace (['/ ' , '\\' ], DS , $ thumbnailPath );
225+ $ originalPath = str_replace (['/ ' , '\\' ], DS , $ originalPath );
226+
227+ if (strpos ($ thumbnailPath , $ profileName . DS ) !== 0 ) {
228+ return false ;
229+ }
230+
231+ // Direct suffix match
232+ if (substr ($ thumbnailPath , -strlen ($ originalPath )) === $ originalPath ) {
233+ return true ;
234+ }
235+
236+ // WebP conversion match
237+ $ thumbExt = strtolower (pathinfo ($ thumbnailPath , PATHINFO_EXTENSION ));
238+ $ origExt = strtolower (pathinfo ($ originalPath , PATHINFO_EXTENSION ));
239+
240+ if ($ thumbExt === 'webp ' && in_array ($ origExt , ['jpg ' , 'jpeg ' , 'png ' ])) {
241+ $ originalWithoutExt = pathinfo ($ originalPath , PATHINFO_DIRNAME ) . DS .
242+ pathinfo ($ originalPath , PATHINFO_FILENAME );
243+ $ thumbWithoutExt = pathinfo ($ thumbnailPath , PATHINFO_DIRNAME ) . DS .
244+ pathinfo ($ thumbnailPath , PATHINFO_FILENAME );
245+
246+ if (substr ($ thumbWithoutExt , -strlen ($ originalWithoutExt )) === $ originalWithoutExt ) {
247+ return true ;
248+ }
249+ }
250+
251+ return false ;
252+ }
253+
173254 public function readAndDelete ($ path )
174255 {
175256 return $ this ->filesystem ()->readAndDelete ($ path );
0 commit comments