From 8908a6bcd7d1c6b812ecb12b2213d6f6598fd619 Mon Sep 17 00:00:00 2001 From: Nico Haase Date: Sat, 6 Apr 2013 12:48:00 +0200 Subject: [PATCH] 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 --- model/Image.php | 59 ++++++++++++++---- tasks/FlushGeneratedImagesTask.php | 44 ------------- tasks/RegenerateCachedImagesTask.php | 44 +++++++++++++ tests/forms/HtmlEditorFieldTest.php | 41 +++++++++++- tests/forms/HtmlEditorFieldTest.yml | 4 +- .../images/HTMLEditorFieldTest_example.jpg | Bin 0 -> 8081 bytes tests/model/ImageTest.php | 10 ++- tests/model/ImageTest.yml | 2 +- 8 files changed, 139 insertions(+), 65 deletions(-) delete mode 100644 tasks/FlushGeneratedImagesTask.php create mode 100644 tasks/RegenerateCachedImagesTask.php create mode 100644 tests/forms/images/HTMLEditorFieldTest_example.jpg diff --git a/model/Image.php b/model/Image.php index b8c6ca9ae..7835ab15f 100644 --- a/model/Image.php +++ b/model/Image.php @@ -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{$generateFuncs})(?P\d*)x(?P\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; } diff --git a/tasks/FlushGeneratedImagesTask.php b/tasks/FlushGeneratedImagesTask.php deleted file mode 100644 index bde953071..000000000 --- a/tasks/FlushGeneratedImagesTask.php +++ /dev/null @@ -1,44 +0,0 @@ -deleteFormattedImages()) { - $removedItems += $deleted; - } - - $processedImages++; - } - - echo "Removed $removedItems generated images from $processedImages Image objects stored in the Database."; - } - -} diff --git a/tasks/RegenerateCachedImagesTask.php b/tasks/RegenerateCachedImagesTask.php new file mode 100644 index 000000000..971b1fc6d --- /dev/null +++ b/tasks/RegenerateCachedImagesTask.php @@ -0,0 +1,44 @@ +regenerateFormattedImages()) { + $regeneratedImages += $generated; + } + + $processedImages++; + } + + echo "Regenerated $regeneratedImages cached images from $processedImages Image objects stored in the Database."; + } + +} diff --git a/tests/forms/HtmlEditorFieldTest.php b/tests/forms/HtmlEditorFieldTest.php index dccda3861..0cf065261 100644 --- a/tests/forms/HtmlEditorFieldTest.php +++ b/tests/forms/HtmlEditorFieldTest.php @@ -41,7 +41,7 @@ class HtmlEditorFieldTest extends FunctionalTest { $obj = new HtmlEditorFieldTest_Object(); $editor = new HtmlEditorField('Content'); - $editor->setValue(''); + $editor->setValue(''); $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('foo'); + $editor->setValue('foo'); $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(''); + $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' ); } diff --git a/tests/forms/HtmlEditorFieldTest.yml b/tests/forms/HtmlEditorFieldTest.yml index 2c001d219..a68017f1b 100644 --- a/tests/forms/HtmlEditorFieldTest.yml +++ b/tests/forms/HtmlEditorFieldTest.yml @@ -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: diff --git a/tests/forms/images/HTMLEditorFieldTest_example.jpg b/tests/forms/images/HTMLEditorFieldTest_example.jpg new file mode 100644 index 0000000000000000000000000000000000000000..b22caa10a53c359bd4a1a911d799f1cf211695d5 GIT binary patch literal 8081 zcmeGhYj{&dc5c$7X`8kwZ2=J>q!w70Hm@daBc(Lyb7`RV0gAe89ye(q$qo13v;{u} z5z!TqRoKPHil7Mcfe+**vMz#%E~^5HAhIq3<>3Q?MYO1J_srbfGzE5bcfb8*r_J0m z=bSln&Y3y$6h0CTCq=6|0zQPCPILo8NQKlCLUMp8lmi)+0LuuBX^Sak3@-zoJ~0?7 zQn@i0xTpb0LF6E`jJh@sucn44)HNcIfCj>E9c3agw2F4$7eGm|x}6|tAn1kvQh%6< z&@hekt?)8#THDad@C?_=M6`}3i*`aF>}A?HWHJ~{HuyIbX^mD}kS>*Y3Uj1nv4uhPDVyX4$d-i#41@oMS$=+%2L6Q$dOYzB+H`Y zS(NYz7%3CBQ{|wgf+7hN#z~GSS&~ATtV&5uqb?^>NG6wv8bl>ga#@m0k*riHNYk0aXFZ&y@6#{eGqiF+ zv$ty7GrYCm`z=T4f2^JT#s|@(=c@1F75=pb!@5-vK1OOeX)_CzqZ9qc z>=97s=QGv|sQK7?7k_>7sfqe`@31}Pd?zRMx6I0UwCAqlHJd;1A3uH5=NHGV`g-wF zX57lJcF;Gv7p>X+#HQyrPHLI6tL@^><(XYu-uHJ}< z&d)p4b!eBn>%}2+7aiNaw1m^VGuGArjaemYJpvjw;?FPcd+mWSvjp_Vi`=D70quTK zKy}Mj&*+?ScG9`Ot?0TSpswo881p|`e@HkWoJt$j9k%8|11hoCIg@b6Ba}Ii znuz4r=GP2_sX-<$5o!5^rn&f7=hp`YH=mtz%o`f9;JGqV&qinqAlJYT2NptU5jGI! z$3^)_l!qdoiI5}6Hqqf|NP_XVvBvJe-?}hQOEe5)9PkrfXT%{wTbZmzny8Bmy==yxM#pk9WoTfaUD`i+b50Vd1=y$|MeMEI~I7Ibj4 z@j|1YbH)n}Htgswg!%45y*tRoDP#S7Tf9&e3RcDoU}m>yyJw1joO`kd+7}%tc?M>3 z@RC=n^)gZSXy#K~B&miCUxBj+ujI3{-sYAtU!B(=yD_MlgLHGCr%# zB>XQl;tLg)EyaRtG(V{0Oy=Eeu>@o=Vkw4)$2K;wBLnH1_O6J#g*Stc6kfl@MT zz#j<5qC{QQgr$!oIFOOK;bA~sflq@jZoQnHMBi{M45{HKD?dYEG19UK3_E_pMTVxh zi6v#skK~z<;ZTucXe5mJmq5@t)E_pgy&KuyjqJ~BBP+(r5F8t*1%41cuth`_$cq@{ zhNVf18c-|1Jp4EU!IF!ze}qGe9HGff*(1nk| zg&roP?{G!*#zKQ0jV$koxI9y6UhAe|_Ak?&-n>Pp4S36R6D&@HGvc6I1GUpxx@r2@ zX3z8~o>H%_e3W)%hpi(N3DLYu+Yt(eIa^1WjtI8_jL~|Xmayz2s=e9Spmi`T zt+f;y3Ooj@L2ES@8qGz;#l<7Ea0WN%4JN(ORA4N&nc*;Q(8iJuT4TLFTVrK)tSu;& z>0(B;x3?Fzn+qA%uQ!&KmSPzuQvq-kaMQxPtD_*yn#in9Yh23O|UkIl!hAs4tj5OVox{p1Mk*Jg!s2Mz`%j6BeN0HMRMwP=Uq1-xqwiM?x$#z!SN z(#U1<#9KW?p1Q<`q@R?_x|2Mf5^Cay9a)_4QvqRH{HY7xhQz0??PwKTbCA1m&|OTb z6a{|WlELFmLQi$;De@%tcltj*|4u)@rwIjfvY}QvRsL8Uc@9%(#ZN`=O~g}Bir z-uq!+>zw8LO2h{x3f|H1l}^27tbiWsRPIcAWbW`6Uj6dPr&njAM$M6y^gA*OZeL0J z4!tyBWch_jP)kM0;H?hnCoCBI_CYFt_SEL;5sZ8CL*JyI zU-f$Ej_l6{Y^|TN_bo!kFMTLyxX1iy*OEP=@)T%xY|yuB z-^#ds;K>W)W^YMq&n@43!~IjMH{`6G zdrD(d4SjEY>Y`h;p1EbOe|q1oYxbu`dG@n;AFsbXe3r}K@O|-?=`(lT)ZVt~M9GS6 kf8ViXsm1r#N3VNw-M1T$w$6Xs=9{#C#?A)cQ^J9N0-_>z&j0`b literal 0 HcmV?d00001 diff --git a/tests/model/ImageTest.php b/tests/model/ImageTest.php index cb9b83e44..8a794aacd 100644 --- a/tests/model/ImageTest.php +++ b/tests/model/ImageTest.php @@ -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'); } } diff --git a/tests/model/ImageTest.yml b/tests/model/ImageTest.yml index fbcdf28f6..ac1dfcaf4 100644 --- a/tests/model/ImageTest.yml +++ b/tests/model/ImageTest.yml @@ -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