N°2435.2 Manage SCSSPHP lib using composer

This commit is contained in:
Molkobain
2019-08-13 10:50:54 +02:00
parent 5960dc6245
commit bb4c8ea52d
43 changed files with 762 additions and 2 deletions

View File

@@ -1528,7 +1528,6 @@ class utils
clearstatcache();
if (!file_exists($sCssPath) || (is_writable($sCssPath) && (filemtime($sCssPath) < filemtime($sSassPath))))
{
require_once(APPROOT.'lib/scssphp/scss.inc.php');
$oScss = new Compiler();
$oScss->setImportPaths($aImportPaths);
$oScss->setFormatter('ScssPhp\\ScssPhp\\Formatter\\Expanded');

View File

@@ -11,6 +11,8 @@
"ext-gd": "*",
"ext-ctype": "*",
"scssphp/scssphp": "1.0.0",
"symfony/console": "3.4.*",
"symfony/dotenv": "3.4.*",
"symfony/framework-bundle": "3.4.*",

61
composer.lock generated
View File

@@ -4,7 +4,7 @@
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
"This file is @generated automatically"
],
"content-hash": "41f51225471c2e18c3488910cdeabcf6",
"content-hash": "b5e0d8a47b8f42ff3820b452900c2d90",
"packages": [
{
"name": "paragonie/random_compat",
@@ -245,6 +245,65 @@
],
"time": "2017-10-23T01:57:42+00:00"
},
{
"name": "scssphp/scssphp",
"version": "1.0.0",
"source": {
"type": "git",
"url": "https://github.com/scssphp/scssphp.git",
"reference": "6c8734b6edcf6c2fa785ad874b998fa854a7d030"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/scssphp/scssphp/zipball/6c8734b6edcf6c2fa785ad874b998fa854a7d030",
"reference": "6c8734b6edcf6c2fa785ad874b998fa854a7d030",
"shasum": ""
},
"require": {
"php": "^5.6.0 || ^7"
},
"require-dev": {
"phpunit/phpunit": "~4.6",
"squizlabs/php_codesniffer": "~2.5",
"twbs/bootstrap": "~4.3",
"zurb/foundation": "~6.5"
},
"bin": [
"bin/pscss"
],
"type": "library",
"autoload": {
"psr-4": {
"ScssPhp\\ScssPhp\\": "src/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Anthon Pang",
"email": "apang@softwaredevelopment.ca",
"homepage": "https://github.com/robocoder"
},
{
"name": "Cédric Morin",
"email": "cedric@yterium.com",
"homepage": "https://github.com/Cerdic"
}
],
"description": "scssphp is a compiler for SCSS written in PHP.",
"homepage": "http://scssphp.github.io/scssphp/",
"keywords": [
"css",
"less",
"sass",
"scss",
"stylesheet"
],
"time": "2019-06-05T01:22:01+00:00"
},
{
"name": "symfony/cache",
"version": "v3.4.30",

10
lib/bin/pscss Normal file
View File

@@ -0,0 +1,10 @@
#!/usr/bin/env sh
dir=$(cd "${0%[/\\]*}" > /dev/null; cd "../scssphp/scssphp/bin" && pwd)
if [ -d /proc/cygdrive ] && [[ $(which php) == $(readlink -n /proc/cygdrive)/* ]]; then
# We are in Cgywin using Windows php, so the path must be translated
dir=$(cygpath -m "$dir");
fi
"${dir}/pscss" "$@"

4
lib/bin/pscss.bat Normal file
View File

@@ -0,0 +1,4 @@
@ECHO OFF
setlocal DISABLEDELAYEDEXPANSION
SET BIN_TARGET=%~dp0/../scssphp/scssphp/bin/pscss
php "%BIN_TARGET%" %*

View File

@@ -381,6 +381,34 @@ return array(
'SQLUnionQuery' => $baseDir . '/core/sqlunionquery.class.inc.php',
'ScalarExpression' => $baseDir . '/core/oql/expression.class.inc.php',
'ScalarOqlExpression' => $baseDir . '/core/oql/oqlquery.class.inc.php',
'ScssPhp\\ScssPhp\\Base\\Range' => $vendorDir . '/scssphp/scssphp/src/Base/Range.php',
'ScssPhp\\ScssPhp\\Block' => $vendorDir . '/scssphp/scssphp/src/Block.php',
'ScssPhp\\ScssPhp\\Cache' => $vendorDir . '/scssphp/scssphp/src/Cache.php',
'ScssPhp\\ScssPhp\\Colors' => $vendorDir . '/scssphp/scssphp/src/Colors.php',
'ScssPhp\\ScssPhp\\Compiler' => $vendorDir . '/scssphp/scssphp/src/Compiler.php',
'ScssPhp\\ScssPhp\\Compiler\\Environment' => $vendorDir . '/scssphp/scssphp/src/Compiler/Environment.php',
'ScssPhp\\ScssPhp\\Exception\\CompilerException' => $vendorDir . '/scssphp/scssphp/src/Exception/CompilerException.php',
'ScssPhp\\ScssPhp\\Exception\\ParserException' => $vendorDir . '/scssphp/scssphp/src/Exception/ParserException.php',
'ScssPhp\\ScssPhp\\Exception\\RangeException' => $vendorDir . '/scssphp/scssphp/src/Exception/RangeException.php',
'ScssPhp\\ScssPhp\\Exception\\ServerException' => $vendorDir . '/scssphp/scssphp/src/Exception/ServerException.php',
'ScssPhp\\ScssPhp\\Formatter' => $vendorDir . '/scssphp/scssphp/src/Formatter.php',
'ScssPhp\\ScssPhp\\Formatter\\Compact' => $vendorDir . '/scssphp/scssphp/src/Formatter/Compact.php',
'ScssPhp\\ScssPhp\\Formatter\\Compressed' => $vendorDir . '/scssphp/scssphp/src/Formatter/Compressed.php',
'ScssPhp\\ScssPhp\\Formatter\\Crunched' => $vendorDir . '/scssphp/scssphp/src/Formatter/Crunched.php',
'ScssPhp\\ScssPhp\\Formatter\\Debug' => $vendorDir . '/scssphp/scssphp/src/Formatter/Debug.php',
'ScssPhp\\ScssPhp\\Formatter\\Expanded' => $vendorDir . '/scssphp/scssphp/src/Formatter/Expanded.php',
'ScssPhp\\ScssPhp\\Formatter\\Nested' => $vendorDir . '/scssphp/scssphp/src/Formatter/Nested.php',
'ScssPhp\\ScssPhp\\Formatter\\OutputBlock' => $vendorDir . '/scssphp/scssphp/src/Formatter/OutputBlock.php',
'ScssPhp\\ScssPhp\\Node' => $vendorDir . '/scssphp/scssphp/src/Node.php',
'ScssPhp\\ScssPhp\\Node\\Number' => $vendorDir . '/scssphp/scssphp/src/Node/Number.php',
'ScssPhp\\ScssPhp\\Parser' => $vendorDir . '/scssphp/scssphp/src/Parser.php',
'ScssPhp\\ScssPhp\\SourceMap\\Base64' => $vendorDir . '/scssphp/scssphp/src/SourceMap/Base64.php',
'ScssPhp\\ScssPhp\\SourceMap\\Base64VLQ' => $vendorDir . '/scssphp/scssphp/src/SourceMap/Base64VLQ.php',
'ScssPhp\\ScssPhp\\SourceMap\\Base64VLQEncoder' => $vendorDir . '/scssphp/scssphp/src/SourceMap/Base64VLQEncoder.php',
'ScssPhp\\ScssPhp\\SourceMap\\SourceMapGenerator' => $vendorDir . '/scssphp/scssphp/src/SourceMap/SourceMapGenerator.php',
'ScssPhp\\ScssPhp\\Type' => $vendorDir . '/scssphp/scssphp/src/Type.php',
'ScssPhp\\ScssPhp\\Util' => $vendorDir . '/scssphp/scssphp/src/Util.php',
'ScssPhp\\ScssPhp\\Version' => $vendorDir . '/scssphp/scssphp/src/Version.php',
'SearchMenuNode' => $baseDir . '/application/menunode.class.inc.php',
'SecurityException' => $baseDir . '/core/coreexception.class.inc.php',
'SeparatorPopupMenuItem' => $baseDir . '/application/applicationextension.inc.php',

View File

@@ -31,6 +31,7 @@ return array(
'Symfony\\Bundle\\TwigBundle\\' => array($vendorDir . '/symfony/twig-bundle'),
'Symfony\\Bundle\\FrameworkBundle\\' => array($vendorDir . '/symfony/framework-bundle'),
'Symfony\\Bridge\\Twig\\' => array($vendorDir . '/symfony/twig-bridge'),
'ScssPhp\\ScssPhp\\' => array($vendorDir . '/scssphp/scssphp/src'),
'Psr\\SimpleCache\\' => array($vendorDir . '/psr/simple-cache/src'),
'Psr\\Log\\' => array($vendorDir . '/psr/log/Psr/Log'),
'Psr\\Container\\' => array($vendorDir . '/psr/container/src'),

View File

@@ -46,6 +46,7 @@ class ComposerStaticInit0018331147de7601e7552f7da8e3bb8b
'Symfony\\Bundle\\TwigBundle\\' => 26,
'Symfony\\Bundle\\FrameworkBundle\\' => 31,
'Symfony\\Bridge\\Twig\\' => 20,
'ScssPhp\\ScssPhp\\' => 16,
),
'P' =>
array (
@@ -157,6 +158,10 @@ class ComposerStaticInit0018331147de7601e7552f7da8e3bb8b
array (
0 => __DIR__ . '/..' . '/symfony/twig-bridge',
),
'ScssPhp\\ScssPhp\\' =>
array (
0 => __DIR__ . '/..' . '/scssphp/scssphp/src',
),
'Psr\\SimpleCache\\' =>
array (
0 => __DIR__ . '/..' . '/psr/simple-cache/src',
@@ -561,6 +566,34 @@ class ComposerStaticInit0018331147de7601e7552f7da8e3bb8b
'SQLUnionQuery' => __DIR__ . '/../..' . '/core/sqlunionquery.class.inc.php',
'ScalarExpression' => __DIR__ . '/../..' . '/core/oql/expression.class.inc.php',
'ScalarOqlExpression' => __DIR__ . '/../..' . '/core/oql/oqlquery.class.inc.php',
'ScssPhp\\ScssPhp\\Base\\Range' => __DIR__ . '/..' . '/scssphp/scssphp/src/Base/Range.php',
'ScssPhp\\ScssPhp\\Block' => __DIR__ . '/..' . '/scssphp/scssphp/src/Block.php',
'ScssPhp\\ScssPhp\\Cache' => __DIR__ . '/..' . '/scssphp/scssphp/src/Cache.php',
'ScssPhp\\ScssPhp\\Colors' => __DIR__ . '/..' . '/scssphp/scssphp/src/Colors.php',
'ScssPhp\\ScssPhp\\Compiler' => __DIR__ . '/..' . '/scssphp/scssphp/src/Compiler.php',
'ScssPhp\\ScssPhp\\Compiler\\Environment' => __DIR__ . '/..' . '/scssphp/scssphp/src/Compiler/Environment.php',
'ScssPhp\\ScssPhp\\Exception\\CompilerException' => __DIR__ . '/..' . '/scssphp/scssphp/src/Exception/CompilerException.php',
'ScssPhp\\ScssPhp\\Exception\\ParserException' => __DIR__ . '/..' . '/scssphp/scssphp/src/Exception/ParserException.php',
'ScssPhp\\ScssPhp\\Exception\\RangeException' => __DIR__ . '/..' . '/scssphp/scssphp/src/Exception/RangeException.php',
'ScssPhp\\ScssPhp\\Exception\\ServerException' => __DIR__ . '/..' . '/scssphp/scssphp/src/Exception/ServerException.php',
'ScssPhp\\ScssPhp\\Formatter' => __DIR__ . '/..' . '/scssphp/scssphp/src/Formatter.php',
'ScssPhp\\ScssPhp\\Formatter\\Compact' => __DIR__ . '/..' . '/scssphp/scssphp/src/Formatter/Compact.php',
'ScssPhp\\ScssPhp\\Formatter\\Compressed' => __DIR__ . '/..' . '/scssphp/scssphp/src/Formatter/Compressed.php',
'ScssPhp\\ScssPhp\\Formatter\\Crunched' => __DIR__ . '/..' . '/scssphp/scssphp/src/Formatter/Crunched.php',
'ScssPhp\\ScssPhp\\Formatter\\Debug' => __DIR__ . '/..' . '/scssphp/scssphp/src/Formatter/Debug.php',
'ScssPhp\\ScssPhp\\Formatter\\Expanded' => __DIR__ . '/..' . '/scssphp/scssphp/src/Formatter/Expanded.php',
'ScssPhp\\ScssPhp\\Formatter\\Nested' => __DIR__ . '/..' . '/scssphp/scssphp/src/Formatter/Nested.php',
'ScssPhp\\ScssPhp\\Formatter\\OutputBlock' => __DIR__ . '/..' . '/scssphp/scssphp/src/Formatter/OutputBlock.php',
'ScssPhp\\ScssPhp\\Node' => __DIR__ . '/..' . '/scssphp/scssphp/src/Node.php',
'ScssPhp\\ScssPhp\\Node\\Number' => __DIR__ . '/..' . '/scssphp/scssphp/src/Node/Number.php',
'ScssPhp\\ScssPhp\\Parser' => __DIR__ . '/..' . '/scssphp/scssphp/src/Parser.php',
'ScssPhp\\ScssPhp\\SourceMap\\Base64' => __DIR__ . '/..' . '/scssphp/scssphp/src/SourceMap/Base64.php',
'ScssPhp\\ScssPhp\\SourceMap\\Base64VLQ' => __DIR__ . '/..' . '/scssphp/scssphp/src/SourceMap/Base64VLQ.php',
'ScssPhp\\ScssPhp\\SourceMap\\Base64VLQEncoder' => __DIR__ . '/..' . '/scssphp/scssphp/src/SourceMap/Base64VLQEncoder.php',
'ScssPhp\\ScssPhp\\SourceMap\\SourceMapGenerator' => __DIR__ . '/..' . '/scssphp/scssphp/src/SourceMap/SourceMapGenerator.php',
'ScssPhp\\ScssPhp\\Type' => __DIR__ . '/..' . '/scssphp/scssphp/src/Type.php',
'ScssPhp\\ScssPhp\\Util' => __DIR__ . '/..' . '/scssphp/scssphp/src/Util.php',
'ScssPhp\\ScssPhp\\Version' => __DIR__ . '/..' . '/scssphp/scssphp/src/Version.php',
'SearchMenuNode' => __DIR__ . '/../..' . '/application/menunode.class.inc.php',
'SecurityException' => __DIR__ . '/../..' . '/core/coreexception.class.inc.php',
'SeparatorPopupMenuItem' => __DIR__ . '/../..' . '/application/applicationextension.inc.php',

View File

@@ -248,6 +248,67 @@
"simple-cache"
]
},
{
"name": "scssphp/scssphp",
"version": "1.0.0",
"version_normalized": "1.0.0.0",
"source": {
"type": "git",
"url": "https://github.com/scssphp/scssphp.git",
"reference": "6c8734b6edcf6c2fa785ad874b998fa854a7d030"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/scssphp/scssphp/zipball/6c8734b6edcf6c2fa785ad874b998fa854a7d030",
"reference": "6c8734b6edcf6c2fa785ad874b998fa854a7d030",
"shasum": ""
},
"require": {
"php": "^5.6.0 || ^7"
},
"require-dev": {
"phpunit/phpunit": "~4.6",
"squizlabs/php_codesniffer": "~2.5",
"twbs/bootstrap": "~4.3",
"zurb/foundation": "~6.5"
},
"time": "2019-06-05T01:22:01+00:00",
"bin": [
"bin/pscss"
],
"type": "library",
"installation-source": "dist",
"autoload": {
"psr-4": {
"ScssPhp\\ScssPhp\\": "src/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Anthon Pang",
"email": "apang@softwaredevelopment.ca",
"homepage": "https://github.com/robocoder"
},
{
"name": "Cédric Morin",
"email": "cedric@yterium.com",
"homepage": "https://github.com/Cerdic"
}
],
"description": "scssphp is a compiler for SCSS written in PHP.",
"homepage": "http://scssphp.github.io/scssphp/",
"keywords": [
"css",
"less",
"sass",
"scss",
"stylesheet"
]
},
{
"name": "symfony/cache",
"version": "v3.4.30",

View File

View File

@@ -0,0 +1,48 @@
{
"name": "scssphp/scssphp",
"type": "library",
"description": "scssphp is a compiler for SCSS written in PHP.",
"keywords": ["css", "stylesheet", "scss", "sass", "less"],
"homepage": "http://scssphp.github.io/scssphp/",
"license": [
"MIT"
],
"authors": [
{
"name": "Anthon Pang",
"email": "apang@softwaredevelopment.ca",
"homepage": "https://github.com/robocoder"
},
{
"name": "Cédric Morin",
"email": "cedric@yterium.com",
"homepage": "https://github.com/Cerdic"
}
],
"autoload": {
"psr-4": { "ScssPhp\\ScssPhp\\": "src/" }
},
"autoload-dev": {
"psr-4": { "ScssPhp\\ScssPhp\\Test\\": "tests/" }
},
"require": {
"php": "^5.6.0 || ^7"
},
"require-dev": {
"squizlabs/php_codesniffer": "~2.5",
"phpunit/phpunit": "~4.6",
"twbs/bootstrap": "~4.3",
"zurb/foundation": "~6.5"
},
"bin": ["bin/pscss"],
"archive": {
"exclude": [
"/Makefile",
"/.gitattributes",
"/.gitignore",
"/.travis.yml",
"/phpunit.xml.dist",
"/tests"
]
}
}

View File

@@ -0,0 +1,515 @@
<?php
/**
* SCSSPHP
*
* @copyright 2012-2019 Leaf Corcoran
*
* @license http://opensource.org/licenses/MIT MIT
*
* @link http://scssphp.github.io/scssphp
*/
namespace ScssPhp\ScssPhp;
use ScssPhp\ScssPhp\Compiler;
use ScssPhp\ScssPhp\Exception\ServerException;
use ScssPhp\ScssPhp\Version;
/**
* Server
*
* @author Leaf Corcoran <leafot@gmail.com>
*/
class Server
{
/**
* @var boolean
*/
private $showErrorsAsCSS;
/**
* @var string
*/
private $dir;
/**
* @var string
*/
private $cacheDir;
/**
* @var \ScssPhp\ScssPhp\Compiler
*/
private $scss;
/**
* Join path components
*
* @param string $left Path component, left of the directory separator
* @param string $right Path component, right of the directory separator
*
* @return string
*/
protected function join($left, $right)
{
return rtrim($left, '/\\') . DIRECTORY_SEPARATOR . ltrim($right, '/\\');
}
/**
* Get name of requested .scss file
*
* @return string|null
*/
protected function inputName()
{
switch (true) {
case isset($_GET['p']):
return $_GET['p'];
case isset($_SERVER['PATH_INFO']):
return $_SERVER['PATH_INFO'];
case isset($_SERVER['DOCUMENT_URI']):
return substr($_SERVER['DOCUMENT_URI'], strlen($_SERVER['SCRIPT_NAME']));
}
}
/**
* Get path to requested .scss file
*
* @return string
*/
protected function findInput()
{
if (($input = $this->inputName())
&& strpos($input, '..') === false
&& substr($input, -5) === '.scss'
) {
$name = $this->join($this->dir, $input);
if (is_file($name) && is_readable($name)) {
return $name;
}
}
return false;
}
/**
* Get path to cached .css file
*
* @return string
*/
protected function cacheName($fname)
{
return $this->join($this->cacheDir, md5($fname) . '.css');
}
/**
* Get path to meta data
*
* @return string
*/
protected function metadataName($out)
{
return $out . '.meta';
}
/**
* Determine whether .scss file needs to be re-compiled.
*
* @param string $out Output path
* @param string $etag ETag
*
* @return boolean True if compile required.
*/
protected function needsCompile($out, &$etag)
{
if (! is_file($out)) {
return true;
}
$mtime = filemtime($out);
$metadataName = $this->metadataName($out);
if (is_readable($metadataName)) {
$metadata = unserialize(file_get_contents($metadataName));
foreach ($metadata['imports'] as $import => $originalMtime) {
$currentMtime = filemtime($import);
if ($currentMtime !== $originalMtime || $currentMtime > $mtime) {
return true;
}
}
$metaVars = crc32(serialize($this->scss->getVariables()));
if ($metaVars !== $metadata['vars']) {
return true;
}
$etag = $metadata['etag'];
return false;
}
return true;
}
/**
* Get If-Modified-Since header from client request
*
* @return string|null
*/
protected function getIfModifiedSinceHeader()
{
$modifiedSince = null;
if (isset($_SERVER['HTTP_IF_MODIFIED_SINCE'])) {
$modifiedSince = $_SERVER['HTTP_IF_MODIFIED_SINCE'];
if (false !== ($semicolonPos = strpos($modifiedSince, ';'))) {
$modifiedSince = substr($modifiedSince, 0, $semicolonPos);
}
}
return $modifiedSince;
}
/**
* Get If-None-Match header from client request
*
* @return string|null
*/
protected function getIfNoneMatchHeader()
{
$noneMatch = null;
if (isset($_SERVER['HTTP_IF_NONE_MATCH'])) {
$noneMatch = $_SERVER['HTTP_IF_NONE_MATCH'];
}
return $noneMatch;
}
/**
* Compile .scss file
*
* @param string $in Input path (.scss)
* @param string $out Output path (.css)
*
* @return array
*/
protected function compile($in, $out)
{
$start = microtime(true);
$css = $this->scss->compile(file_get_contents($in), $in);
$elapsed = round((microtime(true) - $start), 4);
$v = Version::VERSION;
$t = gmdate('r');
$css = "/* compiled by scssphp $v on $t (${elapsed}s) */\n\n" . $css;
$etag = md5($css);
file_put_contents($out, $css);
file_put_contents(
$this->metadataName($out),
serialize([
'etag' => $etag,
'imports' => $this->scss->getParsedFiles(),
'vars' => crc32(serialize($this->scss->getVariables())),
])
);
return [$css, $etag];
}
/**
* Format error as a pseudo-element in CSS
*
* @param \Exception $error
*
* @return string
*/
protected function createErrorCSS(\Exception $error)
{
$message = str_replace(
["'", "\n"],
["\\'", "\\A"],
$error->getfile() . ":\n\n" . $error->getMessage()
);
return "body { display: none !important; }
html:after {
background: white;
color: black;
content: '$message';
display: block !important;
font-family: mono;
padding: 1em;
white-space: pre;
}";
}
/**
* Render errors as a pseudo-element within valid CSS, displaying the errors on any
* page that includes this CSS.
*
* @param boolean $show
*/
public function showErrorsAsCSS($show = true)
{
$this->showErrorsAsCSS = $show;
}
/**
* Compile .scss file
*
* @param string $in Input file (.scss)
* @param string $out Output file (.css) optional
*
* @return string|bool
*
* @throws \ScssPhp\ScssPhp\Exception\ServerException
*/
public function compileFile($in, $out = null)
{
if (! is_readable($in)) {
throw new ServerException('load error: failed to find ' . $in);
}
$pi = pathinfo($in);
$this->scss->addImportPath($pi['dirname'] . '/');
$compiled = $this->scss->compile(file_get_contents($in), $in);
if ($out !== null) {
return file_put_contents($out, $compiled);
}
return $compiled;
}
/**
* Check if file need compiling
*
* @param string $in Input file (.scss)
* @param string $out Output file (.css)
*
* @return bool
*/
public function checkedCompile($in, $out)
{
if (! is_file($out) || filemtime($in) > filemtime($out)) {
$this->compileFile($in, $out);
return true;
}
return false;
}
/**
* Compile requested scss and serve css. Outputs HTTP response.
*
* @param string $salt Prefix a string to the filename for creating the cache name hash
*/
public function serve($salt = '')
{
$protocol = isset($_SERVER['SERVER_PROTOCOL'])
? $_SERVER['SERVER_PROTOCOL']
: 'HTTP/1.0';
if ($input = $this->findInput()) {
$output = $this->cacheName($salt . $input);
$etag = $noneMatch = trim($this->getIfNoneMatchHeader(), '"');
if ($this->needsCompile($output, $etag)) {
try {
list($css, $etag) = $this->compile($input, $output);
$lastModified = gmdate('r', filemtime($output));
header('Last-Modified: ' . $lastModified);
header('Content-type: text/css');
header('ETag: "' . $etag . '"');
echo $css;
} catch (\Exception $e) {
if ($this->showErrorsAsCSS) {
header('Content-type: text/css');
echo $this->createErrorCSS($e);
} else {
header($protocol . ' 500 Internal Server Error');
header('Content-type: text/plain');
echo 'Parse error: ' . $e->getMessage() . "\n";
}
}
return;
}
header('X-SCSS-Cache: true');
header('Content-type: text/css');
header('ETag: "' . $etag . '"');
if ($etag === $noneMatch) {
header($protocol . ' 304 Not Modified');
return;
}
$modifiedSince = $this->getIfModifiedSinceHeader();
$mtime = filemtime($output);
if (strtotime($modifiedSince) === $mtime) {
header($protocol . ' 304 Not Modified');
return;
}
$lastModified = gmdate('r', $mtime);
header('Last-Modified: ' . $lastModified);
echo file_get_contents($output);
return;
}
header($protocol . ' 404 Not Found');
header('Content-type: text/plain');
$v = Version::VERSION;
echo "/* INPUT NOT FOUND scss $v */\n";
}
/**
* Based on explicit input/output files does a full change check on cache before compiling.
*
* @param string $in
* @param string $out
* @param boolean $force
*
* @return string Compiled CSS results
*
* @throws \ScssPhp\ScssPhp\Exception\ServerException
*/
public function checkedCachedCompile($in, $out, $force = false)
{
if (! is_file($in) || ! is_readable($in)) {
throw new ServerException('Invalid or unreadable input file specified.');
}
if (is_dir($out) || ! is_writable(file_exists($out) ? $out : dirname($out))) {
throw new ServerException('Invalid or unwritable output file specified.');
}
if ($force || $this->needsCompile($out, $etag)) {
list($css, $etag) = $this->compile($in, $out);
} else {
$css = file_get_contents($out);
}
return $css;
}
/**
* Execute scssphp on a .scss file or a scssphp cache structure
*
* The scssphp cache structure contains information about a specific
* scss file having been parsed. It can be used as a hint for future
* calls to determine whether or not a rebuild is required.
*
* The cache structure contains two important keys that may be used
* externally:
*
* compiled: The final compiled CSS
* updated: The time (in seconds) the CSS was last compiled
*
* The cache structure is a plain-ol' PHP associative array and can
* be serialized and unserialized without a hitch.
*
* @param mixed $in Input
* @param boolean $force Force rebuild?
*
* @return array scssphp cache structure
*/
public function cachedCompile($in, $force = false)
{
// assume no root
$root = null;
if (is_string($in)) {
$root = $in;
} elseif (is_array($in) and isset($in['root'])) {
if ($force or ! isset($in['files'])) {
// If we are forcing a recompile or if for some reason the
// structure does not contain any file information we should
// specify the root to trigger a rebuild.
$root = $in['root'];
} elseif (isset($in['files']) and is_array($in['files'])) {
foreach ($in['files'] as $fname => $ftime) {
if (! file_exists($fname) or filemtime($fname) > $ftime) {
// One of the files we knew about previously has changed
// so we should look at our incoming root again.
$root = $in['root'];
break;
}
}
}
} else {
// TODO: Throw an exception? We got neither a string nor something
// that looks like a compatible lessphp cache structure.
return null;
}
if ($root !== null) {
// If we have a root value which means we should rebuild.
$out = [];
$out['root'] = $root;
$out['compiled'] = $this->compileFile($root);
$out['files'] = $this->scss->getParsedFiles();
$out['updated'] = time();
return $out;
} else {
// No changes, pass back the structure
// we were given initially.
return $in;
}
}
/**
* Constructor
*
* @param string $dir Root directory to .scss files
* @param string $cacheDir Cache directory
* @param \ScssPhp\ScssPhp\Compiler|null $scss SCSS compiler instance
*/
public function __construct($dir, $cacheDir = null, $scss = null)
{
$this->dir = $dir;
if (! isset($cacheDir)) {
$cacheDir = $this->join($dir, 'scss_cache');
}
$this->cacheDir = $cacheDir;
if (! is_dir($this->cacheDir)) {
throw new ServerException('Cache directory doesn\'t exist: ' . $cacheDir);
}
if (! isset($scss)) {
$scss = new Compiler();
$scss->setImportPaths($this->dir);
}
$this->scss = $scss;
$this->showErrorsAsCSS = false;
date_default_timezone_set('UTC');
}
}