This is a fixed version for RegenerateCachedImagesTask (former FlushGeneratedImagesTask) such that it regenerates images instead of silently removing them and breaking existing pages

The pull request also contains some enhancements and fixes to the corresponding testcases.

Fixes #318
This commit is contained in:
Nico Haase 2013-04-06 12:48:00 +02:00
parent 91477617e6
commit 8908a6bcd7
8 changed files with 139 additions and 65 deletions

View File

@ -298,6 +298,8 @@ class Image extends File {
$cached = new Image_Cached($cacheFile);
// Pass through the title so the templates can use it
$cached->Title = $this->Title;
$cached->ParentID = $this->ParentID;
$cached->Parent = $this->Parent();
return $cached;
}
}
@ -312,7 +314,7 @@ class Image extends File {
public function cacheFilename($format, $arg1 = null, $arg2 = null) {
$folder = $this->ParentID ? $this->Parent()->Filename : ASSETS_DIR . "/";
$format = $format.$arg1.$arg2;
$format = $format.$arg1.'x'.$arg2;
return $folder . "_resampled/$format-" . $this->Name;
}
@ -369,14 +371,11 @@ class Image extends File {
}
/**
* Remove all of the formatted cached images for this image.
*
* @return int The number of formatted images deleted
* Generate a list of images that were generated from this image
*/
public function deleteFormattedImages() {
if(!$this->Filename) return 0;
private function getGeneratedImages() {
$generatedImages = array();
$numDeleted = 0;
$methodNames = $this->allMethodNames(true);
$cachedFiles = array();
@ -404,17 +403,53 @@ class Image extends File {
}
// All generate functions may appear any number of times in the image cache name.
$generateFuncs = implode('|', $generateFuncs);
$pattern = "/^(({$generateFuncs})\d+\-)+" . preg_quote($this->Name) . "$/i";
$pattern = "/^((?P<Generator>{$generateFuncs})(?P<Arg1>\d*)x(?P<Arg2>\d*)\-)+" . preg_quote($this->Name) . "$/i";
foreach($cachedFiles as $cfile) {
if(preg_match($pattern, $cfile)) {
if(preg_match($pattern, $cfile, $matches)) {
if(Director::fileExists($cacheDir . $cfile)) {
unlink($cacheDir . $cfile);
$numDeleted++;
$generatedImages[] = array ( 'FileName' => $cacheDir . $cfile, 'Generator' => $matches['Generator'],
'Arg1' => $matches['Arg1'], 'Arg2' => $matches['Arg2'] );
}
}
}
return $generatedImages;
}
/**
* Regenerate all of the formatted cached images for this image.
*
* @return int The number of formatted images regenerated
*/
public function regenerateFormattedImages() {
if(!$this->Filename) return 0;
$numGenerated = 0;
$generatedImages = $this->getGeneratedImages();
foreach($generatedImages as $singleImage) {
$this->generateFormattedImage($singleImage['Generator'], $singleImage['Arg1'],
$singleImage['Arg2']);
}
return $numGenerated;
}
/**
* Remove all of the formatted cached images for this image.
*
* @return int The number of formatted images deleted
*/
public function deleteFormattedImages() {
if(!$this->Filename) return 0;
$numDeleted = 0;
$generatedImages = $this->getGeneratedImages();
foreach($generatedImages as $singleImage) {
unlink($singleImage['FileName']);
$numDeleted++;
}
return $numDeleted;
}

View File

@ -1,44 +0,0 @@
<?php
/**
* Remove all cached/generated images that have been created as the result of a manipulation method being called on a
* {@link Image} object
*
* @package framework
* @subpackage filesystem
*/
class FlushGeneratedImagesTask extends BuildTask {
protected $title = 'Flush Generated Images Task';
protected $description = 'Remove all cached/generated images created as the result of an image manipulation';
/**
* Check that the user has appropriate permissions to execute this task
*/
public function init() {
if(!Director::is_cli() && !Director::isDev() && !Permission::check('ADMIN')) {
return Security::permissionFailure();
}
parent::init();
}
/**
* Actually clear out all the images
*/
public function run($request) {
$processedImages = 0;
$removedItems = 0;
if($images = DataObject::get('Image')) foreach($images as $image) {
if($deleted = $image->deleteFormattedImages()) {
$removedItems += $deleted;
}
$processedImages++;
}
echo "Removed $removedItems generated images from $processedImages Image objects stored in the Database.";
}
}

View File

@ -0,0 +1,44 @@
<?php
/**
* Regenerate all cached images that have been created as the result of a manipulation method being called on a
* {@link Image} object
*
* @package framework
* @subpackage filesystem
*/
class RegenerateCachedImagesTask extends BuildTask {
protected $title = 'Regenerate Cached Images Task';
protected $description = 'Regenerate all cached images created as the result of an image manipulation';
/**
* Check that the user has appropriate permissions to execute this task
*/
public function init() {
if(!Director::is_cli() && !Director::isDev() && !Permission::check('ADMIN')) {
return Security::permissionFailure();
}
parent::init();
}
/**
* Actually regenerate all the images
*/
public function run($request) {
$processedImages = 0;
$regeneratedImages = 0;
if($images = DataObject::get('Image')) foreach($images as $image) {
if($generated = $image->regenerateFormattedImages()) {
$regeneratedImages += $generated;
}
$processedImages++;
}
echo "Regenerated $regeneratedImages cached images from $processedImages Image objects stored in the Database.";
}
}

View File

@ -41,7 +41,7 @@ class HtmlEditorFieldTest extends FunctionalTest {
$obj = new HtmlEditorFieldTest_Object();
$editor = new HtmlEditorField('Content');
$editor->setValue('<img src="assets/example.jpg" />');
$editor->setValue('<img src="assets/HTMLEditorFieldTest_example.jpg" />');
$editor->saveInto($obj);
$parser = new CSSContentParser($obj->Content);
@ -49,15 +49,49 @@ class HtmlEditorFieldTest extends FunctionalTest {
$this->assertEquals('', (string)$xml[0]['alt'], 'Alt tags are added by default.');
$this->assertEquals('', (string)$xml[0]['title'], 'Title tags are added by default.');
$editor->setValue('<img src="assets/example.jpg" alt="foo" title="bar" />');
$editor->setValue('<img src="assets/HTMLEditorFieldTest_example.jpg" alt="foo" title="bar" />');
$editor->saveInto($obj);
$parser = new CSSContentParser($obj->Content);
$xml = $parser->getByXpath('//img');
$this->assertEquals('foo', (string)$xml[0]['alt'], 'Alt tags are preserved.');
$this->assertEquals('bar', (string)$xml[0]['title'], 'Title tags are preserved.');
$this->assertEquals(false, $obj->HasBrokenFile, 'Referenced image file exists.');
}
public function testResizedImageInsertion() {
$obj = new HtmlEditorFieldTest_Object();
$editor = new HtmlEditorField('Content');
/*
* Following stuff is neccessary to
* a) use the proper filename for the image we are referencing
* b) not confuse the "existing" filesystem by our test
*/
$imageFile = $this->objFromFixture('Image', 'example_image');
$imageFile->Filename = FRAMEWORK_DIR . '/' . $imageFile->Filename;
$origUpdateFilesystem = Config::inst()->get('File', 'update_filesystem');
Config::inst()->update('File', 'update_filesystem', false);
$imageFile->write();
Config::inst()->update('File', 'update_filesystem', $origUpdateFilesystem);
/*
* End of test bet setting
*/
$editor->setValue('<img src="assets/HTMLEditorFieldTest_example.jpg" width="10" height="20" />');
$editor->saveInto($obj);
$parser = new CSSContentParser($obj->Content);
$xml = $parser->getByXpath('//img');
$this->assertEquals('', (string)$xml[0]['alt'], 'Alt tags are added by default.');
$this->assertEquals('', (string)$xml[0]['title'], 'Title tags are added by default.');
$this->assertEquals(10, (int)$xml[0]['width'], 'Width tag of resized image is set.');
$this->assertEquals(20, (int)$xml[0]['height'], 'Height tag of resized image is set.');
$this->assertEquals('assets/_resampled/resizedimage10x20-HTMLEditorFieldTest_example.jpg', (string)$xml[0]['src'], 'Correct URL of resized image is set.');
$this->assertTrue(file_exists('assets/_resampled/resizedimage10x20-HTMLEditorFieldTest_example.jpg'), 'File for resized image exists');
$this->assertEquals(false, $obj->HasBrokenFile, 'Referenced image file exists.');
}
public function testMultiLineSaving() {
$obj = $this->objFromFixture('HtmlEditorFieldTest_Object', 'home');
$editor = new HtmlEditorField('Content');
@ -112,6 +146,7 @@ class HtmlEditorFieldTest_DummyMediaFormFieldExtension extends Extension impleme
class HtmlEditorFieldTest_Object extends DataObject implements TestOnly {
private static $db = array(
'Title' => 'Varchar',
'Content' => 'HTMLText'
'Content' => 'HTMLText',
'HasBrokenFile' => 'Boolean'
);
}

View File

@ -5,8 +5,8 @@ File:
Image:
example_image:
Name: example.jpg
Filename: folder/subfolder/example.jpg
Name: HTMLEditorFieldTest_example.jpg
Filename: tests/forms/images/HTMLEditorFieldTest_example.jpg
HtmlEditorFieldTest_Object:
home:

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.9 KiB

View File

@ -50,6 +50,9 @@ class ImageTest extends SapphireTest {
if($folder && file_exists(BASE_PATH."/$folder->Filename")) {
Filesystem::removeFolder(BASE_PATH."/$folder->Filename");
}
if($folder && file_exists(BASE_PATH."/".$folder->Filename."_resampled")) {
Filesystem::removeFolder(BASE_PATH."/".$folder->Filename."_resampled");
}
}
parent::tearDown();
@ -102,8 +105,9 @@ class ImageTest extends SapphireTest {
$image = $this->objFromFixture('Image', 'imageWithMetacharacters');
$image_generated = $image->SetWidth(200);
$p = $image_generated->getFullPath();
$this->assertTrue(file_exists($p));
$image->deleteFormattedImages();
$this->assertFalse(file_exists($p));
$this->assertTrue(file_exists($p), 'Resized image exists after creation call');
$numDeleted = $image->deleteFormattedImages();
$this->assertEquals(1, $numDeleted, 'Expected one image to be deleted, but deleted ' . $numDeleted . ' images');
$this->assertFalse(file_exists($p), 'Resized image not existing after deletion call');
}
}

View File

@ -14,5 +14,5 @@ Image:
Parent: =>Folder.folder1
imageWithMetacharacters:
Title: This is a/an image Title
Filename: assets/ImageTest/test_image).png
Filename: assets/ImageTest/test_image.png
Parent: =>Folder.folder1