Browse Source

Added `yii\web\AssetConverter::$isOutdatedCallback` allowing custom check for outdated asset conversion result

tags/3.0.0-alpha1
Klimov Paul 7 years ago
parent
commit
fdd761d6cb
  1. 1
      framework/CHANGELOG.md
  2. 72
      framework/web/AssetConverter.php
  3. 68
      tests/framework/web/AssetConverterTest.php

1
framework/CHANGELOG.md

@ -22,6 +22,7 @@ Yii Framework 2 Change Log
- Enh #13702: Added support for PSR-3 'Logger' (klimov-paul)
- Enh #13706: 'Profiler' layer extracted (klimov-paul)
- Enh #15410: Added serialization abstraction layer under `yii\serialize\*` namespace (klimov-paul)
- Enh #608: Added `yii\web\AssetConverter::$isOutdatedCallback` allowing custom check for outdated asset conversion result (klimov-paul)
- Enh: Objects `yii\helpers\ReplaceArrayValue`, `yii\helpers\UnsetArrayValue` now support restoring after being exported with `var_export()` function (silverfire)
- Chg: Removed methods marked as deprecated in 2.0.x (samdark)
- Chg #8452: Packages 'captcha', 'jquery', 'rest', 'mssql' and 'oracle' have been extracted into extensions (klimov-paul)

72
framework/web/AssetConverter.php

@ -49,6 +49,42 @@ class AssetConverter extends Component implements AssetConverterInterface
* significantly degrade the performance.
*/
public $forceConvert = false;
/**
* @var callable a PHP callback, which should be invoked to check whether asset conversion result is outdated.
* It will be invoked only if conversion target file exists and its modification time is older then the one of source file.
* Callback should match following signature:
*
* ```php
* function (string $basePath, string $sourceFile, string $targetFile, string $sourceExtension, string $targetExtension) : bool
* ```
*
* where $basePath is the asset source directory; $sourceFile is the asset source file path, relative to $basePath;
* $targetFile is the asset target file path, relative to $basePath; $sourceExtension is the source asset file extension
* and $targetExtension is the target asset file extension, respectively.
*
* It should return `true` is case asset should be reconverted.
* For example:
*
* ```php
* function ($basePath, $sourceFile, $targetFile, $sourceExtension, $targetExtension) {
* if (YII_ENV !== 'dev') {
* return false;
* }
*
* $resultModificationTime = @filemtime("$basePath/$result");
* foreach (FileHelper::findFiles($basePath, ['only' => ["*.{$sourceExtension}"]]) as $filename) {
* if ($resultModificationTime < @filemtime($filename)) {
* return true;
* }
* }
*
* return false;
* }
* ```
*
* @since 2.1.0
*/
public $isOutdatedCallback;
/**
@ -61,11 +97,11 @@ class AssetConverter extends Component implements AssetConverterInterface
{
$pos = strrpos($asset, '.');
if ($pos !== false) {
$ext = substr($asset, $pos + 1);
if (isset($this->commands[$ext])) {
[$ext, $command] = $this->commands[$ext];
$srcExt = substr($asset, $pos + 1);
if (isset($this->commands[$srcExt])) {
[$ext, $command] = $this->commands[$srcExt];
$result = substr($asset, 0, $pos + 1) . $ext;
if ($this->forceConvert || @filemtime("$basePath/$result") < @filemtime("$basePath/$asset")) {
if ($this->forceConvert || $this->isOutdated($basePath, $asset, $result, $srcExt, $ext)) {
$this->runCommand($command, $basePath, $asset, $result);
}
@ -77,6 +113,34 @@ class AssetConverter extends Component implements AssetConverterInterface
}
/**
* Checks whether asset convert result is outdated, and thus should be reconverted.
* @param string $basePath the directory the $asset is relative to.
* @param string $sourceFile the asset source file path, relative to [[$basePath]].
* @param string $targetFile the converted asset file path, relative to [[$basePath]].
* @param string $sourceExtension source asset file extension.
* @param string $targetExtension target asset file extension.
* @return bool whether asset is outdated or not.
* @since 2.1.0
*/
protected function isOutdated($basePath, $sourceFile, $targetFile, $sourceExtension, $targetExtension)
{
$resultModificationTime = @filemtime("$basePath/$targetFile");
if ($resultModificationTime === false || $resultModificationTime === null) {
return true;
}
if ($resultModificationTime < @filemtime("$basePath/$sourceFile")) {
return true;
}
if ($this->isOutdatedCallback === null) {
return false;
}
return call_user_func($this->isOutdatedCallback, $basePath, $sourceFile, $targetFile, $sourceExtension, $targetExtension);
}
/**
* Runs a command to convert asset files.
* @param string $command the command to run. If prefixed with an `@` it will be treated as a [path alias](guide:concept-aliases).
* @param string $basePath asset base path and command working directory

68
tests/framework/web/AssetConverterTest.php

@ -20,6 +20,9 @@ class AssetConverterTest extends \yiiunit\TestCase
*/
protected $tmpPath;
/**
* {@inheritdoc}
*/
protected function setUp()
{
parent::setUp();
@ -30,6 +33,9 @@ class AssetConverterTest extends \yiiunit\TestCase
}
}
/**
* {@inheritdoc}
*/
protected function tearDown()
{
if (is_dir($this->tmpPath)) {
@ -62,6 +68,35 @@ EOF
/**
* @depends testConvert
*/
public function testConvertOutdated()
{
$tmpPath = $this->tmpPath;
$srcFilename = $tmpPath . '/test.php';
file_put_contents($srcFilename, <<<'EOF'
<?php
echo microtime();
EOF
);
$converter = new AssetConverter();
$converter->commands['php'] = ['txt', 'php {from} > {to}'];
$converter->convert('test.php', $tmpPath);
$initialConvertTime = file_get_contents($tmpPath . '/test.txt');
usleep(1);
$converter->convert('test.php', $tmpPath);
$this->assertStringEqualsFile($tmpPath . '/test.txt', $initialConvertTime);
touch($srcFilename, time() + 1000);
$converter->convert('test.php', $tmpPath);
$this->assertNotEquals($initialConvertTime, file_get_contents($tmpPath . '/test.txt'));
}
/**
* @depends testConvertOutdated
*/
public function testForceConvert()
{
$tmpPath = $this->tmpPath;
@ -86,4 +121,37 @@ EOF
$converter->convert('test.php', $tmpPath);
$this->assertNotEquals($initialConvertTime, file_get_contents($tmpPath . '/test.txt'));
}
/**
* @depends testConvertOutdated
*/
public function testCheckOutdatedCallback()
{
$tmpPath = $this->tmpPath;
$srcFilename = $tmpPath . '/test.php';
file_put_contents($srcFilename, <<<'EOF'
<?php
echo microtime();
EOF
);
$converter = new AssetConverter();
$converter->commands['php'] = ['txt', 'php {from} > {to}'];
$converter->convert('test.php', $tmpPath);
$initialConvertTime = file_get_contents($tmpPath . '/test.txt');
$converter->isOutdatedCallback = function() {
return false;
};
$converter->convert('test.php', $tmpPath);
$this->assertStringEqualsFile($tmpPath . '/test.txt', $initialConvertTime);
$converter->isOutdatedCallback = function() {
return true;
};
$converter->convert('test.php', $tmpPath);
$this->assertNotEquals($initialConvertTime, file_get_contents($tmpPath . '/test.txt'));
}
}

Loading…
Cancel
Save