Passed
Push — master ( 3e245e...ef140d )
by Phan
07:34
created

app/Console/Commands/SyncCommand.php (2 issues)

Labels
Severity
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
It seems like $record can also be of type string[]; however, parameter $record of App\Console\Commands\SyncCommand::syngle() does only seem to accept string, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

53
        $this->syngle(/** @scrutinizer ignore-type */ $record);
Loading history...
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);
0 ignored issues
show
$this->option('force') of type string is incompatible with the type boolean expected by parameter $force of App\Services\MediaSyncService::sync(). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

70
        $this->mediaSyncService->sync(null, $tags, /** @scrutinizer ignore-type */ $this->option('force'), $this);
Loading history...
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