Scan.php 4.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155
  1. <?php
  2. declare(strict_types=1);
  3. /**
  4. * @copyright Copyright (c) 2021 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 OCA\Files_External\Command;
  23. use OC\Files\Cache\Scanner;
  24. use OCA\Files_External\Service\GlobalStoragesService;
  25. use OCP\IUserManager;
  26. use Symfony\Component\Console\Helper\Table;
  27. use Symfony\Component\Console\Input\InputArgument;
  28. use Symfony\Component\Console\Input\InputInterface;
  29. use Symfony\Component\Console\Input\InputOption;
  30. use Symfony\Component\Console\Output\OutputInterface;
  31. class Scan extends StorageAuthBase {
  32. protected float $execTime = 0;
  33. protected int $foldersCounter = 0;
  34. protected int $filesCounter = 0;
  35. public function __construct(
  36. GlobalStoragesService $globalService,
  37. IUserManager $userManager
  38. ) {
  39. parent::__construct($globalService, $userManager);
  40. }
  41. protected function configure(): void {
  42. $this
  43. ->setName('files_external:scan')
  44. ->setDescription('Scan an external storage for changed files')
  45. ->addArgument(
  46. 'mount_id',
  47. InputArgument::REQUIRED,
  48. 'the mount id of the mount to scan'
  49. )->addOption(
  50. 'user',
  51. 'u',
  52. InputOption::VALUE_REQUIRED,
  53. 'The username for the remote mount (required only for some mount configuration that don\'t store credentials)'
  54. )->addOption(
  55. 'password',
  56. 'p',
  57. InputOption::VALUE_REQUIRED,
  58. 'The password for the remote mount (required only for some mount configuration that don\'t store credentials)'
  59. )->addOption(
  60. 'path',
  61. '',
  62. InputOption::VALUE_OPTIONAL,
  63. 'The path in the storage to scan',
  64. ''
  65. );
  66. parent::configure();
  67. }
  68. protected function execute(InputInterface $input, OutputInterface $output): int {
  69. [, $storage] = $this->createStorage($input, $output);
  70. if ($storage === null) {
  71. return 1;
  72. }
  73. $path = $input->getOption('path');
  74. $this->execTime = -microtime(true);
  75. /** @var Scanner $scanner */
  76. $scanner = $storage->getScanner();
  77. $scanner->listen('\OC\Files\Cache\Scanner', 'scanFile', function (string $path) use ($output) {
  78. $output->writeln("\tFile\t<info>$path</info>", OutputInterface::VERBOSITY_VERBOSE);
  79. ++$this->filesCounter;
  80. $this->abortIfInterrupted();
  81. });
  82. $scanner->listen('\OC\Files\Cache\Scanner', 'scanFolder', function (string $path) use ($output) {
  83. $output->writeln("\tFolder\t<info>$path</info>", OutputInterface::VERBOSITY_VERBOSE);
  84. ++$this->foldersCounter;
  85. $this->abortIfInterrupted();
  86. });
  87. $scanner->scan($path);
  88. $this->presentStats($output);
  89. return 0;
  90. }
  91. /**
  92. * @param OutputInterface $output
  93. */
  94. protected function presentStats(OutputInterface $output): void {
  95. // Stop the timer
  96. $this->execTime += microtime(true);
  97. $headers = [
  98. 'Folders', 'Files', 'Elapsed time'
  99. ];
  100. $this->showSummary($headers, [], $output);
  101. }
  102. /**
  103. * Shows a summary of operations
  104. *
  105. * @param string[] $headers
  106. * @param string[] $rows
  107. * @param OutputInterface $output
  108. */
  109. protected function showSummary(array $headers, array $rows, OutputInterface $output): void {
  110. $niceDate = $this->formatExecTime();
  111. if (!$rows) {
  112. $rows = [
  113. $this->foldersCounter,
  114. $this->filesCounter,
  115. $niceDate,
  116. ];
  117. }
  118. $table = new Table($output);
  119. $table
  120. ->setHeaders($headers)
  121. ->setRows([$rows]);
  122. $table->render();
  123. }
  124. /**
  125. * Formats microtime into a human readable format
  126. *
  127. * @return string
  128. */
  129. protected function formatExecTime(): string {
  130. $secs = round($this->execTime);
  131. # convert seconds into HH:MM:SS form
  132. return sprintf('%02d:%02d:%02d', ($secs / 3600), ($secs / 60 % 60), $secs % 60);
  133. }
  134. }