Generate.php 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141
  1. <?php
  2. declare(strict_types=1);
  3. /**
  4. * @copyright Copyright (c) 2023 Robin Appelman <robin@icewind.nl>
  5. *
  6. * @license GNU AGPL version 3 or any later version
  7. *
  8. * This program is free software: you can redistribute it and/or modify
  9. * it under the terms of the GNU Affero General Public License as
  10. * published by the Free Software Foundation, either version 3 of the
  11. * License, or (at your option) any later version.
  12. *
  13. * This program is distributed in the hope that it will be useful,
  14. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  15. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  16. * GNU Affero General Public License for more details.
  17. *
  18. * You should have received a copy of the GNU Affero General Public License
  19. * along with this program. If not, see <http://www.gnu.org/licenses/>.
  20. *
  21. */
  22. namespace OC\Core\Command\Preview;
  23. use OCP\Files\Config\IUserMountCache;
  24. use OCP\Files\IRootFolder;
  25. use OCP\Files\Node;
  26. use OCP\Files\File;
  27. use OCP\Files\NotFoundException;
  28. use OCP\IPreview;
  29. use Symfony\Component\Console\Command\Command;
  30. use Symfony\Component\Console\Input\InputArgument;
  31. use Symfony\Component\Console\Input\InputInterface;
  32. use Symfony\Component\Console\Input\InputOption;
  33. use Symfony\Component\Console\Output\OutputInterface;
  34. class Generate extends Command {
  35. private IRootFolder $rootFolder;
  36. private IUserMountCache $userMountCache;
  37. private IPreview $previewManager;
  38. public function __construct(IRootFolder $rootFolder, IUserMountCache $userMountCache, IPreview $previewManager) {
  39. $this->rootFolder = $rootFolder;
  40. $this->userMountCache = $userMountCache;
  41. $this->previewManager = $previewManager;
  42. parent::__construct();
  43. }
  44. protected function configure() {
  45. $this
  46. ->setName('preview:generate')
  47. ->setDescription('generate a preview for a file')
  48. ->addArgument("file", InputArgument::REQUIRED, "path or fileid of the file to generate the preview for")
  49. ->addOption("size", "s", InputOption::VALUE_IS_ARRAY | InputOption::VALUE_REQUIRED, "size to generate the preview for in pixels, defaults to 64x64", ["64x64"])
  50. ->addOption("crop", "c", InputOption::VALUE_NONE, "crop the previews instead of maintaining aspect ratio")
  51. ->addOption("mode", "m", InputOption::VALUE_REQUIRED, "mode for generating uncropped previews, 'cover' or 'fill'", IPreview::MODE_FILL);
  52. }
  53. protected function execute(InputInterface $input, OutputInterface $output): int {
  54. $fileInput = $input->getArgument("file");
  55. $sizes = $input->getOption("size");
  56. $sizes = array_map(function (string $size) use ($output, &$error) {
  57. if (str_contains($size, 'x')) {
  58. $sizeParts = explode('x', $size, 2);
  59. } else {
  60. $sizeParts = [$size, $size];
  61. }
  62. if (!is_numeric($sizeParts[0]) || !is_numeric($sizeParts[1])) {
  63. $output->writeln("<error>Invalid size $size</error>");
  64. return null;
  65. }
  66. return array_map("intval", $sizeParts);
  67. }, $sizes);
  68. if (in_array(null, $sizes)) {
  69. return 1;
  70. }
  71. $mode = $input->getOption("mode");
  72. if ($mode !== IPreview::MODE_FILL && $mode !== IPreview::MODE_COVER) {
  73. $output->writeln("<error>Invalid mode $mode</error>");
  74. return 1;
  75. }
  76. $crop = $input->getOption("crop");
  77. $file = $this->getFile($fileInput);
  78. if (!$file) {
  79. $output->writeln("<error>File $fileInput not found</error>");
  80. return 1;
  81. }
  82. if (!$file instanceof File) {
  83. $output->writeln("<error>Can't generate previews for folders</error>");
  84. return 1;
  85. }
  86. if (!$this->previewManager->isAvailable($file)) {
  87. $output->writeln("<error>No preview generator available for file of type" . $file->getMimetype() . "</error>");
  88. return 1;
  89. }
  90. $specifications = array_map(function (array $sizes) use ($crop, $mode) {
  91. return [
  92. 'width' => $sizes[0],
  93. 'height' => $sizes[1],
  94. 'crop' => $crop,
  95. 'mode' => $mode,
  96. ];
  97. }, $sizes);
  98. $this->previewManager->generatePreviews($file, $specifications);
  99. if (count($specifications) > 1) {
  100. $output->writeln("generated <info>" . count($specifications) . "</info> previews");
  101. } else {
  102. $output->writeln("preview generated");
  103. }
  104. return 0;
  105. }
  106. private function getFile(string $fileInput): ?Node {
  107. if (is_numeric($fileInput)) {
  108. $mounts = $this->userMountCache->getMountsForFileId((int)$fileInput);
  109. if (!$mounts) {
  110. return null;
  111. }
  112. $mount = $mounts[0];
  113. $userFolder = $this->rootFolder->getUserFolder($mount->getUser()->getUID());
  114. $nodes = $userFolder->getById((int)$fileInput);
  115. if (!$nodes) {
  116. return null;
  117. }
  118. return $nodes[0];
  119. } else {
  120. try {
  121. return $this->rootFolder->get($fileInput);
  122. } catch (NotFoundException $e) {
  123. return null;
  124. }
  125. }
  126. }
  127. }