Last active
May 27, 2023 19:50
-
-
Save Arifursdev/899d0d71ed0ea4e3d62bf27a6b33275b to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
/* | |
USAGES | |
require __DIR__ . '/AssetsManager.php'; | |
$assets = new AssetsManager( 'assets/', 'cache/'); | |
<link rel="stylesheet" href="<?php echo $assets->getAssetUrl('css/style.min.css'); ?>"> | |
<script src="<?php echo $assets->getAssetUrl('js/vendors.min.js', false); ?>" defer></script> | |
<script src="<?php echo $assets->getAssetUrl('js/app.min.js'); ?>" defer></script> | |
use at your own risk | |
*/ | |
class AssetsManager { | |
private $assetPath; | |
private $cachePath; | |
/** | |
* AssetsManager constructor. | |
* | |
* @param string $assetPath The path to the asset files. | |
* @param string $cachePath The path to the cache folder. | |
*/ | |
public function __construct( $assetPath, $cachePath ) { | |
$this->assetPath = $assetPath; | |
$this->cachePath = $cachePath; | |
} | |
/** | |
* Minify CSS content. | |
* | |
* @param string $content The CSS content to be minified. | |
* @return string The minified CSS content. | |
*/ | |
private function minifyCSS( $content ) { | |
// Remove CSS comments (/* ... */) | |
$content = preg_replace('!/\*[^*]*\*+([^/][^*]*\*+)*/!', '', $content); | |
// Remove leading and trailing whitespace | |
$content = trim($content); | |
// Remove whitespace around selectors, properties, and values | |
$content = preg_replace('/\s*([{}|:;,])\s*/', '$1', $content); | |
// Remove semicolons before closing braces | |
$content = preg_replace('/;\s*}/', '}', $content); | |
// Remove empty rules | |
$content = preg_replace('/[^{}]+{}/', '', $content); | |
// Remove trailing semicolons from rules | |
$content = preg_replace('/;\s*}/', '}', $content); | |
// Remove leading zeros from decimal values | |
$content = preg_replace('/(\s|:|,)0+\.(\d+)/', '$1.$2', $content); | |
// Remove units from zero values | |
$content = preg_replace('/(\s|:)0+([a-zA-Z]+)/', '$1$2', $content); | |
return $content; | |
} | |
/** | |
* Minify JS content. | |
* | |
* @param string $content The JS content to be minified. | |
* @return string The minified JS content. | |
*/ | |
private function minifyJS( $content ) { | |
// Remove JS comments (// ... and /* ... */) | |
$content = preg_replace('!/\*[^*]*\*+([^/][^*]*\*+)*/!', '', $content); | |
$content = preg_replace('/\/\/(.+)$/', '', $content); | |
// Remove leading and trailing whitespace | |
$content = trim($content); | |
// Remove line breaks and multiple whitespace | |
$content = preg_replace('/\s+/', ' ', $content); | |
// Remove unnecessary whitespace around operators and brackets | |
$content = preg_replace('/\s*([=!<>+\-*\/%&|^~?:]=|\+\+|--|\+=|-=|\*=|\/=|%=|&&|\|\||<<|>>|>>>)\s*/', '$1', $content); | |
$content = preg_replace('/\s*([{}()[\],;])\s*/', '$1', $content); | |
return $content; | |
} | |
/** | |
* Get the URL for the asset file, either from the cache or generate a new minified version. | |
* | |
* @param string $filePath The path to the asset file. | |
* @return string The URL of the asset file. | |
* @throws Exception If the file extension is invalid. | |
*/ | |
public function getAssetUrl( $filePath, $minifyAndCache = true ) { | |
if ( $minifyAndCache === false ) { | |
return $this->assetPath . $filePath; | |
} | |
$extension = pathinfo( $filePath, PATHINFO_EXTENSION ); | |
// Check if the file extension is valid (CSS or JS) | |
if ( $extension !== 'css' && $extension !== 'js' ) { | |
// Invalid file extension, throw an exception | |
throw new Exception( 'Invalid file extension. Only CSS and JS files are supported.' ); | |
} | |
$cachedFile = $this->getCachedFilePath( $filePath ); | |
// Check if the cached file exists and if the original file has been modified | |
if ( file_exists( $cachedFile ) && !$this->isFileModified( $filePath, $cachedFile ) ) { | |
// Retrieve the URL from the cache folder | |
return $this->getCacheUrl( $cachedFile ); | |
} | |
// Generate the minified version | |
$minifiedFile = $this->generateMinifiedFile( $filePath, $extension ); | |
// Move the minified file to the cache folder | |
$this->moveToCache( $minifiedFile, $cachedFile ); | |
// Retrieve the URL from the cache folder | |
return $this->getCacheUrl( $cachedFile ); | |
} | |
/** | |
* Generate a minified version of the asset file. | |
* | |
* @param string $filePath The path to the asset file. | |
* @param string $extension The file extension. | |
* @return string The path to the minified file. | |
*/ | |
private function generateMinifiedFile( $filePath, $extension ) { | |
$fileContent = file_get_contents( $this->assetPath . $filePath ); | |
$minifiedContent = ''; | |
if ( $extension === 'css' ) { | |
// Minify CSS | |
$minifiedContent = $this->minifyCSS( $fileContent, 'css' ); | |
} elseif ( $extension === 'js' ) { | |
// Minify JS | |
$minifiedContent = $this->minifyJS( $fileContent, 'js' ); | |
} | |
// Get the original file name without the extension | |
$originalFileName = pathinfo( $filePath, PATHINFO_FILENAME ); | |
// Generate the minified file name with the original file name and version | |
$minifiedFileName = $originalFileName . '.' . filemtime( $this->assetPath . $filePath ) . '.min.' . $extension; | |
// Get the directory path of the cache file | |
$cacheDirectory = dirname( $this->cachePath . $minifiedFileName ); | |
// Create the directory if it doesn't exist | |
if ( !file_exists( $cacheDirectory ) ) { | |
mkdir( $cacheDirectory, 0777, true ); | |
} | |
// Write the minified content to a new file | |
$minifiedFilePath = $this->cachePath . $minifiedFileName; | |
file_put_contents( $minifiedFilePath, $minifiedContent ); | |
return $minifiedFilePath; | |
} | |
/** | |
* Check if the original asset file has been modified. | |
* | |
* @param string $filePath The path to the asset file. | |
* @param string $cachedFile The path to the cached file. | |
* @return bool Whether the original file has been modified or not. | |
*/ | |
private function isFileModified( $filePath, $cachedFile ) { | |
$originalTimestamp = filemtime( $this->assetPath . $filePath ); | |
$cachedTimestamp = filemtime( $cachedFile ); | |
return $originalTimestamp > $cachedTimestamp; | |
} | |
/** | |
* Get the path to the cached file. | |
* | |
* @param string $filePath The path to the asset file. | |
* @return string The path to the cached file. | |
*/ | |
private function getCachedFilePath( $filePath ) { | |
// Get the directory name of the asset file | |
$directoryName = pathinfo( $filePath, PATHINFO_DIRNAME ); | |
// Get the original file name without the extension | |
$originalFileName = pathinfo( $filePath, PATHINFO_FILENAME ); | |
// Generate a unique file name for the cached version with the original file name, directory, and version | |
$cachedFileName = $directoryName . '/' . $originalFileName . '.' . filemtime( $this->assetPath . $filePath ) . '.' . pathinfo( $filePath, PATHINFO_EXTENSION ); | |
return $this->cachePath . $cachedFileName; | |
} | |
/** | |
* Move a file to the cache folder. | |
* | |
* @param string $sourceFile The path to the source file. | |
* @param string $destinationFile The path to the destination file. | |
* @return void | |
*/ | |
private function moveToCache( $sourceFile, $destinationFile ) { | |
// Create the parent directory if it doesn't exist | |
$parentDirectory = pathinfo( $destinationFile, PATHINFO_DIRNAME ); | |
if ( !file_exists( $parentDirectory ) ) { | |
mkdir( $parentDirectory, 0777, true ); | |
} | |
// Move the file to the cache folder | |
rename( $sourceFile, $destinationFile ); | |
} | |
/** | |
* Get the URL of the cached file. | |
* | |
* @param string $cachedFile The path to the cached file. | |
* @return string The URL of the cached file. | |
*/ | |
private function getCacheUrl( $cachedFile ) { | |
// Get the relative path to the cached file | |
$relativePath = str_replace( $this->cachePath, '', $cachedFile ); | |
// Combine the cache folder path with the relative path | |
$cacheUrl = rtrim( $this->cachePath, '/' ) . '/' . ltrim( $relativePath, '/' ); | |
return $cacheUrl; | |
} | |
/** | |
* Delete all cache files. | |
* | |
* @return void | |
*/ | |
public function deleteCacheFiles() { | |
foreach (glob($dir) as $file) { | |
if (is_dir($file)) { | |
rmrf("$file/*"); | |
rmdir($file); | |
} else { | |
unlink($file); | |
} | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment