mirror of
https://github.com/Poniverse/Pony.fm.git
synced 2024-11-21 20:48:00 +01:00
Merge branch 'master' into laravel-upgrades
This commit is contained in:
commit
081202e7e2
4 changed files with 166 additions and 38 deletions
1
.gitignore
vendored
1
.gitignore
vendored
|
@ -12,3 +12,4 @@ _ide_helper.php
|
||||||
resources/views/emails/html
|
resources/views/emails/html
|
||||||
npm-debug.log
|
npm-debug.log
|
||||||
yarn-error.log
|
yarn-error.log
|
||||||
|
/composer.phar
|
||||||
|
|
|
@ -145,7 +145,9 @@ class UploadTrackCommand extends CommandBase
|
||||||
|
|
||||||
$input = Request::all();
|
$input = Request::all();
|
||||||
$input['track'] = $trackFile;
|
$input['track'] = $trackFile;
|
||||||
if (!$this->_isReplacingTrack) {
|
|
||||||
|
// Prevent the setting of the cover index for validation
|
||||||
|
if (!$this->_isReplacingTrack && isset($coverFile)) {
|
||||||
$input['cover'] = $coverFile;
|
$input['cover'] = $coverFile;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -159,7 +161,7 @@ class UploadTrackCommand extends CommandBase
|
||||||
. 'audio_channels:1,2',
|
. 'audio_channels:1,2',
|
||||||
];
|
];
|
||||||
if (!$this->_isReplacingTrack) {
|
if (!$this->_isReplacingTrack) {
|
||||||
array_push($rules, [
|
array_merge($rules, [
|
||||||
'cover' => 'image|mimes:png,jpeg|min_width:350|min_height:350',
|
'cover' => 'image|mimes:png,jpeg|min_width:350|min_height:350',
|
||||||
'auto_publish' => 'boolean',
|
'auto_publish' => 'boolean',
|
||||||
'title' => 'string',
|
'title' => 'string',
|
||||||
|
@ -198,6 +200,12 @@ class UploadTrackCommand extends CommandBase
|
||||||
$this->_track->source = $this->_customTrackSource ?? $source;
|
$this->_track->source = $this->_customTrackSource ?? $source;
|
||||||
$this->_track->save();
|
$this->_track->save();
|
||||||
|
|
||||||
|
// If the cover was null, and not included, add it back in as null so that
|
||||||
|
// other commands do not encounter a undefined index.
|
||||||
|
if (! isset($input['cover'])) {
|
||||||
|
$input['cover'] = null;
|
||||||
|
}
|
||||||
|
|
||||||
if (!$this->_isReplacingTrack) {
|
if (!$this->_isReplacingTrack) {
|
||||||
// Parse any tags in the uploaded files.
|
// Parse any tags in the uploaded files.
|
||||||
$parseTagsCommand = new ParseTrackTagsCommand($this->_track, $trackFile, $input);
|
$parseTagsCommand = new ParseTrackTagsCommand($this->_track, $trackFile, $input);
|
||||||
|
|
78
app/Console/Commands/RebuildImages.php
Normal file
78
app/Console/Commands/RebuildImages.php
Normal file
|
@ -0,0 +1,78 @@
|
||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* Pony.fm - A community for pony fan music.
|
||||||
|
* Copyright (C) 2017 Isaac Avram
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU Affero General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU Affero General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Affero General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace Poniverse\Ponyfm\Console\Commands;
|
||||||
|
|
||||||
|
use Illuminate\Console\Command;
|
||||||
|
use Poniverse\Ponyfm\Models\Image;
|
||||||
|
use Symfony\Component\HttpFoundation\File\Exception\FileNotFoundException;
|
||||||
|
use Symfony\Component\HttpFoundation\File\File;
|
||||||
|
|
||||||
|
class RebuildImages extends Command
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* The name and signature of the console command.
|
||||||
|
*
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
protected $signature = 'rebuild:images';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The console command description.
|
||||||
|
*
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
protected $description = 'Resizes all images to fit the specifications in Models/Image';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a new command instance.
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function __construct()
|
||||||
|
{
|
||||||
|
parent::__construct();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Execute the console command.
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function handle()
|
||||||
|
{
|
||||||
|
$this->info("Regenerating Images");
|
||||||
|
$progressBar = $this->output->createProgressBar(Image::count());
|
||||||
|
|
||||||
|
Image::chunk(1000, function($images) use ($progressBar) {
|
||||||
|
foreach ($images as $image) {
|
||||||
|
try {
|
||||||
|
$image->buildCovers();
|
||||||
|
} catch (FileNotFoundException $e) {
|
||||||
|
$name = $image->filename;
|
||||||
|
$id = $image->id;
|
||||||
|
|
||||||
|
$this->error("Unable to process image $name (id: $id): ".$e->getMessage());
|
||||||
|
}
|
||||||
|
|
||||||
|
$progressBar->advance();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
|
@ -24,6 +24,8 @@ use External;
|
||||||
use Illuminate\Database\Eloquent\Model;
|
use Illuminate\Database\Eloquent\Model;
|
||||||
use Config;
|
use Config;
|
||||||
use Illuminate\Support\Str;
|
use Illuminate\Support\Str;
|
||||||
|
use Symfony\Component\HttpFoundation\File\Exception\FileNotFoundException;
|
||||||
|
use Symfony\Component\HttpFoundation\File\File;
|
||||||
use Symfony\Component\HttpFoundation\File\UploadedFile;
|
use Symfony\Component\HttpFoundation\File\UploadedFile;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -57,12 +59,14 @@ class Image extends Model
|
||||||
const SMALL = 4;
|
const SMALL = 4;
|
||||||
|
|
||||||
public static $ImageTypes = [
|
public static $ImageTypes = [
|
||||||
self::NORMAL => ['id' => self::NORMAL, 'name' => 'normal', 'width' => 350, 'height' => 350],
|
self::NORMAL => ['id' => self::NORMAL, 'name' => 'normal', 'width' => 350, 'height' => 350, 'geometry' => '350'],
|
||||||
self::ORIGINAL => ['id' => self::ORIGINAL, 'name' => 'original', 'width' => null, 'height' => null],
|
self::ORIGINAL => ['id' => self::ORIGINAL, 'name' => 'original', 'width' => null, 'height' => null, 'geometry' => null],
|
||||||
self::SMALL => ['id' => self::SMALL, 'name' => 'small', 'width' => 100, 'height' => 100],
|
self::SMALL => ['id' => self::SMALL, 'name' => 'small', 'width' => 100, 'height' => 100, 'geometry' => '100x100^'],
|
||||||
self::THUMBNAIL => ['id' => self::THUMBNAIL, 'name' => 'thumbnail', 'width' => 50, 'height' => 50]
|
self::THUMBNAIL => ['id' => self::THUMBNAIL, 'name' => 'thumbnail', 'width' => 50, 'height' => 50, 'geometry' => '50x50^']
|
||||||
];
|
];
|
||||||
|
|
||||||
|
const MIME_JPEG = 'image/jpeg';
|
||||||
|
|
||||||
public static function getImageTypeFromName($name)
|
public static function getImageTypeFromName($name)
|
||||||
{
|
{
|
||||||
foreach (self::$ImageTypes as $cover) {
|
foreach (self::$ImageTypes as $cover) {
|
||||||
|
@ -95,17 +99,7 @@ class Image extends Model
|
||||||
|
|
||||||
if ($image) {
|
if ($image) {
|
||||||
if ($forceReupload) {
|
if ($forceReupload) {
|
||||||
// delete existing versions of the image
|
$image->clearExisting(true);
|
||||||
$filenames = scandir($image->getDirectory());
|
|
||||||
$imagePrefix = $image->id.'_';
|
|
||||||
|
|
||||||
$filenames = array_filter($filenames, function (string $filename) use ($imagePrefix) {
|
|
||||||
return Str::startsWith($filename, $imagePrefix);
|
|
||||||
});
|
|
||||||
|
|
||||||
foreach ($filenames as $filename) {
|
|
||||||
unlink($image->getDirectory().'/'.$filename);
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
return $image;
|
return $image;
|
||||||
}
|
}
|
||||||
|
@ -124,27 +118,7 @@ class Image extends Model
|
||||||
|
|
||||||
$image->ensureDirectoryExists();
|
$image->ensureDirectoryExists();
|
||||||
foreach (self::$ImageTypes as $coverType) {
|
foreach (self::$ImageTypes as $coverType) {
|
||||||
if ($coverType['id'] === self::ORIGINAL && $image->mime === 'image/jpeg') {
|
self::processFile($file, $image->getFile($coverType['id']), $coverType);
|
||||||
$command = 'cp "'.$file->getPathname().'" '.$image->getFile($coverType['id']);
|
|
||||||
} else {
|
|
||||||
// ImageMagick options reference: http://www.imagemagick.org/script/command-line-options.php
|
|
||||||
$command = 'convert 2>&1 "'.$file->getPathname().'" -background white -alpha remove -alpha off -strip';
|
|
||||||
|
|
||||||
if ($image->mime === 'image/jpeg') {
|
|
||||||
$command .= ' -quality 100 -format jpeg';
|
|
||||||
} else {
|
|
||||||
$command .= ' -quality 95 -format png';
|
|
||||||
}
|
|
||||||
|
|
||||||
if (isset($coverType['width']) && isset($coverType['height'])) {
|
|
||||||
$command .= " -thumbnail ${coverType['width']}x${coverType['height']}^ -gravity center -extent ${coverType['width']}x${coverType['height']}";
|
|
||||||
}
|
|
||||||
|
|
||||||
$command .= ' "'.$image->getFile($coverType['id']).'"';
|
|
||||||
}
|
|
||||||
|
|
||||||
External::execute($command);
|
|
||||||
chmod($image->getFile($coverType['id']), 0644);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return $image;
|
return $image;
|
||||||
|
@ -154,6 +128,37 @@ class Image extends Model
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Converts the image into the specified cover type to the specified path.
|
||||||
|
*
|
||||||
|
* @param File $image The image file to be processed
|
||||||
|
* @param string $path The path to save the processed image file
|
||||||
|
* @param array $coverType The type to process the image to
|
||||||
|
*/
|
||||||
|
private static function processFile(File $image, string $path, $coverType) {
|
||||||
|
if ($coverType['id'] === self::ORIGINAL && $image->getMimeType() === self::MIME_JPEG) {
|
||||||
|
$command = 'cp "'.$image->getPathname().'" '.$path;
|
||||||
|
} else {
|
||||||
|
// ImageMagick options reference: http://www.imagemagick.org/script/command-line-options.php
|
||||||
|
$command = 'convert 2>&1 "'.$image->getPathname().'" -background white -alpha remove -alpha off -strip';
|
||||||
|
|
||||||
|
if ($image->getMimeType() === self::MIME_JPEG) {
|
||||||
|
$command .= ' -quality 100 -format jpeg';
|
||||||
|
} else {
|
||||||
|
$command .= ' -quality 95 -format png';
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isset($coverType['geometry'])) {
|
||||||
|
$command .= " -gravity center -thumbnail ${coverType['geometry']} -extent ${coverType['geometry']}";
|
||||||
|
}
|
||||||
|
|
||||||
|
$command .= ' "'.$path.'"';
|
||||||
|
}
|
||||||
|
|
||||||
|
External::execute($command);
|
||||||
|
chmod($path, 0644);
|
||||||
|
}
|
||||||
|
|
||||||
protected $table = 'images';
|
protected $table = 'images';
|
||||||
|
|
||||||
public function getUrl($type = self::NORMAL)
|
public function getUrl($type = self::NORMAL)
|
||||||
|
@ -191,4 +196,40 @@ class Image extends Model
|
||||||
mkdir($destination, 0777, true);
|
mkdir($destination, 0777, true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Deletes any generated files if they exist
|
||||||
|
* @param bool $includeOriginal Set to true if the original image should be deleted as well.
|
||||||
|
*/
|
||||||
|
public function clearExisting(bool $includeOriginal = false) {
|
||||||
|
$files = scandir($this->getDirectory());
|
||||||
|
$filePrefix = $this->id.'_';
|
||||||
|
$originalName = $filePrefix.Image::$ImageTypes[Image::ORIGINAL]['name'];
|
||||||
|
|
||||||
|
$files = array_filter($files, function($file) use ($originalName, $includeOriginal, $filePrefix) {
|
||||||
|
if (Str::startsWith($file,$originalName) && !$includeOriginal) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return (Str::startsWith($file, $filePrefix));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
foreach ($files as $file) {
|
||||||
|
unlink($this->getDirectory().'/'.$file);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Builds the cover images for the image, overwriting if needed.
|
||||||
|
*
|
||||||
|
* @throws FileNotFoundException If the original file cannot be found.
|
||||||
|
*/
|
||||||
|
public function buildCovers() {
|
||||||
|
$originalFile = new File($this->getFile(self::ORIGINAL));
|
||||||
|
|
||||||
|
foreach (self::$ImageTypes as $imageType) {
|
||||||
|
self::processFile($originalFile, $this->getFile($imageType['id']), $imageType);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue