Da sich viel per Message bei mir gemeldet habe, kann ich hier ein einfaches CLI Plugin bzw. das wesentliche Skript davon zur Verfügung stellen. Wenn es geholfen habt, bitte verifiziert, ob Euer Problem auch aufgrund dieser High Resolution Thumbnails (mit “@2x.jpg” Endung) entstanden ist. Wenn ja sollten wir ein Bug bei Shopwaresupport eröffnen.
Das ganze Plugin hier sollte helfen diese unrefenzierten High Resolution Thumbnails zu identifizieren und löschen. Wem es geholfen hat kann sich gerne bei mir bedanken oder eine Paypal donation hinterlassen.
Benützung - Achtung, auf eigene Gefahr !
- Löscht zuerst die unrefenzierten Media Dateien über die bereits vorhandenen Möglichkeiten im Backend, entweder über das Menü “Inhalte > Medienverwaltung > Papierkorb > löschen” oder besser über die Console auf der Kommandozeilenumgebung “php console sw:media:cleanup” und “php console sw:thumbnail:cleanup”
- prüft ob der Schritt 1 Euer Problem schon gelöst hat z.B. genügend Speicherplatz wieder frei wurde
- Macht ein Backup der DB und der Media Dateien, checkt wieviel Speicherplatz momentan in Benützung ist. Prüft ob verhältnismässig zuviele High Resolution Plugins immer noch auf dem Filesystem besteht (mit “@2x.jpg” Endung)
- Installiert das Plugin
- ruft über die console den neuen Befehl auf “php console megloff:media:cleanup” – dies löscht die unrefenzierten HD Thumbnails, beachtet das dies lange dauern könnte und je nach der Menge Einträge in der DB viel Speicher benötigt. Eventuell muss dabei die PHP.ini kurzfristig angepasst werden
Datei “Shopware/Plugins/Local/Core/ExtendedConsole/Bootstrap.php”
class Shopware_Plugins_Core_ExtendedConsole_Bootstrap extends Shopware_Components_Plugin_Bootstrap
{
/**
* @return bool
*/
public function install()
{
$this->subscribeEvents();
return true;
}
/**
* Registers all necessary events and hooks.
*/
private function subscribeEvents()
{
$this->subscribeEvent(
'Shopware_Console_Add_Command',
'onAddConsoleCommand'
);
}
/**
* @param Enlight_Event_EventArgs $args
*/
public function onEnlightControllerFrontStartDispatch(Enlight_Event_EventArgs $args)
{ }
// Just register one single command
public function onAddConsoleCommand(Enlight_Event_EventArgs $args)
{
require_once __DIR__. '/Commands/MediaCleanupCommand.php';
return new \Shopware\Commands\MediaCleanupCommand();
}
}
Datei “Shopware/Plugins/Local/Core/ExtendedConsole/Commands/MediaCleanupCommand.php”
namespace Shopware\Commands;
use Shopware\Components\Model\ModelManager;
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 Symfony\Component\Filesystem\Filesystem;
class MediaCleanupCommand extends ShopwareCommand
{
/**
* @var \Shopware\Bundle\MediaBundle\MediaService $mediaService
*/
private $mediaService;
/**
* {@inheritdoc}
*/
protected function configure()
{
$this
->setName('megloff:media:cleanup')
->setDescription('cleans up unused media files from filesystem')
->addOption('delete', false, InputOption::VALUE_NONE, "Delete unused media files.");
$this->mediaService = Shopware()->Container()->get('shopware_media.media_service');
}
/**
* @return \Shopware\Bundle\MediaBundle\MediaService
*/
protected function getMediaservice() {
return $this->mediaService;
}
/**
* {@inheritdoc}
*/
protected function execute(InputInterface $input, OutputInterface $output)
{
$output->writeln('');
$albums = $this->getAlbums();
$medias = $this->getRegisteredMediaPaths($albums);
$output->writeln('number of registered media in DB found: ' . count($medias));
$missing_medias = array();
foreach ($medias as $media) {
if(!$this->getMediaservice()->has($media)) {
$missing_medias[] = $media;
}
}
if(count($missing_medias)) {
$output->writeln('number of missing media files in DB found: ' . count($missing_medias));
}
$thumbnails = $this->getThumbnailPaths($albums);
$output->writeln('number of registered thumbnails files found: ' . count($thumbnails));
$files = $this->listFiles("media");
$output->writeln('number of files in media folder found: ' . count($files));
$files = array_diff($files,$medias,$thumbnails);
$output->writeln('number of unused files: ' . count($files));
if ($output->getVerbosity() >= OutputInterface::VERBOSITY_VERBOSE) {
foreach($files as $file) {
$output->writeln("found unused file: " .$file);
}
}
if (count($files)) {
if ($input->getOption('delete')) {
if ($input->isInteractive()) {
$dialog = $this->getHelper('dialog');
if (!$dialog->askConfirmation($output, 'Are you sure you want to delete these files? [y/N] ', false)) {
return;
}
}
$fs = new Filesystem();
$baseDir = Shopware()->DocPath();
foreach($files as $file) {
$fs->remove($file);
$output->writeln("deleted file " .$file);
}
}
}
$output->writeln('');
}
private function getAlbums() {
/**
* @var \Shopware\Components\Model\ModelManager $em
*/
$em = $this->container->get('models');
$builder = $em->createQueryBuilder();
$builder->select(array('album', 'settings', 'media'))
->from('Shopware\Models\Media\Album', 'album')
->leftJoin('album.settings', 'settings')
->leftJoin('album.media', 'media');
$result = $builder->getQuery()->getResult(\Doctrine\ORM\AbstractQuery::HYDRATE_ARRAY);
return $result;
}
/**
* Returns all thumbnails paths
* @return array
*/
private function getRegisteredMediaPaths($albums) {
$result = array();
foreach ($albums as $album) {
// $output->writeln("Processing album {$album['name']} (ID: {$album['id']})");
foreach ($album['media'] as $media) {
$path = Shopware()->oldPath() . $media['path'];
$result[] = $this->getMediaService()->encode($path);
}
}
return $result;
}
private function getThumbnailPaths($albums) {
$result = array();
foreach ($albums as $album) {
$sizes = $album['settings']['thumbnailSize'];
if(!empty($sizes)) {
foreach ($album['media'] as $media) {
$paths = $this->getMediaThumbnailPaths($media, explode(';', $sizes));
foreach ($paths as $path) {
if ($this->getMediaService()->has($path)) {
$path = $this->getMediaService()->encode($path);
}
}
}
}
}
return $result;
}
/**
* Returns all thumbnails paths according to the given media object
*
* @param $media
* @param $sizes
* @return array
*/
private function getMediaThumbnailPaths($media, $sizes)
{
$sizes = array_merge($sizes, array('140x140'));
$sizes = array_unique($sizes);
$thumbnails = array();
//iterate thumbnail sizes
foreach ($sizes as $size) {
if (strpos($size, 'x') === false) {
$size = $size . 'x' . $size;
}
$thumbnailDir = Shopware()->DocPath('media_' . strtolower($media['type'])) . 'thumbnail' . DIRECTORY_SEPARATOR;
$path = $thumbnailDir . $this->removeSpecialCharacters($media['name']) . '_' . $size;
if (DIRECTORY_SEPARATOR !== '/') {
$path = str_replace(DIRECTORY_SEPARATOR, '/', $path);
}
$thumbnails[] = $path . '.jpg';
$thumbnails[] = $path . '@2x.jpg';
if ($media['extension'] !== 'jpg') {
$thumbnails[] = $path . '.' . $media['extension'];
$thumbnails[] = $path . '@2x.' . $media['extension'];
}
}
return $thumbnails;
}
/**
* Removes special characters from a filename
*
* @param $name
* @return string
*/
private function removeSpecialCharacters($name)
{
$name = iconv('utf-8', 'ascii//translit', $name);
$name = preg_replace('#[^A-z0-9\-_]#', '-', $name);
$name = preg_replace('#-{2,}#', '-', $name);
$name = trim($name, '-');
return mb_substr($name, 0, 180);
}
private function listFiles($dir, &$results = array()){
$files = scandir($dir);
foreach($files as $key => $value){
if ($value == ".htaccess") continue;
if ($value == ".gitkeep") continue;
$path = $dir."/".$value;
if(!is_dir($path)) {
$results[] = $path;
} else if($value != "." && $value != "..") {
$this->listFiles($path, $results);
}
}
return $results;
}
}