1 | <?php |
||
2 | |||
3 | namespace App\Console\Commands; |
||
4 | |||
5 | use App\Libraries\WatchRecord\InotifyWatchRecord; |
||
6 | use App\Models\Setting; |
||
7 | use App\Repositories\SettingRepository; |
||
8 | use App\Services\FileSynchronizer; |
||
9 | use App\Services\MediaSyncService; |
||
10 | use Exception; |
||
11 | use Illuminate\Console\Command; |
||
12 | use Symfony\Component\Console\Helper\ProgressBar; |
||
13 | |||
14 | class SyncCommand extends Command |
||
15 | { |
||
16 | protected $signature = 'koel:sync |
||
17 | {record? : A single watch record. Consult Wiki for more info.} |
||
18 | {--tags= : The comma-separated tags to sync into the database} |
||
19 | {--force : Force re-syncing even unchanged files}'; |
||
20 | |||
21 | protected $description = 'Sync songs found in configured directory against the database.'; |
||
22 | private $ignored = 0; |
||
23 | private $invalid = 0; |
||
24 | private $synced = 0; |
||
25 | private $mediaSyncService; |
||
26 | private $settingRepository; |
||
27 | |||
28 | /** |
||
29 | * @var ProgressBar |
||
30 | */ |
||
31 | private $progressBar; |
||
32 | |||
33 | 132 | public function __construct(MediaSyncService $mediaSyncService, SettingRepository $settingRepository) |
|
34 | { |
||
35 | 132 | parent::__construct(); |
|
36 | 132 | $this->mediaSyncService = $mediaSyncService; |
|
37 | 132 | $this->settingRepository = $settingRepository; |
|
38 | 132 | } |
|
39 | |||
40 | /** |
||
41 | * @throws Exception |
||
42 | */ |
||
43 | public function handle(): void |
||
44 | { |
||
45 | $this->ensureMediaPath(); |
||
46 | |||
47 | if (!$record = $this->argument('record')) { |
||
48 | $this->syncAll(); |
||
49 | |||
50 | return; |
||
51 | } |
||
52 | |||
53 | $this->syngle($record); |
||
0 ignored issues
–
show
Bug
introduced
by
![]() |
|||
54 | } |
||
55 | |||
56 | /** |
||
57 | * Sync all files in the configured media path. |
||
58 | * |
||
59 | * @throws Exception |
||
60 | */ |
||
61 | protected function syncAll(): void |
||
62 | { |
||
63 | $this->info('Syncing media from '.Setting::get('media_path').PHP_EOL); |
||
64 | |||
65 | // Get the tags to sync. |
||
66 | // Notice that this is only meaningful for existing records. |
||
67 | // New records will have every applicable field sync'ed in. |
||
68 | $tags = $this->option('tags') ? explode(',', $this->option('tags')) : []; |
||
69 | |||
70 | $this->mediaSyncService->sync(null, $tags, $this->option('force'), $this); |
||
71 | |||
72 | $this->output->writeln( |
||
73 | PHP_EOL.PHP_EOL |
||
74 | ."<info>Completed! {$this->synced} new or updated song(s)</info>, " |
||
75 | ."{$this->ignored} unchanged song(s), " |
||
76 | ."and <comment>{$this->invalid} invalid file(s)</comment>." |
||
77 | ); |
||
78 | } |
||
79 | |||
80 | /** |
||
81 | * SYNc a sinGLE file or directory. See my awesome pun? |
||
82 | * |
||
83 | * @param string $record The watch record. |
||
84 | * As of current we only support inotifywait. |
||
85 | * Some examples: |
||
86 | * - "DELETE /var/www/media/gone.mp3" |
||
87 | * - "CLOSE_WRITE,CLOSE /var/www/media/new.mp3" |
||
88 | * - "MOVED_TO /var/www/media/new_dir" |
||
89 | * |
||
90 | * @link http://man7.org/linux/man-pages/man1/inotifywait.1.html |
||
91 | * |
||
92 | * @throws Exception |
||
93 | */ |
||
94 | public function syngle(string $record): void |
||
95 | { |
||
96 | $this->mediaSyncService->syncByWatchRecord(new InotifyWatchRecord($record)); |
||
97 | } |
||
98 | |||
99 | /** |
||
100 | * Log a song's sync status to console. |
||
101 | */ |
||
102 | public function logSyncStatusToConsole(string $path, int $result, ?string $reason = null): void |
||
103 | { |
||
104 | $name = basename($path); |
||
105 | |||
106 | if ($result === FileSynchronizer::SYNC_RESULT_UNMODIFIED) { |
||
107 | $this->ignored++; |
||
108 | } elseif ($result === FileSynchronizer::SYNC_RESULT_BAD_FILE) { |
||
109 | if ($this->option('verbose')) { |
||
110 | $this->error(PHP_EOL."'$name' is not a valid media file: ".$reason); |
||
111 | } |
||
112 | |||
113 | $this->invalid++; |
||
114 | } else { |
||
115 | $this->synced++; |
||
116 | } |
||
117 | } |
||
118 | |||
119 | public function createProgressBar(int $max): void |
||
120 | { |
||
121 | $this->progressBar = $this->getOutput()->createProgressBar($max); |
||
122 | } |
||
123 | |||
124 | public function advanceProgressBar(): void |
||
125 | { |
||
126 | $this->progressBar->advance(); |
||
127 | } |
||
128 | |||
129 | private function ensureMediaPath(): void |
||
130 | { |
||
131 | if (Setting::get('media_path')) { |
||
132 | return; |
||
133 | } |
||
134 | |||
135 | $this->warn("Media path hasn't been configured. Let's set it up."); |
||
136 | |||
137 | while (true) { |
||
138 | $path = $this->ask('Absolute path to your media directory'); |
||
139 | |||
140 | if (is_dir($path) && is_readable($path)) { |
||
141 | Setting::set('media_path', $path); |
||
142 | break; |
||
143 | } |
||
144 | |||
145 | $this->error('The path does not exist or is not readable. Try again.'); |
||
146 | } |
||
147 | } |
||
148 | } |
||
149 |