Completed
Push — php7-support ( ec5817...a3ee17 )
by Sam
09:34 queued 03:20
created

ImageTest::testMultipleGenerateManipulationCalls()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 16
Code Lines 12

Duplication

Lines 0
Ratio 0 %
Metric Value
dl 0
loc 16
rs 9.4285
cc 1
eloc 12
nc 1
nop 0
1
<?php
2
3
use Filesystem as SS_Filesystem;
4
use League\Flysystem\Filesystem;
0 ignored issues
show
Bug introduced by
This use statement conflicts with another class in this namespace, Filesystem.

Let’s assume that you have a directory layout like this:

.
|-- OtherDir
|   |-- Bar.php
|   `-- Foo.php
`-- SomeDir
    `-- Foo.php

and let’s assume the following content of Bar.php:

// Bar.php
namespace OtherDir;

use SomeDir\Foo; // This now conflicts the class OtherDir\Foo

If both files OtherDir/Foo.php and SomeDir/Foo.php are loaded in the same runtime, you will see a PHP error such as the following:

PHP Fatal error:  Cannot use SomeDir\Foo as Foo because the name is already in use in OtherDir/Foo.php

However, as OtherDir/Foo.php does not necessarily have to be loaded and the error is only triggered if it is loaded before OtherDir/Bar.php, this problem might go unnoticed for a while. In order to prevent this error from surfacing, you must import the namespace with a different alias:

// Bar.php
namespace OtherDir;

use SomeDir\Foo as SomeDirFoo; // There is no conflict anymore.
Loading history...
5
use SilverStripe\Filesystem\Flysystem\AssetAdapter;
6
use SilverStripe\Filesystem\Flysystem\FlysystemAssetStore;
7
use SilverStripe\Filesystem\Flysystem\FlysystemUrlPlugin;
8
9
/**
10
 * @package framework
11
 * @subpackage tests
12
 */
13
class ImageTest extends SapphireTest {
14
15
	protected static $fixture_file = 'ImageTest.yml';
16
17
	public function setUp() {
18
		parent::setUp();
19
20
		// Execute specific subclass
21
		if(get_class($this) == "ImageTest") {
22
			$this->markTestSkipped(sprintf('Skipping %s ', get_class($this)));
23
			return;
24
		}
25
26
		// Set backend root to /ImageTest
27
		AssetStoreTest_SpyStore::activate('ImageTest');
28
29
		// Copy test images for each of the fixture references
30
		$files = File::get()->exclude('ClassName', 'Folder');
31
		foreach($files as $image) {
32
			$filePath = AssetStoreTest_SpyStore::getLocalPath($image); // Only correct for test asset store
33
			$sourcePath = BASE_PATH . '/framework/tests/model/testimages/' . $image->Name;
34
			if(!file_exists($filePath)) {
35
				SS_Filesystem::makeFolder(dirname($filePath));
36
				if (!copy($sourcePath, $filePath)) {
37
					user_error('Failed to copy test images', E_USER_ERROR);
38
				}
39
			}
40
		}
41
	}
42
43
	public function tearDown() {
44
		AssetStoreTest_SpyStore::reset();
45
		parent::tearDown();
46
	}
47
48 View Code Duplication
	public function testGetTagWithTitle() {
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
49
		Config::inst()->update('SilverStripe\Filesystem\Storage\DBFile', 'force_resample', false);
50
51
		$image = $this->objFromFixture('Image', 'imageWithTitle');
52
		$expected = '<img src="/assets/ImageTest/folder/444065542b/test-image.png" alt="This is a image Title" />';
53
		$actual = trim($image->getTag());
54
55
		$this->assertEquals($expected, $actual);
56
	}
57
58 View Code Duplication
	public function testGetTagWithoutTitle() {
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
59
		Config::inst()->update('SilverStripe\Filesystem\Storage\DBFile', 'force_resample', false);
60
61
		$image = $this->objFromFixture('Image', 'imageWithoutTitle');
62
		$expected = '<img src="/assets/ImageTest/folder/444065542b/test-image.png" alt="test image" />';
63
		$actual = trim($image->getTag());
64
65
		$this->assertEquals($expected, $actual);
66
	}
67
68 View Code Duplication
	public function testGetTagWithoutTitleContainingDots() {
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
69
		Config::inst()->update('SilverStripe\Filesystem\Storage\DBFile', 'force_resample', false);
70
71
		$image = $this->objFromFixture('Image', 'imageWithoutTitleContainingDots');
72
		$expected = '<img src="/assets/ImageTest/folder/46affab704/test.image.with.dots.png" alt="test.image.with.dots" />';
73
		$actual = trim($image->getTag());
74
75
		$this->assertEquals($expected, $actual);
76
	}
77
78
	/**
79
	 * Tests that multiple image manipulations may be performed on a single Image
80
	 */
81
	public function testMultipleGenerateManipulationCalls() {
82
		$image = $this->objFromFixture('Image', 'imageWithoutTitle');
83
84
		$imageFirst = $image->ScaleWidth(200);
85
		$this->assertNotNull($imageFirst);
86
		$expected = 200;
87
		$actual = $imageFirst->getWidth();
88
89
		$this->assertEquals($expected, $actual);
90
91
		$imageSecond = $imageFirst->ScaleHeight(100);
92
		$this->assertNotNull($imageSecond);
93
		$expected = 100;
94
		$actual = $imageSecond->getHeight();
95
		$this->assertEquals($expected, $actual);
96
	}
97
98
	/**
99
	 * Tests that image manipulations that do not affect the resulting dimensions
100
	 * of the output image do not resample the file.
101
	 */
102
	public function testReluctanceToResampling() {
103
		$image = $this->objFromFixture('Image', 'imageWithoutTitle');
104
		$this->assertTrue($image->isSize(300, 300));
105
106
		// Set width to 300 pixels
107
		$imageScaleWidth = $image->ScaleWidth(300);
108
		$this->assertEquals($imageScaleWidth->getWidth(), 300);
109
		$this->assertEquals($image->Filename, $imageScaleWidth->Filename);
110
111
		// Set height to 300 pixels
112
		$imageScaleHeight = $image->ScaleHeight(300);
113
		$this->assertEquals($imageScaleHeight->getHeight(), 300);
114
		$this->assertEquals($image->Filename, $imageScaleHeight->Filename);
115
116
		// Crop image to 300 x 300
117
		$imageCropped = $image->Fill(300, 300);
118
		$this->assertTrue($imageCropped->isSize(300, 300));
119
		$this->assertEquals($image->Filename, $imageCropped->Filename);
120
121
		// Resize (padded) to 300 x 300
122
		$imageSized = $image->Pad(300, 300);
123
		$this->assertTrue($imageSized->isSize(300, 300));
124
		$this->assertEquals($image->Filename, $imageSized->Filename);
125
126
		// Padded image 300 x 300 (same as above)
127
		$imagePadded = $image->Pad(300, 300);
128
		$this->assertTrue($imagePadded->isSize(300, 300));
129
		$this->assertEquals($image->Filename, $imagePadded->Filename);
130
131
		// Resized (stretched) to 300 x 300
132
		$imageStretched = $image->ResizedImage(300, 300);
133
		$this->assertTrue($imageStretched->isSize(300, 300));
134
		$this->assertEquals($image->Filename, $imageStretched->Filename);
135
136
		// Fit (various options)
137
		$imageFit = $image->Fit(300, 600);
138
		$this->assertTrue($imageFit->isSize(300, 300));
139
		$this->assertEquals($image->Filename, $imageFit->Filename);
140
		$imageFit = $image->Fit(600, 300);
141
		$this->assertTrue($imageFit->isSize(300, 300));
142
		$this->assertEquals($image->Filename, $imageFit->Filename);
143
		$imageFit = $image->Fit(300, 300);
144
		$this->assertTrue($imageFit->isSize(300, 300));
145
		$this->assertEquals($image->Filename, $imageFit->Filename);
146
	}
147
148
	/**
149
	 * Tests that a URL to a resampled image is provided when force_resample is
150
	 * set to true, if the resampled file is smaller than the original.
151
	 */
152
	public function testForceResample() {
153
		$imageHQ = $this->objFromFixture('Image', 'highQualityJPEG');
154
		$imageHQR = $imageHQ->Resampled();
155
		$imageLQ = $this->objFromFixture('Image', 'lowQualityJPEG');
156
		$imageLQR = $imageLQ->Resampled();
157
158
		// Test resampled file is served when force_resample = true
159
		Config::inst()->update('SilverStripe\Filesystem\Storage\DBFile', 'force_resample', true);
160
		$this->assertLessThan($imageHQ->getAbsoluteSize(), $imageHQR->getAbsoluteSize(), 'Resampled image is smaller than original');
161
		$this->assertEquals($imageHQ->getURL(), $imageHQR->getSourceURL(), 'Path to a resampled image was returned by getURL()');
162
163
		// Test original file is served when force_resample = true but original file is low quality
164
		$this->assertGreaterThanOrEqual($imageLQ->getAbsoluteSize(), $imageLQR->getAbsoluteSize(), 'Resampled image is larger or same size as original');
165
		$this->assertNotEquals($imageLQ->getURL(), $imageLQR->getSourceURL(), 'Path to the original image file was returned by getURL()');
166
167
		// Test original file is served when force_resample = false
168
		Config::inst()->update('SilverStripe\Filesystem\Storage\DBFile', 'force_resample', false);
169
		$this->assertNotEquals($imageHQ->getURL(), $imageHQR->getSourceURL(), 'Path to the original image file was returned by getURL()');
170
	}
171
172
	public function testImageResize() {
173
		$image = $this->objFromFixture('Image', 'imageWithoutTitle');
174
		$this->assertTrue($image->isSize(300, 300));
175
176
		// Test normal resize
177
		$resized = $image->Pad(150, 100);
178
		$this->assertTrue($resized->isSize(150, 100));
179
180
		// Test cropped resize
181
		$cropped = $image->Fill(100, 200);
182
		$this->assertTrue($cropped->isSize(100, 200));
183
184
		// Test padded resize
185
		$padded = $image->Pad(200, 100);
186
		$this->assertTrue($padded->isSize(200, 100));
187
188
		// Test Fit
189
		$ratio = $image->Fit(80, 160);
190
		$this->assertTrue($ratio->isSize(80, 80));
191
192
		// Test FitMax
193
		$fitMaxDn = $image->FitMax(200, 100);
194
		$this->assertTrue($fitMaxDn->isSize(100, 100));
195
		$fitMaxUp = $image->FitMax(500, 400);
196
		$this->assertTrue($fitMaxUp->isSize(300, 300));
197
198
		//Test ScaleMax
199
		$scaleMaxWDn = $image->ScaleMaxWidth(200);
200
		$this->assertTrue($scaleMaxWDn->isSize(200, 200));
201
		$scaleMaxWUp = $image->ScaleMaxWidth(400);
202
		$this->assertTrue($scaleMaxWUp->isSize(300, 300));
203
		$scaleMaxHDn = $image->ScaleMaxHeight(200);
204
		$this->assertTrue($scaleMaxHDn->isSize(200, 200));
205
		$scaleMaxHUp = $image->ScaleMaxHeight(400);
206
		$this->assertTrue($scaleMaxHUp->isSize(300, 300));
207
208
		// Test FillMax
209
		$cropMaxDn = $image->FillMax(200, 100);
210
		$this->assertTrue($cropMaxDn->isSize(200, 100));
211
		$cropMaxUp = $image->FillMax(400, 200);
212
		$this->assertTrue($cropMaxUp->isSize(300, 150));
213
214
		// Test Clip
215
		$clipWDn = $image->CropWidth(200);
216
		$this->assertTrue($clipWDn->isSize(200, 300));
217
		$clipWUp = $image->CropWidth(400);
218
		$this->assertTrue($clipWUp->isSize(300, 300));
219
		$clipHDn = $image->CropHeight(200);
220
		$this->assertTrue($clipHDn->isSize(300, 200));
221
		$clipHUp = $image->CropHeight(400);
222
		$this->assertTrue($clipHUp->isSize(300, 300));
223
	}
224
225
	/**
226
	 * @expectedException InvalidArgumentException
227
	 */
228
	public function testGenerateImageWithInvalidParameters() {
229
		$image = $this->objFromFixture('Image', 'imageWithoutTitle');
230
		$image->ScaleHeight('String');
231
		$image->Pad(600,600,'XXXXXX');
232
	}
233
234
	public function testCacheFilename() {
235
		$image = $this->objFromFixture('Image', 'imageWithoutTitle');
236
		$imageFirst = $image->Pad(200,200,'CCCCCC');
237
		$imageFilename = $imageFirst->getURL();
238
			// Encoding of the arguments is duplicated from cacheFilename
239
		$neededPart = 'Pad' . Convert::base64url_encode(array(200,200,'CCCCCC'));
240
		$this->assertContains($neededPart, $imageFilename, 'Filename for cached image is correctly generated');
241
	}
242
243
	/**
244
	 * Test that propertes from the source Image are inherited by resampled images
245
	 */
246
	public function testPropertyInheritance() {
247
		$testString = 'This is a test';
248
		$origImage = $this->objFromFixture('Image', 'imageWithTitle');
249
		$origImage->TestProperty = $testString;
0 ignored issues
show
Documentation introduced by
The property TestProperty does not exist on object<DataObject>. Since you implemented __set, maybe consider adding a @property annotation.

Since your code implements the magic setter _set, this function will be called for any write access on an undefined variable. You can add the @property annotation to your class or interface to document the existence of this variable.

<?php

/**
 * @property int $x
 * @property int $y
 * @property string $text
 */
class MyLabel
{
    private $properties;

    private $allowedProperties = array('x', 'y', 'text');

    public function __get($name)
    {
        if (isset($properties[$name]) && in_array($name, $this->allowedProperties)) {
            return $properties[$name];
        } else {
            return null;
        }
    }

    public function __set($name, $value)
    {
        if (in_array($name, $this->allowedProperties)) {
            $properties[$name] = $value;
        } else {
            throw new \LogicException("Property $name is not defined.");
        }
    }

}

Since the property has write access only, you can use the @property-write annotation instead.

Of course, you may also just have mistyped another name, in which case you should fix the error.

See also the PhpDoc documentation for @property.

Loading history...
250
		$resampled = $origImage->ScaleWidth(10);
251
		$this->assertEquals($resampled->TestProperty, $testString);
252
		$resampled2 = $resampled->ScaleWidth(5);
253
		$this->assertEquals($resampled2->TestProperty, $testString);
254
	}
255
256 View Code Duplication
	public function testShortcodeHandlerFallsBackToFileProperties() {
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
257
		$image = $this->objFromFixture('Image', 'imageWithTitle');
258
		$parser = new ShortcodeParser();
259
		$parser->register('image', array('Image', 'handle_shortcode'));
260
261
		$this->assertEquals(
262
			sprintf(
263
				'<img src="%s" alt="%s">',
264
				$image->Link(),
265
				$image->Title
266
			),
267
			$parser->parse(sprintf('[image id=%d]', $image->ID))
268
		);
269
	}
270
271 View Code Duplication
	public function testShortcodeHandlerUsesShortcodeProperties() {
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
272
		$image = $this->objFromFixture('Image', 'imageWithTitle');
273
		$parser = new ShortcodeParser();
274
		$parser->register('image', array('Image', 'handle_shortcode'));
275
276
		$this->assertEquals(
277
			sprintf(
278
				'<img src="%s" alt="Alt content" title="Title content">',
279
				$image->Link()
280
			),
281
			$parser->parse(sprintf(
282
				'[image id="%d" alt="Alt content" title="Title content"]',
283
				$image->ID
284
			))
285
		);
286
	}
287
288 View Code Duplication
	public function testShortcodeHandlerAddsDefaultAttributes() {
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
289
		$image = $this->objFromFixture('Image', 'imageWithoutTitle');
290
		$parser = new ShortcodeParser();
291
		$parser->register('image', array('Image', 'handle_shortcode'));
292
293
		$this->assertEquals(
294
			sprintf(
295
				'<img src="%s" alt="%s">',
296
				$image->Link(),
297
				$image->Title
298
			),
299
			$parser->parse(sprintf(
300
				'[image id="%d"]',
301
				$image->ID
302
			))
303
		);
304
	}
305
}
306