Skip to content

Instantly share code, notes, and snippets.

@peterjaap
Created May 1, 2020 12:39
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save peterjaap/5bb95ea634b4e87a9e91d342b2769f25 to your computer and use it in GitHub Desktop.
Save peterjaap/5bb95ea634b4e87a9e91d342b2769f25 to your computer and use it in GitHub Desktop.
PNG Image optimizer example console command - Virtual Magento Meetup 30-04-2020
<?php declare(strict_types=1);
namespace VirtualMeetup\ImageOptimization\Console\Command;
use Graze\ParallelProcess\Event\RunEvent;
use Graze\ParallelProcess\PriorityPool;
use Graze\ParallelProcess\RunInterface;
use Magento\Framework\Filesystem\DirectoryList;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Helper\ProgressBar;
use Symfony\Component\Console\Helper\Table;
use Symfony\Component\Console\Input\InputArgument;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Input\InputOption;
use Symfony\Component\Console\Output\OutputInterface;
use Magento\Framework\Filesystem\Driver\File;
use Symfony\Component\Process\Process;
class Optimize extends Command
{
/**
* @var File
*/
public $file;
/**
* @var DirectoryList
*/
public $dir;
/**
* @var ProgressBar
*/
protected $progressBar;
/**
* @var Table
*/
protected $table;
public function __construct(File $file, DirectoryList $dir, string $name = null)
{
parent::__construct($name);
$this->file = $file;
$this->dir = $dir;
}
/**
* {@inheritdoc}
*/
protected function execute(
InputInterface $input,
OutputInterface $output
) {
$target = $input->getArgument('target');
$format = $input->getOption('format');
$headers = ['File', 'New size', 'Reduction'];
if ($this->file->isDirectory($target)) {
$pngs = $this->getListOfImages($target, 'png');
$pngs = array_slice($pngs, 0, 50); // test with 50 items, remove later
$section = $output->section();
$this->table = new Table($section);
$this->table->setHeaders($headers);
$this->table->render();
$this->progressBar = new ProgressBar($output, count($pngs));
$this->progressBar->start();
$pool = new PriorityPool();
$pool->setMaxSimultaneous(10);
foreach ($pngs as $png) {
$process = new Process(['php','bin/magento','img:opt',$png,'--format=json']);
$pool->add($process);
}
array_map(function ($process) {
/** @var $process RunInterface */
$process->addListener(RunEvent::SUCCESSFUL, function (RunEvent $event) {
$data = json_decode($event->getRun()->getLastMessage(), true);
$this->table->appendRow($data);
$this->progressBar->advance();
});
}, $pool->getAll());
$pool->run();
}
if ($this->file->isFile($target)) {
// @TODO: actually call pngquant to optimize the image and retrieve reduction stat
$data = ['file' => basename($target), 'size' => mt_rand(100,400), 'reduction' => mt_rand(10,90) . '%'];
if ($format === 'json') {
$output->write(json_encode($data));
} else {
$table = new Table($output);
$table->setHeaders($headers);
$table->addRow($data);
$table->render();
}
}
}
private function getListOfImages(string $dir, string $extension)
{
$files = $this->file->readDirectoryRecursively($dir);
return array_filter($files, function ($png) use ($extension) {
return strtolower(pathinfo($png)['extension'] ?? '') === $extension;
});
}
protected function configure()
{
$this->setName('images:optimize');
$this->setDescription('Optimize PNG images');
$this->setDefinition([
new InputArgument('target', InputArgument::REQUIRED, 'Target file or directory to optimize'),
new InputOption('format', 'f', InputOption::VALUE_OPTIONAL, 'Format to output in', 'table'),
]);
parent::configure();
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment