View source
<?php
namespace Drupal\minifyjs;
use Drupal\Core\File\FileSystem;
use Drupal\Core\File\FileSystemInterface;
use Drupal\Core\Path\PathMatcher;
use Drupal\Core\ProxyClass\File\MimeType\MimeTypeGuesser;
use Drupal\file\Entity\File;
use Drupal\file\FileUsage\DatabaseFileUsageBackend;
use Patchwork\JSqueeze;
class MinifyJs {
protected $fileSystem;
protected $fileUsage;
protected $pathMatcher;
protected $mimeTypeGuesser;
public function __construct(PathMatcher $pathMatcher, MimeTypeGuesser $mimeTypeGuesser, DatabaseFileUsageBackend $fileUsage, FileSystem $fileSystem) {
$this->pathMatcher = $pathMatcher;
$this->mimeTypeGuesser = $mimeTypeGuesser;
$this->fileUsage = $fileUsage;
$this->fileSystem = $fileSystem;
}
public function minify($file) {
$result = $this
->minifyFile($file, TRUE);
if ($result === TRUE) {
\Drupal::messenger()
->addMessage(t('File was minified successfully.'));
}
else {
\Drupal::messenger()
->addMessage($result, 'error');
}
}
public function restore($file) {
$result = $this
->removeMinifiedFile($file, TRUE);
if ($result === TRUE) {
\Drupal::messenger()
->addMessage(t('File was restored successfully.'));
}
else {
\Drupal::messenger()
->addMessage($result, 'error');
}
}
public function scan() {
$directory = new \RecursiveDirectoryIterator(DRUPAL_ROOT);
$iterator = new \RecursiveIteratorIterator($directory);
$regex = new \RegexIterator($iterator, '/\\.js$/i');
$new_files = [];
$old_files = [];
$changed_files = [];
$existing = $this
->loadAllFiles();
$exclusions = \Drupal::config('minifyjs.config')
->get('exclusion_list');
foreach ($regex as $info) {
$new_absolute = $info
->getPathname();
$new_relative = str_replace(DRUPAL_ROOT . DIRECTORY_SEPARATOR, '', $new_absolute);
if ($this->pathMatcher
->matchPath($new_relative, $exclusions)) {
continue;
}
$exists = FALSE;
foreach ($existing as $file) {
if ($file->uri == $new_relative) {
if (!empty($file->minified_uri)) {
$size = filesize($new_absolute);
$modified = filemtime($new_absolute);
if ($size != $file->size || $modified != $file->modified) {
$changed_files[$new_relative] = $file;
}
}
$exists = TRUE;
$old_files[$new_relative] = TRUE;
break;
}
}
if (!$exists) {
$new_files[$new_absolute] = TRUE;
}
}
foreach ($existing as $file) {
if (!isset($old_files[$file->uri])) {
$this
->removeFile($file->uri);
}
}
foreach ($changed_files as $file_uri => $file) {
$this
->removeFile($file->uri);
$new_files[$file_uri] = TRUE;
\Drupal::messenger()
->addMessage(t('Original file %file has been modified and was restored.', [
'%file' => $file_uri,
]));
}
foreach ($new_files as $file => $junk) {
\Drupal::database()
->insert('minifyjs_file')
->fields([
'uri' => str_replace(DRUPAL_ROOT . DIRECTORY_SEPARATOR, '', $file),
'size' => filesize($file),
'modified' => filemtime($file),
])
->execute();
}
\Drupal::cache()
->delete(MINIFYJS_CACHE_CID);
}
public function loadAllFiles() {
if ($cache = \Drupal::cache()
->get(MINIFYJS_CACHE_CID)) {
return $cache->data;
}
$result = \Drupal::database()
->select('minifyjs_file', 'f')
->fields('f')
->orderBy('uri')
->execute();
$exclusions = \Drupal::config('minifyjs.config')
->get('exclusion_list');
$files = [];
while ($file = $result
->fetchObject()) {
if (!$this->pathMatcher
->matchPath($file->uri, $exclusions)) {
$files[$file->fid] = $file;
}
}
\Drupal::cache()
->set(MINIFYJS_CACHE_CID, $files, strtotime('+1 day', \Drupal::time()
->getRequestTime()));
return $files;
}
public function minifyFile($fid, $reset = FALSE) {
$files = $this
->loadAllFiles();
$file = $files[$fid];
$js = file_get_contents(DRUPAL_ROOT . DIRECTORY_SEPARATOR . $file->uri);
$minified = $js;
if (strlen($js)) {
$minifier = new JSqueeze();
$minified = $minifier
->squeeze($js, TRUE, FALSE);
}
$minifyjs_folder = 'public://minifyjs/' . dirname($file->uri);
$result = $this->fileSystem
->prepareDirectory($minifyjs_folder, FileSystemInterface::CREATE_DIRECTORY | FileSystemInterface::MODIFY_PERMISSIONS);
$file_name = str_replace('.js', '.min.js', basename($file->uri));
$tmp_file = $this->fileSystem
->getTempDirectory() . DIRECTORY_SEPARATOR . $file_name;
$file_uri = $minifyjs_folder . DIRECTORY_SEPARATOR . $file_name;
if (file_put_contents($tmp_file, $minified) !== FALSE) {
if (copy($tmp_file, $file_uri)) {
if (empty($file->minified_uri)) {
$file = File::create([
'uid' => \Drupal::currentUser()
->id(),
'uri' => $file_uri,
'filename' => $file_name,
'filemime' => $this->mimeTypeGuesser
->guess($file->uri),
'status' => FILE_STATUS_PERMANENT,
]);
$file
->save();
$this->fileUsage
->add($file, 'minifyjs', 'node', 1);
}
$filesize = filesize($file_uri);
\Drupal::database()
->update('minifyjs_file')
->fields([
'minified_uri' => $file_uri,
'minified_size' => $filesize ? $filesize : 0,
'minified_modified' => \Drupal::time()
->getRequestTime(),
])
->condition('fid', $fid)
->execute();
unlink($tmp_file);
if ($reset) {
\Drupal::cache()
->delete(MINIFYJS_CACHE_CID);
}
return TRUE;
}
else {
return t('Could not copy the file from the %tmp folder.', [
'%tmp' => $this->fileSystem
->getTempDirectory(),
]);
}
}
else {
return t('Could not save the file - %file', [
'%file' => $this->fileSystem
->getTempDirectory() . DIRECTORY_SEPARATOR . $file_name,
]);
}
}
public function removeMinifiedFile($fid, $reset = FALSE) {
$query = \Drupal::database()
->select('minifyjs_file', 'm')
->fields('m', [
'minified_uri',
])
->condition('m.fid', $fid);
if ($query
->countQuery()
->execute()
->fetchField() > 0) {
$file = $query
->execute()
->fetchObject();
$query = \Drupal::database()
->select('file_managed', 'f')
->fields('f', [
'fid',
])
->condition('f.uri', $file->minified_uri);
if ($query
->countQuery()
->execute()
->fetchField() > 0) {
$file = $query
->execute()
->fetchObject();
$file = File::load($file->fid);
$file
->delete();
\Drupal::database()
->update('minifyjs_file')
->fields([
'minified_uri' => '',
'minified_size' => 0,
'minified_modified' => 0,
])
->condition('fid', $fid)
->execute();
if ($reset) {
\Drupal::cache()
->delete(MINIFYJS_CACHE_CID);
}
return TRUE;
}
}
return t('File not found. Check that the file ID is correct.');
}
protected function removeFile($file_uri) {
$query = \Drupal::database()
->select('minifyjs_file', 'm')
->fields('m', [
'fid',
'minified_uri',
])
->condition('m.uri', $file_uri);
if ($query
->countQuery()
->execute()
->fetchField() > 0) {
$file = $query
->execute()
->fetchObject();
if (!empty($file->minified_uri)) {
$query = \Drupal::database()
->select('file_managed', 'f')
->fields('f', [
'fid',
])
->condition('f.uri', $file->minified_uri);
if ($query
->countQuery()
->execute()
->fetchField() > 0) {
$minified_file = $query
->execute()
->fetchObject();
$minified_file = File::load($minified_file->fid);
$minified_file
->delete();
}
}
\Drupal::database()
->delete('minifyjs_file')
->condition('fid', $file->fid)
->execute();
return TRUE;
}
}
}