Skip to content

Commit

Permalink
Enable using wildcards on occ music:playlist-import
Browse files Browse the repository at this point in the history
Wildcard characters * and ? are now supported when defining the name(s)
of playlists files to import. These characters are *not* interpreted as
wildcards when they are part of the directory name (on Linux, these
characters are allowed as ordinary characters in any file/folder name).

refs #832
  • Loading branch information
paulijar committed Nov 25, 2021
1 parent 938ba85 commit 51f739d
Showing 1 changed file with 54 additions and 1 deletion.
55 changes: 54 additions & 1 deletion lib/Command/PlaylistImport.php
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,11 @@
use OCA\Music\Db\Playlist;
use OCA\Music\Utility\PlaylistFileService;

use OCP\Files\File;
use OCP\Files\Folder;
use OCP\Files\IRootFolder;
use OCP\Files\Node;
use OCP\Files\NotFoundException;

use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Input\InputOption;
Expand Down Expand Up @@ -52,7 +55,7 @@ protected function doConfigure() : void {
'file',
null,
InputOption::VALUE_REQUIRED | InputOption::VALUE_IS_ARRAY,
'path of the playlist file, relative to the user home folder'
'path of the playlist file, relative to the user home folder; * and ? are treated as wildcards within the file name but not on the directory name'
)
->addOption(
'overwrite',
Expand Down Expand Up @@ -97,6 +100,7 @@ private function executeForUser(string $userId, array $files, bool $overwrite, b
$output->writeln("Importing playlist(s) for <info>$userId</info>...");

$userFolder = $this->rootFolder->getUserFolder($userId);
$files = self::resolveWildcards($files, $userFolder, $output);

foreach ($files as $filePath) {
$name = \pathinfo($filePath, PATHINFO_FILENAME);
Expand Down Expand Up @@ -129,4 +133,53 @@ private function importPlaylist(string $filePath, Playlist $playlist, string $us
$output->writeln(" The file <error>$filePath</error> is not a supported playlist file");
}
}

/**
* @param string[] $paths
* @return string[]
*/
private static function resolveWildcards(array $paths, Folder $userFolder, OutputInterface $output) : array {
$result = [];

foreach ($paths as $path) {
list('basename' => $basename, 'dirname' => $dirname) = \pathinfo($path);
if (\strpos($basename, '?') === false && \strpos($basename, '*') === false) {
// no wildcards, take the path as such
$result[] = $path;
} else {
try {
$dir = $userFolder->get($dirname);
} catch (NotFoundException $e) {
$dir = null;
}
if (!($dir instanceof Folder)) {
$output->writeln(" Invalid directory path <error>$dirname</error>");
} else {
$matches = [];
foreach ($dir->getDirectoryListing() as $node) {
if ($node instanceof File && self::fileMatchesPattern($node, $basename)) {
$matches[] = $userFolder->getRelativePath($node->getPath());
}
}
if (\count($matches) == 0) {
$output->writeln(" The path pattern <error>$path</error> matched no files");
} else {
$result = \array_merge($result, $matches);
}
}
}
}

return $result;
}

private static function fileMatchesPattern(File $file, string $pattern) : bool {
// convert the pattern to regex
$pattern = \preg_quote($pattern); // escape regex meta characters
$pattern = \str_replace('\*', '.*', $pattern); // convert * to its regex equivaleant
$pattern = \str_replace('\?', '.', $pattern); // convert ? to its regex equivaleant
$pattern = "/^$pattern$/"; // the pattern should match the name from begin to end

return (\preg_match($pattern, $file->getName()) === 1);
}
}

0 comments on commit 51f739d

Please sign in to comment.