PageRenderTime 25ms CodeModel.GetById 12ms RepoModel.GetById 0ms app.codeStats 0ms

/tests/model/ImageTest.php

http://github.com/silverstripe/sapphire
PHP | 305 lines | 211 code | 51 blank | 43 comment | 4 complexity | e7c24ccb4e2c28d34ff475afa4488f1a MD5 | raw file
Possible License(s): BSD-3-Clause, MIT, CC-BY-3.0, GPL-2.0, AGPL-1.0, LGPL-2.1
  1. <?php
  2. use Filesystem as SS_Filesystem;
  3. use League\Flysystem\Filesystem;
  4. use SilverStripe\Filesystem\Flysystem\AssetAdapter;
  5. use SilverStripe\Filesystem\Flysystem\FlysystemAssetStore;
  6. use SilverStripe\Filesystem\Flysystem\FlysystemUrlPlugin;
  7. /**
  8. * @package framework
  9. * @subpackage tests
  10. */
  11. class ImageTest extends SapphireTest {
  12. protected static $fixture_file = 'ImageTest.yml';
  13. public function setUp() {
  14. parent::setUp();
  15. // Execute specific subclass
  16. if(get_class($this) == "ImageTest") {
  17. $this->markTestSkipped(sprintf('Skipping %s ', get_class($this)));
  18. return;
  19. }
  20. // Set backend root to /ImageTest
  21. AssetStoreTest_SpyStore::activate('ImageTest');
  22. // Copy test images for each of the fixture references
  23. $files = File::get()->exclude('ClassName', 'Folder');
  24. foreach($files as $image) {
  25. $filePath = AssetStoreTest_SpyStore::getLocalPath($image); // Only correct for test asset store
  26. $sourcePath = BASE_PATH . '/framework/tests/model/testimages/' . $image->Name;
  27. if(!file_exists($filePath)) {
  28. SS_Filesystem::makeFolder(dirname($filePath));
  29. if (!copy($sourcePath, $filePath)) {
  30. user_error('Failed to copy test images', E_USER_ERROR);
  31. }
  32. }
  33. }
  34. }
  35. public function tearDown() {
  36. AssetStoreTest_SpyStore::reset();
  37. parent::tearDown();
  38. }
  39. public function testGetTagWithTitle() {
  40. Config::inst()->update('SilverStripe\Filesystem\Storage\DBFile', 'force_resample', false);
  41. $image = $this->objFromFixture('Image', 'imageWithTitle');
  42. $expected = '<img src="/assets/ImageTest/folder/444065542b/test-image.png" alt="This is a image Title" />';
  43. $actual = trim($image->getTag());
  44. $this->assertEquals($expected, $actual);
  45. }
  46. public function testGetTagWithoutTitle() {
  47. Config::inst()->update('SilverStripe\Filesystem\Storage\DBFile', 'force_resample', false);
  48. $image = $this->objFromFixture('Image', 'imageWithoutTitle');
  49. $expected = '<img src="/assets/ImageTest/folder/444065542b/test-image.png" alt="test image" />';
  50. $actual = trim($image->getTag());
  51. $this->assertEquals($expected, $actual);
  52. }
  53. public function testGetTagWithoutTitleContainingDots() {
  54. Config::inst()->update('SilverStripe\Filesystem\Storage\DBFile', 'force_resample', false);
  55. $image = $this->objFromFixture('Image', 'imageWithoutTitleContainingDots');
  56. $expected = '<img src="/assets/ImageTest/folder/46affab704/test.image.with.dots.png" alt="test.image.with.dots" />';
  57. $actual = trim($image->getTag());
  58. $this->assertEquals($expected, $actual);
  59. }
  60. /**
  61. * Tests that multiple image manipulations may be performed on a single Image
  62. */
  63. public function testMultipleGenerateManipulationCalls() {
  64. $image = $this->objFromFixture('Image', 'imageWithoutTitle');
  65. $imageFirst = $image->ScaleWidth(200);
  66. $this->assertNotNull($imageFirst);
  67. $expected = 200;
  68. $actual = $imageFirst->getWidth();
  69. $this->assertEquals($expected, $actual);
  70. $imageSecond = $imageFirst->ScaleHeight(100);
  71. $this->assertNotNull($imageSecond);
  72. $expected = 100;
  73. $actual = $imageSecond->getHeight();
  74. $this->assertEquals($expected, $actual);
  75. }
  76. /**
  77. * Tests that image manipulations that do not affect the resulting dimensions
  78. * of the output image do not resample the file.
  79. */
  80. public function testReluctanceToResampling() {
  81. $image = $this->objFromFixture('Image', 'imageWithoutTitle');
  82. $this->assertTrue($image->isSize(300, 300));
  83. // Set width to 300 pixels
  84. $imageScaleWidth = $image->ScaleWidth(300);
  85. $this->assertEquals($imageScaleWidth->getWidth(), 300);
  86. $this->assertEquals($image->Filename, $imageScaleWidth->Filename);
  87. // Set height to 300 pixels
  88. $imageScaleHeight = $image->ScaleHeight(300);
  89. $this->assertEquals($imageScaleHeight->getHeight(), 300);
  90. $this->assertEquals($image->Filename, $imageScaleHeight->Filename);
  91. // Crop image to 300 x 300
  92. $imageCropped = $image->Fill(300, 300);
  93. $this->assertTrue($imageCropped->isSize(300, 300));
  94. $this->assertEquals($image->Filename, $imageCropped->Filename);
  95. // Resize (padded) to 300 x 300
  96. $imageSized = $image->Pad(300, 300);
  97. $this->assertTrue($imageSized->isSize(300, 300));
  98. $this->assertEquals($image->Filename, $imageSized->Filename);
  99. // Padded image 300 x 300 (same as above)
  100. $imagePadded = $image->Pad(300, 300);
  101. $this->assertTrue($imagePadded->isSize(300, 300));
  102. $this->assertEquals($image->Filename, $imagePadded->Filename);
  103. // Resized (stretched) to 300 x 300
  104. $imageStretched = $image->ResizedImage(300, 300);
  105. $this->assertTrue($imageStretched->isSize(300, 300));
  106. $this->assertEquals($image->Filename, $imageStretched->Filename);
  107. // Fit (various options)
  108. $imageFit = $image->Fit(300, 600);
  109. $this->assertTrue($imageFit->isSize(300, 300));
  110. $this->assertEquals($image->Filename, $imageFit->Filename);
  111. $imageFit = $image->Fit(600, 300);
  112. $this->assertTrue($imageFit->isSize(300, 300));
  113. $this->assertEquals($image->Filename, $imageFit->Filename);
  114. $imageFit = $image->Fit(300, 300);
  115. $this->assertTrue($imageFit->isSize(300, 300));
  116. $this->assertEquals($image->Filename, $imageFit->Filename);
  117. }
  118. /**
  119. * Tests that a URL to a resampled image is provided when force_resample is
  120. * set to true, if the resampled file is smaller than the original.
  121. */
  122. public function testForceResample() {
  123. $imageHQ = $this->objFromFixture('Image', 'highQualityJPEG');
  124. $imageHQR = $imageHQ->Resampled();
  125. $imageLQ = $this->objFromFixture('Image', 'lowQualityJPEG');
  126. $imageLQR = $imageLQ->Resampled();
  127. // Test resampled file is served when force_resample = true
  128. Config::inst()->update('SilverStripe\Filesystem\Storage\DBFile', 'force_resample', true);
  129. $this->assertLessThan($imageHQ->getAbsoluteSize(), $imageHQR->getAbsoluteSize(), 'Resampled image is smaller than original');
  130. $this->assertEquals($imageHQ->getURL(), $imageHQR->getSourceURL(), 'Path to a resampled image was returned by getURL()');
  131. // Test original file is served when force_resample = true but original file is low quality
  132. $this->assertGreaterThanOrEqual($imageLQ->getAbsoluteSize(), $imageLQR->getAbsoluteSize(), 'Resampled image is larger or same size as original');
  133. $this->assertNotEquals($imageLQ->getURL(), $imageLQR->getSourceURL(), 'Path to the original image file was returned by getURL()');
  134. // Test original file is served when force_resample = false
  135. Config::inst()->update('SilverStripe\Filesystem\Storage\DBFile', 'force_resample', false);
  136. $this->assertNotEquals($imageHQ->getURL(), $imageHQR->getSourceURL(), 'Path to the original image file was returned by getURL()');
  137. }
  138. public function testImageResize() {
  139. $image = $this->objFromFixture('Image', 'imageWithoutTitle');
  140. $this->assertTrue($image->isSize(300, 300));
  141. // Test normal resize
  142. $resized = $image->Pad(150, 100);
  143. $this->assertTrue($resized->isSize(150, 100));
  144. // Test cropped resize
  145. $cropped = $image->Fill(100, 200);
  146. $this->assertTrue($cropped->isSize(100, 200));
  147. // Test padded resize
  148. $padded = $image->Pad(200, 100);
  149. $this->assertTrue($padded->isSize(200, 100));
  150. // Test Fit
  151. $ratio = $image->Fit(80, 160);
  152. $this->assertTrue($ratio->isSize(80, 80));
  153. // Test FitMax
  154. $fitMaxDn = $image->FitMax(200, 100);
  155. $this->assertTrue($fitMaxDn->isSize(100, 100));
  156. $fitMaxUp = $image->FitMax(500, 400);
  157. $this->assertTrue($fitMaxUp->isSize(300, 300));
  158. //Test ScaleMax
  159. $scaleMaxWDn = $image->ScaleMaxWidth(200);
  160. $this->assertTrue($scaleMaxWDn->isSize(200, 200));
  161. $scaleMaxWUp = $image->ScaleMaxWidth(400);
  162. $this->assertTrue($scaleMaxWUp->isSize(300, 300));
  163. $scaleMaxHDn = $image->ScaleMaxHeight(200);
  164. $this->assertTrue($scaleMaxHDn->isSize(200, 200));
  165. $scaleMaxHUp = $image->ScaleMaxHeight(400);
  166. $this->assertTrue($scaleMaxHUp->isSize(300, 300));
  167. // Test FillMax
  168. $cropMaxDn = $image->FillMax(200, 100);
  169. $this->assertTrue($cropMaxDn->isSize(200, 100));
  170. $cropMaxUp = $image->FillMax(400, 200);
  171. $this->assertTrue($cropMaxUp->isSize(300, 150));
  172. // Test Clip
  173. $clipWDn = $image->CropWidth(200);
  174. $this->assertTrue($clipWDn->isSize(200, 300));
  175. $clipWUp = $image->CropWidth(400);
  176. $this->assertTrue($clipWUp->isSize(300, 300));
  177. $clipHDn = $image->CropHeight(200);
  178. $this->assertTrue($clipHDn->isSize(300, 200));
  179. $clipHUp = $image->CropHeight(400);
  180. $this->assertTrue($clipHUp->isSize(300, 300));
  181. }
  182. /**
  183. * @expectedException InvalidArgumentException
  184. */
  185. public function testGenerateImageWithInvalidParameters() {
  186. $image = $this->objFromFixture('Image', 'imageWithoutTitle');
  187. $image->ScaleHeight('String');
  188. $image->Pad(600,600,'XXXXXX');
  189. }
  190. public function testCacheFilename() {
  191. $image = $this->objFromFixture('Image', 'imageWithoutTitle');
  192. $imageFirst = $image->Pad(200,200,'CCCCCC');
  193. $imageFilename = $imageFirst->getURL();
  194. // Encoding of the arguments is duplicated from cacheFilename
  195. $neededPart = 'Pad' . Convert::base64url_encode(array(200,200,'CCCCCC'));
  196. $this->assertContains($neededPart, $imageFilename, 'Filename for cached image is correctly generated');
  197. }
  198. /**
  199. * Test that propertes from the source Image are inherited by resampled images
  200. */
  201. public function testPropertyInheritance() {
  202. $testString = 'This is a test';
  203. $origImage = $this->objFromFixture('Image', 'imageWithTitle');
  204. $origImage->TestProperty = $testString;
  205. $resampled = $origImage->ScaleWidth(10);
  206. $this->assertEquals($resampled->TestProperty, $testString);
  207. $resampled2 = $resampled->ScaleWidth(5);
  208. $this->assertEquals($resampled2->TestProperty, $testString);
  209. }
  210. public function testShortcodeHandlerFallsBackToFileProperties() {
  211. $image = $this->objFromFixture('Image', 'imageWithTitle');
  212. $parser = new ShortcodeParser();
  213. $parser->register('image', array('Image', 'handle_shortcode'));
  214. $this->assertEquals(
  215. sprintf(
  216. '<img src="%s" alt="%s">',
  217. $image->Link(),
  218. $image->Title
  219. ),
  220. $parser->parse(sprintf('[image id=%d]', $image->ID))
  221. );
  222. }
  223. public function testShortcodeHandlerUsesShortcodeProperties() {
  224. $image = $this->objFromFixture('Image', 'imageWithTitle');
  225. $parser = new ShortcodeParser();
  226. $parser->register('image', array('Image', 'handle_shortcode'));
  227. $this->assertEquals(
  228. sprintf(
  229. '<img src="%s" alt="Alt content" title="Title content">',
  230. $image->Link()
  231. ),
  232. $parser->parse(sprintf(
  233. '[image id="%d" alt="Alt content" title="Title content"]',
  234. $image->ID
  235. ))
  236. );
  237. }
  238. public function testShortcodeHandlerAddsDefaultAttributes() {
  239. $image = $this->objFromFixture('Image', 'imageWithoutTitle');
  240. $parser = new ShortcodeParser();
  241. $parser->register('image', array('Image', 'handle_shortcode'));
  242. $this->assertEquals(
  243. sprintf(
  244. '<img src="%s" alt="%s">',
  245. $image->Link(),
  246. $image->Title
  247. ),
  248. $parser->parse(sprintf(
  249. '[image id="%d"]',
  250. $image->ID
  251. ))
  252. );
  253. }
  254. }