improvements streamCSSBigFile

This commit is contained in:
Fernando Ontiveros
2025-04-25 16:20:18 +00:00
parent e6ce83a1e4
commit 6a5e44a04c
2 changed files with 72 additions and 74 deletions

View File

@@ -408,19 +408,20 @@ class Bootstrap
}
/**
* Parsing the URI
* Parses the given URI and sets system constants based on the parsed values.
*
* @author Fernando Ontiveros Lira <fernando@colosa.com>
* @access public
* @param string $urlLink
* @param array $arrayFriendlyUri
* @param string $uri The URI to parse.
* @param array $arrayFriendlyUri An optional array for friendly URIs.
*
* @return string
*/
public static function parseURI($uri, array $arrayFriendlyUri = null)
public static function parseURI($uri, array $arrayFriendlyUri = [])
{
$aRequestUri = explode('/', $uri);
$args = self::parseNormalUri($aRequestUri, $arrayFriendlyUri);
// Split the URI into segments
$requestUriSegments = explode('/', $uri);
// Parse the URI segments into
$args = self::parseNormalUri($requestUriSegments, $arrayFriendlyUri);
if (! empty($args)) {
define("SYS_LANG", $args ['SYS_LANG']);
@@ -428,7 +429,7 @@ class Bootstrap
define('SYS_COLLECTION', $args ['SYS_COLLECTION']);
define('SYS_TARGET', $args ['SYS_TARGET']);
if (array_key_exists('API_VERSION', $args)) {
if (isset($args['API_VERSION'])) {
define('API_VERSION', $args['API_VERSION']);
}
}
@@ -853,34 +854,34 @@ class Bootstrap
}
/**
* Dynamically generates and streams a CSS file by aggregating smaller CSS files.
*
* This function is designed to serve CSS content dynamically based on different skins or themes.
* It reads configuration files to determine which CSS files to include, handles caching headers,
* and performs browser-specific logic to ensure compatibility.
* streaming a big JS file with small js files
*
* @author Fernando Ontiveros Lira <fernando@colosa.com>
* @access public
* @param string $filename The name of the file, used to determine the skin and variant.
* @return string The aggregated and minified CSS content.
* @param string $file
* @return string
*/
public static function streamCSSBigFile($filename)
{
// Set the content type to CSS and prevent MIME type sniffing
header('Content-Type: text/css');
header('X-Content-Type-Options: nosniff');
// Parse the filename to extract skin name and variant
//First get Skin info
$filenameParts = explode("-", $filename);
$skinName = !empty($filenameParts[0]) ? $filenameParts[0] : 'base';
$skinVariant = isset($filenameParts[1]) ? strtolower($filenameParts[1]) : 'skin';
$skinName = empty($filenameParts[0]) ? 'base' : $filenameParts[0];
$skinVariant = "skin";
// Normalize skin names
if (in_array($skinName, ['jscolors', 'xmlcolors'])) {
$skinName = 'classic';
if (isset($filenameParts[1])) {
$skinVariant = strtolower($filenameParts[1]);
}
// Determine the configuration file path based on the skin name
$configurationFile = '';
if ($skinName == "jscolors") {
$skinName = "classic";
}
if ($skinName == "xmlcolors") {
$skinName = "classic";
}
if ($skinName == "classic") {
$configurationFile = Bootstrap::ExpandPath("skinEngine") . 'base' . PATH_SEP . 'config.xml';
} else {
@@ -894,49 +895,50 @@ class Bootstrap
$configurationFile = Bootstrap::ExpandPath("skinEngine") . $skinName . PATH_SEP . 'config.xml';
}
}
// Fallback to base configuration if the specific one doesn't exist
if (!file_exists($configurationFile)) {
$configurationFile = Bootstrap::ExpandPath("skinEngine") . 'base' . PATH_SEP . 'config.xml';
}
// Set caching headers
$mtime = time();
$mtime = date('U');
$gmt_mtime = gmdate("D, d M Y H:i:s", $mtime) . " GMT";
$etag = '"' . Bootstrap::encryptOld($mtime . $filename) . '"';
$expires = gmdate("D, d M Y H:i:s", $mtime + 30 * 24 * 60 * 60) . " GMT"; // 1 month
header('Pragma: cache');
header('ETag: ' . $etag);
header('Last-Modified: ' . $gmt_mtime);
header('ETag: "' . Bootstrap::encryptOld($mtime . $filename) . '"');
header("Last-Modified: " . $gmt_mtime);
header('Cache-Control: public');
header('Expires: ' . $expires);
// Handle conditional requests for caching
$ifModifiedSince = $_SERVER['HTTP_IF_MODIFIED_SINCE'] ?? null;
$ifNoneMatch = $_SERVER['HTTP_IF_NONE_MATCH'] ?? null;
if (($ifModifiedSince && $ifModifiedSince === $gmt_mtime) ||
($ifNoneMatch && str_replace('"', '', stripslashes($ifNoneMatch)) === Bootstrap::encryptOld($mtime . $filename))) {
header("Expires: " . gmdate("D, d M Y H:i:s", time() + 30 * 60 * 60 * 24) . " GMT"); //1 month
//header("Expires: " . gmdate("D, d M Y H:i:s", time () + 60*60*24 ) . " GMT"); //1 day - tempor
if (isset($_SERVER['HTTP_IF_MODIFIED_SINCE'])) {
if ($_SERVER['HTTP_IF_MODIFIED_SINCE'] == $gmt_mtime) {
header('HTTP/1.1 304 Not Modified');
exit();
}
}
// Read and parse the configuration XML file
if (isset($_SERVER['HTTP_IF_NONE_MATCH'])) {
if (str_replace('"', '', stripslashes($_SERVER['HTTP_IF_NONE_MATCH'])) == Bootstrap::encryptOld($mtime . $filename)) {
header("HTTP/1.1 304 Not Modified");
exit();
}
}
//Read Configuration File
$xmlConfiguration = file_get_contents($configurationFile);
$xmlConfigurationObj = Bootstrap::xmlParser($xmlConfiguration);
$baseSkinDirectory = dirname($configurationFile);
$directorySize = Bootstrap::getDirectorySize($baseSkinDirectory);
$mtime = $directorySize['maxmtime'];
// Prepare the CSS output with a header comment
$outputHeader = "/* Autogenerated CSS file by gulliver framework ** \n";
//if userAgent (BROWSER) is MSIE we need special headers to avoid MSIE behaivor.
//$userAgent = strtolower($_SERVER['HTTP_USER_AGENT']);
$outputHeader = "/* Autogenerated CSS file by gulliver framework \n";
$outputHeader .= " Skin: $filename\n";
$mtimeNow = date('U');
$gmt_mtimeNow = gmdate("D, d M Y H:i:s", $mtimeNow) . " GMT";
$outputHeader .= " Date: $gmt_mtimeNow*/\n";
$output = "";
// Include base CSS files based on the skin variant
//Base files
switch (strtolower($skinVariant)) {
case "extjs":
//Base
@@ -951,7 +953,7 @@ class Bootstrap
break;
}
// Get browser information for compatibility checks
//Get Browser Info
$infoBrowser = Bootstrap::get_current_browser();
$browserName = $infoBrowser['browser_working'];
if (isset($infoBrowser[$browserName . '_data'])) {
@@ -960,7 +962,7 @@ class Bootstrap
}
}
// Parse the configuration to get the list of CSS files to include
//Read Configuration File
$xmlConfiguration = file_get_contents($configurationFile);
$xmlConfigurationObj = Bootstrap::xmlParser($xmlConfiguration);
@@ -971,8 +973,6 @@ class Bootstrap
if (isset($skinFilesArray['__ATTRIBUTES__'])) {
$skinFilesArray = array($skinFilesArray);
}
// Iterate over each CSS file and include it if compatible with the current browser
foreach ($skinFilesArray as $keyFile => $cssFileInfo) {
$enabledBrowsers = explode(",", $cssFileInfo['__ATTRIBUTES__']['enabledBrowsers']);
$disabledBrowsers = explode(",", $cssFileInfo['__ATTRIBUTES__']['disabledBrowsers']);
@@ -1000,14 +1000,8 @@ class Bootstrap
}
}
// Minify the CSS by removing comments and unnecessary whitespace
$regex = array(
"`^([\t\s]+)`ism" => '',
"`^\/\*(.+?)\*\/`ism" => "",
"`([\n;]+)\/\*(.+?)\*\/`ism" => "$1",
"`([\n;\s]+)//(.+?)[\n\r]`ism" => "$1\n",
"`(^[\r\n]*|[\r\n]+)[\s\t]*[\r\n]+`ism" => "\n"
);
//Remove comments..
$regex = array("`^([\t\s]+)`ism" => '', "`^\/\*(.+?)\*\/`ism" => "", "`([\n;]+)\/\*(.+?)\*\/`ism" => "$1", "`([\n;\s]+)//(.+?)[\n\r]`ism" => "$1\n", "`(^[\r\n]*|[\r\n]+)[\s\t]*[\r\n]+`ism" => "\n");
$output = preg_replace(array_keys($regex), $regex, $output);
$output = $outputHeader . $output;

View File

@@ -380,16 +380,20 @@ if (!defined('PATH_DB') || !file_exists(PATH_DB)) {
app()->useStoragePath(realpath(PATH_DATA));
app()->make(Kernel::class)->bootstrap();
restore_error_handler();
//Overwrite with the Processmaker env.ini configuration used in production environments
//@todo: move env.ini configuration to .env
ini_set('display_errors', $config['display_errors']);
ini_set('error_reporting', $config['error_reporting']);
//ini_set('display_errors', $config['display_errors']);
//ini_set('error_reporting', $config['error_reporting']);
ini_set('display_errors', true);
ini_set('error_reporting', true);
ini_set('short_open_tag', 'On');
ini_set('default_charset', "UTF-8");
ini_set('soap.wsdl_cache_enabled', $config['wsdl_cache']);
ini_set('date.timezone', TIME_ZONE); //Set Time Zone
date_default_timezone_set(TIME_ZONE);
config(['app.timezone' => TIME_ZONE]);