mirror of
https://github.com/koel/koel
synced 2024-09-20 06:11:53 +00:00
Use cover/folder.jpg/png as album cover if found (fixes #380)
This commit is contained in:
parent
cb7cebe151
commit
7556ba79e0
4 changed files with 85 additions and 10 deletions
|
@ -123,12 +123,36 @@ class Album extends Model
|
|||
public function writeCoverFile($binaryData, $extension)
|
||||
{
|
||||
$extension = trim(strtolower($extension), '. ');
|
||||
$fileName = uniqid('', true).".$extension";
|
||||
$coverPath = app()->publicPath().'/public/img/covers/'.$fileName;
|
||||
$destPath = $this->generateRandomCoverPath($extension);
|
||||
file_put_contents($destPath, $binaryData);
|
||||
|
||||
file_put_contents($coverPath, $binaryData);
|
||||
$this->update(['cover' => basename($destPath)]);
|
||||
}
|
||||
|
||||
$this->update(['cover' => $fileName]);
|
||||
/**
|
||||
* Copy a cover file from an existing image on the system.
|
||||
*
|
||||
* @param string $srcPath The original image's full path.
|
||||
*/
|
||||
public function copyCoverFile($srcPath)
|
||||
{
|
||||
$extension = pathinfo($srcPath, PATHINFO_EXTENSION);
|
||||
$destPath = $this->generateRandomCoverPath($extension);
|
||||
copy($srcPath, $destPath);
|
||||
|
||||
$this->update(['cover' => basename($destPath)]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate a random path for the cover image.
|
||||
*
|
||||
* @param string $extension The extension of the cover (without dot)
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
private function generateRandomCoverPath($extension)
|
||||
{
|
||||
return app()->publicPath().'/public/img/covers/'.uniqid('', true).".$extension";
|
||||
}
|
||||
|
||||
public function setCoverAttribute($value)
|
||||
|
|
|
@ -2,7 +2,9 @@
|
|||
|
||||
namespace App\Models;
|
||||
|
||||
use Cache;
|
||||
use Exception;
|
||||
use Symfony\Component\Finder\Finder;
|
||||
use getID3;
|
||||
use getid3_lib;
|
||||
use Illuminate\Support\Facades\Log;
|
||||
|
@ -99,7 +101,7 @@ class File
|
|||
'comments.track_number',
|
||||
];
|
||||
|
||||
for ($i = 0; $i < count($trackIndices) && $track === 0; $i++) {
|
||||
for ($i = 0; $i < count($trackIndices) && $track === 0; ++$i) {
|
||||
$track = array_get($info, $trackIndices[$i], [0])[0];
|
||||
}
|
||||
|
||||
|
@ -227,11 +229,18 @@ class File
|
|||
$album = Album::get($artist, $info['album'], $isCompilation);
|
||||
}
|
||||
|
||||
if (!empty($info['cover']) && !$album->has_cover) {
|
||||
try {
|
||||
$album->generateCover($info['cover']);
|
||||
} catch (Exception $e) {
|
||||
Log::error($e);
|
||||
if (!$album->has_cover) {
|
||||
// If the album has no cover, we try to get the cover image from existing tag data
|
||||
if (!empty($info['cover'])) {
|
||||
try {
|
||||
$album->generateCover($info['cover']);
|
||||
} catch (Exception $e) {
|
||||
Log::error($e);
|
||||
}
|
||||
}
|
||||
// or, if there's a cover image under the same directory, use it.
|
||||
elseif ($cover = $this->getCoverFileUnderSameDirectory()) {
|
||||
$album->copyCoverFile($cover);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -303,6 +312,42 @@ class File
|
|||
return $this->path;
|
||||
}
|
||||
|
||||
/**
|
||||
* Issue #380.
|
||||
* Some albums have its own cover image under the same directory as cover|folder.jpg/png.
|
||||
* We'll check if such a cover file is found, and use it if positive.
|
||||
*
|
||||
* @return string|false The cover file's full path, or false if none found
|
||||
*/
|
||||
private function getCoverFileUnderSameDirectory()
|
||||
{
|
||||
// As directory scanning can be expensive, we cache and reuse the result.
|
||||
$cacheKey = md5($this->path.'_cover');
|
||||
|
||||
if (!is_null($cover = Cache::get($cacheKey))) {
|
||||
return $cover;
|
||||
}
|
||||
|
||||
$matches = array_keys(iterator_to_array(
|
||||
Finder::create()
|
||||
->depth(0)
|
||||
->ignoreUnreadableDirs()
|
||||
->files()
|
||||
->name('/(cov|fold)er\.(jpe?g|png)$/i')
|
||||
->in(dirname($this->path))
|
||||
));
|
||||
|
||||
$cover = $matches ? $matches[0] : false;
|
||||
// Even if a file is found, make sure it's a real image.
|
||||
if ($cover && exif_imagetype($cover) === false) {
|
||||
$cover = false;
|
||||
}
|
||||
|
||||
Cache::put($cacheKey, $cover, 24 * 60);
|
||||
|
||||
return $cover;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a unique hash from a file path.
|
||||
*
|
||||
|
|
|
@ -32,6 +32,11 @@ class MediaTest extends TestCase
|
|||
// Ogg files and audio files in subdirectories should be recognized
|
||||
$this->seeInDatabase('songs', ['path' => $this->mediaPath.'/subdir/back-in-black.ogg']);
|
||||
|
||||
// GitHub issue #380. folder.png should be copied and used as the cover for files
|
||||
// under subdir/
|
||||
$song = Song::wherePath($this->mediaPath.'/subdir/back-in-black.ogg')->first();
|
||||
$this->assertNotNull($song->album->cover);
|
||||
|
||||
// File search shouldn't be case-sensitive.
|
||||
$this->seeInDatabase('songs', ['path' => $this->mediaPath.'/subdir/no-name.MP3']);
|
||||
|
||||
|
@ -58,6 +63,7 @@ class MediaTest extends TestCase
|
|||
$this->assertTrue($song->album->is_compilation);
|
||||
$this->assertEquals(Artist::VARIOUS_ID, $song->album->artist_id);
|
||||
|
||||
|
||||
$currentCover = $album->cover;
|
||||
|
||||
$song = Song::orderBy('id', 'desc')->first();
|
||||
|
|
BIN
tests/songs/subdir/folder.png
Normal file
BIN
tests/songs/subdir/folder.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 7.2 KiB |
Loading…
Reference in a new issue