Skip to content

Commit

Permalink
Add occ command playlist-export
Browse files Browse the repository at this point in the history
The command may be used to export one, several, or all playlists of a
user or multiple users to a file. By default, the playlists are exported
to the user home directory but another directory may be given with an
optional argument.

refs owncloud#832
  • Loading branch information
paulijar committed Oct 28, 2021
1 parent 7e18699 commit a72eaf7
Show file tree
Hide file tree
Showing 3 changed files with 162 additions and 0 deletions.
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,8 @@
## [Unreleased]
### Added
- `occ` command `playlist-export`
[#832](https://github.com/owncloud/music/issues/832)

### Changed
- Ampache: A few more actions now support pagination with offset and limit: `artist_albums`, `artist_songs`, `album_songs`, `search_songs`
- Subsonic: Added support to `getArtistInfo` to identify the artist using a track, an album, or a folder ID
Expand Down
7 changes: 7 additions & 0 deletions appinfo/register_command.php
Original file line number Diff line number Diff line change
Expand Up @@ -53,3 +53,10 @@
$c->query('GroupManager'),
$c->query('PodcastService')
));
$application->add(new OCA\Music\Command\PlaylistExport(
$c->query('UserManager'),
$c->query('GroupManager'),
$c->query('RootFolder'),
$c->query('PlaylistBusinessLayer'),
$c->query('PlaylistFileService')
));
151 changes: 151 additions & 0 deletions lib/Command/PlaylistExport.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,151 @@
<?php declare(strict_types=1);

/**
* ownCloud - Music app
*
* This file is licensed under the Affero General Public License version 3 or
* later. See the COPYING file.
*
* @author Pauli Järvinen <pauli.jarvinen@gmail.com>
* @copyright Pauli Järvinen 2021
*/

namespace OCA\Music\Command;

use OCA\Music\AppFramework\BusinessLayer\BusinessLayerException;
use OCA\Music\BusinessLayer\PlaylistBusinessLayer;
use OCA\Music\Db\Playlist;
use OCA\Music\Utility\PlaylistFileService;

use OCP\Files\Folder;
use OCP\Files\IRootFolder;

use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Input\InputOption;
use Symfony\Component\Console\Output\OutputInterface;

class PlaylistExport extends BaseCommand {
/** @var IRootFolder */
private $rootFolder;
/** @var PlaylistBusinessLayer */
private $businessLayer;
/** @var PlaylistFileService */
private $playlistFileService;

public function __construct(
\OCP\IUserManager $userManager,
\OCP\IGroupManager $groupManager,
IRootFolder $rootFolder,
PlaylistBusinessLayer $playlistBusinessLayer,
PlaylistFileService $playlistFileService) {
$this->rootFolder = $rootFolder;
$this->businessLayer = $playlistBusinessLayer;
$this->playlistFileService = $playlistFileService;
parent::__construct($userManager, $groupManager);
}

protected function doConfigure() : void {
$this
->setName('music:playlist-export')
->setDescription('export user playlist(s) to file(s)')
->addOption(
'list-id',
null,
InputOption::VALUE_REQUIRED | InputOption::VALUE_IS_ARRAY,
'ID of the playlist to export'
)
->addOption(
'list-name',
null,
InputOption::VALUE_REQUIRED | InputOption::VALUE_IS_ARRAY,
'name of the playlist to export'
)
->addOption(
'all-lists',
null,
InputOption::VALUE_NONE,
'export all playlists of the user'
)
->addOption(
'dir',
null,
InputOption::VALUE_REQUIRED,
'target directory, relative to the user home folder (the dir must exist)',
''
)
->addOption(
'overwrite',
null,
InputOption::VALUE_NONE,
'overwrite the target file if it already exists'
)
;
}

protected function doExecute(InputInterface $input, OutputInterface $output, array $users) : void {
$ids = $input->getOption('list-id');
$names = $input->getOption('list-name');
$allLists = (bool)$input->getOption('all-lists');
$dir = $input->getOption('dir');
$overwrite = (bool)$input->getOption('overwrite');

if (empty($ids) && empty($names) && !$allLists) {
throw new \InvalidArgumentException('At least one of the arguments <error>list-id</error>, ' .
'<error>list-name</error>, <error>all-lists</error> must be given');
}
elseif ($allLists && (!empty($ids) || !empty($names))) {
throw new \InvalidArgumentException('Argument <error>all-lists</error> should not be used together with ' .
'<error>list-id</error> nor <error>list-name</error>');
}

if ($input->getOption('all')) {
$this->userManager->callForAllUsers(function($user) use ($output, $ids, $names, $allLists, $dir, $overwrite) {
$this->executeForUser($user->getUID(), $ids, $names, $allLists, $dir, $overwrite, $output);
});
} else {
foreach ($users as $userId) {
$this->executeForUser($userId, $ids, $names, $allLists, $dir, $overwrite, $output);
}
}
}

private function executeForUser(string $userId, array $ids, array $names, bool $allLists,
string $dir, bool $overwrite, OutputInterface $output) : void {
$output->writeln("Exporting playlist(s) of <info>$userId</info>...");

if ($allLists) {
$lists = $this->businessLayer->findAll($userId);
}
else {
$lists = $this->businessLayer->findById($ids, $userId);

foreach ($names as $name) {
$listsOfName = $this->businessLayer->findAllByName($name, $userId);
if (\count($listsOfName) === 0) {
$output->writeln(" User <info>$userId</info> has no playlist with name <error>$name</error>");
} else {
$lists = \array_merge($lists, $listsOfName);
}
}
}

$userFolder = $this->rootFolder->getUserFolder($userId);
foreach ($lists as $playlist) {
$this->exportPlaylist($playlist, $userId, $userFolder, $dir, $overwrite, $output);
}
}

private function exportPlaylist(Playlist $playlist, string $userId, Folder $userFolder, string $dir, bool $overwrite, OutputInterface $output) : void {
try {
$id = $playlist->getId();
$filePath = $this->playlistFileService->exportToFile($id, $userId, $userFolder, $dir, $overwrite ? 'overwrite' : 'abort');
$output->writeln(" The playlist <info>$id</info> was exported to <info>$filePath</info>");
} catch (BusinessLayerException $ex) {
$output->writeln(" User <info>$userId</info> has no playlist with id <error>$id</error>");
} catch (\OCP\Files\NotFoundException $ex) {
$output->writeln(" Invalid folder path <error>$dir</error>");
} catch (\RuntimeException $ex) {
$output->writeln(" Playlist file with the name <error>{$playlist->getName()}</error> already exists, pass the argument <info>--overwrite</info> to overwrite it");
}
}
}

0 comments on commit a72eaf7

Please sign in to comment.