Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
28 changes: 28 additions & 0 deletions src/Filesystem/Filesystem.php
Original file line number Diff line number Diff line change
Expand Up @@ -231,6 +231,34 @@ public function isLocalDisk(\Illuminate\Filesystem\FilesystemAdapter $disk): boo
return ($disk->getAdapter() instanceof \League\Flysystem\Local\LocalFilesystemAdapter);
}

/**
* Apply a unique index to a filename from provided list i.e.
* winter.txt, [winter_1.txt, winter_2.txt] -> winter_3.txt
* winter.txt, [winter_1.txt, winter_3.txt] -> winter_4.txt
Comment on lines +236 to +237
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
* winter.txt, [winter_1.txt, winter_2.txt] -> winter_3.txt
* winter.txt, [winter_1.txt, winter_3.txt] -> winter_4.txt
* winter.txt, [winter.txt] -> winter_1.txt
* winter.txt, [winter.txt, winter_1.txt, winter_2.txt] -> winter_3.txt
* winter.txt, [winter.txt, winter_1.txt, winter_3.txt] -> winter_4.txt
* winter.txt, [winter_1.txt, winter_3.txt] -> winter.txt

@damsfx it should probably allow the input to be returned unmodified if it doesn't exist within the array.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@LukeTowers If the entry doesn't exist in the array, it must be returned with another index anyway, right?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@damsfx I'm making the suggestion that if it doesn't exist in the array it should be returned unmodified. The method is intended to give you a unique filename provided the input of a desired filename and a list of already existing options. If the filename provided is already unique, then there's no need to modify it.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@LukeTowers So in a such case, the same filename is needed in the array of references to get the next incremented name.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The suggested change above should list all the cases that I think the method should need to handle, I've already updated the tests so it should just require a minor change in the method itself.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@LukeTowers Your modifications in tests goes to a failure for me.

// File already unique, return original
'winter.cms' => ['winter.cms', ['winter_1.cms']],

FAILED !
The function return wintert_2.cms in that case.

What I don't understand is why you want to return the unmodified value if it's unique.
In any case, we should return the incremented value! 🤯

(new Filesystem())->unique('winter.cms', ['test.cms']);   // winter_1.cms
(new Filesystem())->unique('winter.cms', []);             // winter_1.cms

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@damsfx The tests are failing because the method doesn't currently have the logic to allow the name to be returned unmodified. The method claims to return a unique filename given the input of a desired filename and a list of existing filenames; why does it have to always return an incremented value if the desired filename isn't present?

Copy link
Contributor Author

@damsfx damsfx Feb 17, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@LukeTowers Apply a unique index to a filename from provided list ...
Maybe we should then say Apply a unique index to a filename from provided list ONLY if it is found in the list ... or change the name of the method which is perhaps the source of the confusion.

In any case, the current function respects the logic of the original one:
68bb7ac

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@LukeTowers Do we continue with this PR in draft?

*/
public function unique(string $str, array $list, string $separator = '_', int $starting = 1, int $step = 1): string
{
$indexes = [];

$info = pathinfo($str);

if (empty($info['filename']) || empty($info['extension'])) {
throw new \InvalidArgumentException('$str must be a file name');
}

foreach ($list as $item) {
if (!preg_match('/' . $info['filename'] . $separator . '(\d*)\.' . $info['extension'] . '/', $item, $matches)) {
continue;
}

$indexes[] = (int) $matches[1];
}

return empty($indexes)
? $info['filename'] . $separator . $starting . '.' . $info['extension']
: $info['filename'] . $separator . (max($indexes) + $step) . '.' . $info['extension'];
}

/**
* Finds the path of a given class.
*
Expand Down
1 change: 1 addition & 0 deletions src/Support/Facades/File.php
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@
* @method static bool fileNameMatch(string $fileName, string $pattern)
* @method static bool copyBetweenDisks(string|FilesystemAdapter $sourceDisk, string|FilesystemAdapter $destinationDisk, string $filePath, ?string $targetPath = null)
* @method static bool moveBetweenDisks(string|FilesystemAdapter $sourceDisk, string|FilesystemAdapter $destinationDisk, string $filePath, ?string $targetPath = null)
* @method static string unique(string $str, array $list, string $separator = '_', int $starting = 1, int $step = 1)
*
* @see \Winter\Storm\Filesystem\Filesystem
*/
Expand Down
21 changes: 21 additions & 0 deletions tests/Filesystem/FilesystemTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,27 @@
$this->filesystem = new Filesystem();
}

public function testUnique()
{
$cases = [
// File exists, make it unique
'winter_1.cms' => ['winter.cms', ['winter.cms', 'test_5']],

// File already unique, return original
'winter.cms' => ['winter.cms', ['winter_1.cms']],

// Last index available is incremented
'winter_4.cms' => ['winter.cms', ['winter_1.cms', 'test_5', 'winter_3.cms']],
'winter_98.cms' => ['winter.cms', ['winter_97.cms', 'test_5', 'winter_1.cms']],

// Separator as space
'winter 1.cms' => ['winter.cms', ['winter_1.cms', 'test_5', 'winter_3.cms'], ' '],
];
foreach ($cases as $output => $config) {
$this->assertSame($output, $this->filesystem->unique(...$config));

Check failure on line 31 in tests/Filesystem/FilesystemTest.php

View workflow job for this annotation

GitHub Actions / ubuntu-latest / PHP 8.3

Failed asserting that two strings are identical.

Check failure on line 31 in tests/Filesystem/FilesystemTest.php

View workflow job for this annotation

GitHub Actions / windows-latest / PHP 8.3

Failed asserting that two strings are identical.

Check failure on line 31 in tests/Filesystem/FilesystemTest.php

View workflow job for this annotation

GitHub Actions / windows-latest / PHP 8.3

Failed asserting that two strings are identical.

Check failure on line 31 in tests/Filesystem/FilesystemTest.php

View workflow job for this annotation

GitHub Actions / ubuntu-latest / PHP 8.3

Failed asserting that two strings are identical.

Check failure on line 31 in tests/Filesystem/FilesystemTest.php

View workflow job for this annotation

GitHub Actions / ubuntu-latest / PHP 8.3

Failed asserting that two strings are identical.

Check failure on line 31 in tests/Filesystem/FilesystemTest.php

View workflow job for this annotation

GitHub Actions / windows-latest / PHP 8.3

Failed asserting that two strings are identical.
}
}

/**
* @dataProvider providePathsForIsAbsolutePath
* @see Symfony\Component\Filesystem\Tests\FilesystemTest::testIsAbsolutePath
Expand Down
Loading