Passed
Push — master ( 484f92...9dd3d0 )
by Aimeos
04:56
created

Standard::addPropertyTypes()   A

Complexity

Conditions 4
Paths 4

Size

Total Lines 15
Code Lines 8

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 4
eloc 8
nc 4
nop 1
dl 0
loc 15
rs 10
c 0
b 0
f 0
1
<?php
2
3
/**
4
 * @license LGPLv3, http://opensource.org/licenses/LGPL-3.0
5
 * @copyright Aimeos (aimeos.org), 2015-2018
6
 * @package Controller
7
 * @subpackage Common
8
 */
9
10
11
namespace Aimeos\Controller\Common\Media;
12
13
14
/**
15
 * Common media controller methods
16
 *
17
 * @package Controller
18
 * @subpackage Common
19
 */
20
class Standard
21
	implements \Aimeos\Controller\Common\Media\Iface
22
{
23
	private $context;
24
	private $types = [];
0 ignored issues
show
introduced by
The private property $types is not used, and could be removed.
Loading history...
25
26
27
	/**
28
	 * Initializes the object
29
	 *
30
	 * @param \Aimeos\MShop\Context\Item\Iface $context Context object
31
	 */
32
	public function __construct( \Aimeos\MShop\Context\Item\Iface $context )
33
	{
34
		$this->context = $context;
35
	}
36
37
38
	/**
39
	 * Stores the uploaded file and adds the references to the media item
40
	 *
41
	 * {inheritDoc}
42
	 *
43
	 * @param \Aimeos\MShop\Media\Item\Iface $item Media item to add the file references to
44
	 * @param \Psr\Http\Message\UploadedFileInterface $file Uploaded file
45
	 * @param string $fsname Name of the file system to store the files at
46
	 * @return \Aimeos\MShop\Media\Item\Iface Added media item
47
	 */
48
	public function add( \Aimeos\MShop\Media\Item\Iface $item, \Psr\Http\Message\UploadedFileInterface $file, $fsname = 'fs-media' )
49
	{
50
		$this->checkFileUpload( $file );
51
		$media = $this->getMediaFile( $file->getStream() );
52
53
		if( $media instanceof \Aimeos\MW\Media\Image\Iface )
54
		{
55
			$item = $this->addImages( $item, $media, md5( $file->getClientFilename() ), $fsname );
56
		}
57
		else
58
		{
59
			$mimetype = $media->getMimeType();
60
			$filepath = $this->getFilePath( $file->getClientFilename(), 'files', $mimetype );
61
62
			$this->store( $filepath, $media->save(), $fsname );
63
			$item->setUrl( $filepath )->setPreviews( [1 => $this->getMimeIcon( $mimetype )] )->setMimeType( $mimetype );
0 ignored issues
show
Bug introduced by
The method setPreviews() does not exist on Aimeos\MShop\Media\Item\Iface. Did you maybe mean setPreview()? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

63
			$item->setUrl( $filepath )->/** @scrutinizer ignore-call */ setPreviews( [1 => $this->getMimeIcon( $mimetype )] )->setMimeType( $mimetype );

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
64
		}
65
66
		return $item->setLabel( $item->getLabel() ?: basename( $file->getClientFilename() ) );
67
	}
68
69
70
	/**
71
	 * Copies the media item and the referenced files
72
	 *
73
	 * @param \Aimeos\MShop\Media\Item\Iface $item Media item whose files should be copied
74
	 * @param string $fsname Name of the file system to delete the files from
75
	 * @return \Aimeos\MShop\Media\Item\Iface Copied media item with new files
76
	 */
77
	public function copy( \Aimeos\MShop\Media\Item\Iface $item, $fsname = 'fs-media' )
78
	{
79
		$manager = \Aimeos\MShop::create( $this->context, 'media' );
80
81
		$search = $manager->createSearch()->setSlice( 0, 1 );
82
		$search->setConditions( $search->compare( '==', 'media.url', $item->getUrl() ) );
83
84
		if( count( $manager->searchItems( $search ) ) > 0 ) {
85
			return $item;
86
		}
87
88
		$fs = $this->context->getFilesystemManager()->get( $fsname );
89
		$previews = $item->getPreviews();
90
		$path = $item->getUrl();
91
92
		if( $fs->has( $path ) )
93
		{
94
			$newPath = $this->getFilePath( $path, 'files', $item->getMimeType() );
95
			$fs->copy( $path, $newPath );
96
			$item->setUrl( $newPath );
97
		}
98
99
		foreach( $previews as $size => $preview )
100
		{
101
			if( $fs->has( $preview ) )
102
			{
103
				try
104
				{
105
					$newPath = $this->getFilePath( $preview, 'preview', pathinfo( $preview, PATHINFO_EXTENSION ) );
106
					$fs->copy( $preview, $newPath );
107
					$previews[$size] = $newPath;
108
				}
109
				catch( \Aimeos\MW\Filesystem\Exception $e ) {} // mime icons can't be copied
110
			}
111
		}
112
113
		return $item->setPreviews( $previews );
114
	}
115
116
117
	/**
118
	 * Deletes the files of the media item
119
	 *
120
	 * {inheritDoc}
121
	 *
122
	 * @param \Aimeos\MShop\Media\Item\Iface $item Media item whose files should be deleted
123
	 * @param string $fsname Name of the file system to delete the files from
124
	 */
125
	public function delete( \Aimeos\MShop\Media\Item\Iface $item, $fsname = 'fs-media' )
126
	{
127
		$manager = \Aimeos\MShop::create( $this->context, 'media' );
128
		$search = $manager->createSearch()->setSlice( 0, 2 );
129
		$search->setConditions( $search->compare( '==', 'media.url', $item->getUrl() ) );
130
131
		if( count( $manager->searchItems( $search ) ) > 1 ) {
132
			return $item->setUrl( '' )->setPreview( '' );
133
		}
134
135
		$fs = $this->context->getFilesystemManager()->get( $fsname );
136
		$path = $item->getUrl();
137
138
		if( $path !== '' && $fs->has( $path ) ) {
139
			$fs->rm( $path );
140
		}
141
142
		foreach( $item->getPreviews() as $preview )
143
		{
144
			try
145
			{
146
				if( $preview !== '' && $fs->has( $preview ) ) {
147
					$fs->rm( $preview );
148
				}
149
			}
150
			catch( \Exception $e ) { ; } // Can be a mime icon with relative path
151
		}
152
153
		return $item->setUrl( '' )->setPreviews( [] )->deletePropertyItems( $item->getPropertyItems() );
154
	}
155
156
157
	/**
158
	 * Rescales the files (original and preview) referenced by the media item
159
	 *
160
	 * The height/width configuration for scaling and which one should be scaled is used from
161
	 * - controller/common/media/standard/<files|preview>/maxheight
162
	 * - controller/common/media/standard/<files|preview>/maxwidth
163
	 * - controller/common/media/standard/<files|preview>/scale
164
	 *
165
	 * @param \Aimeos\MShop\Media\Item\Iface $item Media item whose files should be scaled
166
	 * @param string $fsname Name of the file system to rescale the files from
167
	 * @return \Aimeos\MShop\Media\Item\Iface Rescaled media item
168
	 */
169
	public function scale( \Aimeos\MShop\Media\Item\Iface $item, $fsname = 'fs-media' )
170
	{
171
		$path = $item->getUrl();
172
		$media = $this->getMediaFile( $this->getFileContent( $path, $fsname ) );
173
174
		if( !( $media instanceof \Aimeos\MW\Media\Image\Iface ) ) {
175
			return $item;
176
		}
177
178
		return $this->addImages( $item, $media, $path, $fsname );
179
	}
180
181
182
	/**
183
	 * Adds original image and preview images to the media item
184
	 *
185
	 * @param \Aimeos\MShop\Media\Item\Iface $item Media item which will contains the image URLs afterwards
186
	 * @param \Aimeos\MW\Media\Image\Iface $media Image object to scale
187
	 * @param string $path Path to the file or URL, empty or random for uploaded files
188
	 * @param string $fsname File system name the file is located at
189
	 * @return \Aimeos\MShop\Media\Item\Iface Updated media item with URLs
190
	 */
191
	protected function addImages( \Aimeos\MShop\Media\Item\Iface $item, \Aimeos\MW\Media\Image\Iface $media, $path, $fsname )
192
	{
193
		$mime = $this->getMimeType( $media, 'files' );
194
		$mediaFile = $this->scaleImage( $media, 'files' );
195
196
		// Don't overwrite original files that are stored in linked directories
197
		$filepath = ( strncmp( $path, 'files/', 6 ) ? $this->getFilePath( $path, 'files', $mime ) : $path );
198
199
		$this->store( $filepath, $mediaFile->save( null, $mime ), $fsname );
200
		$item = $item->setUrl( $filepath )->setMimeType( $mime );
201
		unset( $mediaFile );
202
203
204
		$previews = [];
205
		$mediaFiles = $this->createPreviews( $media );
206
		$mime = $this->getMimeType( $media, 'preview' );
207
		$manager = \Aimeos\MShop::create( $this->context, 'media' );
0 ignored issues
show
Unused Code introduced by
The assignment to $manager is dead and can be removed.
Loading history...
208
209
		foreach( $mediaFiles as $type => $mediaFile )
210
		{
211
			// Don't try to overwrite mime icons that are stored in another directory
212
			$filepath = ( strncmp( $path, 'preview/', 8 ) ? $this->getFilePath( $path, 'preview', $mime ) : $path );
213
214
			$this->store( $filepath, $mediaFile->save( null, $mime ), $fsname );
215
			$previews[$mediaFile->getWidth()] = $filepath;
216
			unset( $mediaFile );
217
		}
218
219
		return $item->setPreviews( $previews );
220
	}
221
222
223
	/**
224
	 * Checks if an error during upload occured
225
	 *
226
	 * @param \Psr\Http\Message\UploadedFileInterface $file Uploaded file
227
	 * @throws \Aimeos\Controller\Common\Exception If an error occured during upload
228
	 */
229
	protected function checkFileUpload( \Psr\Http\Message\UploadedFileInterface $file )
230
	{
231
		if( $file->getError() !== UPLOAD_ERR_OK )
232
		{
233
			switch( $file->getError() )
234
			{
235
				case UPLOAD_ERR_INI_SIZE:
236
				case UPLOAD_ERR_FORM_SIZE:
237
					throw new \Aimeos\Controller\Common\Exception( 'The uploaded file exceeds the max. allowed filesize' );
238
				case UPLOAD_ERR_PARTIAL:
239
					throw new \Aimeos\Controller\Common\Exception( 'The uploaded file was only partially uploaded' );
240
				case UPLOAD_ERR_NO_FILE:
241
					throw new \Aimeos\Controller\Common\Exception( 'No file was uploaded' );
242
				case UPLOAD_ERR_NO_TMP_DIR:
243
					throw new \Aimeos\Controller\Common\Exception( 'Temporary folder is missing' );
244
				case UPLOAD_ERR_CANT_WRITE:
245
					throw new \Aimeos\Controller\Common\Exception( 'Failed to write file to disk' );
246
				case UPLOAD_ERR_EXTENSION:
247
					throw new \Aimeos\Controller\Common\Exception( 'File upload stopped by extension' );
248
				default:
249
					throw new \Aimeos\Controller\Common\Exception( 'Unknown upload error' );
250
			}
251
		}
252
	}
253
254
255
	/**
256
	 * Creates scaled images according to the configuration settings
257
	 *
258
	 * @param \Aimeos\MW\Media\Image\Iface $media Media object
259
	 * @return \Aimeos\MW\Media\Image\Iface[] Associative list of image width as keys and scaled media object as values
260
	 */
261
	protected function createPreviews( \Aimeos\MW\Media\Image\Iface $media )
262
	{
263
		$list = [];
264
		$config = $this->context->getConfig();
265
266
		foreach( $config->get( 'controller/common/media/standard/previews', [] ) as $entry )
267
		{
268
			$maxwidth = ( isset( $entry['maxwidth'] ) ? (int) $entry['maxwidth'] : null );
269
			$maxheight = ( isset( $entry['maxheight'] ) ? (int) $entry['maxheight'] : null );
270
			$fit = ( isset( $entry['force-size'] ) ? (bool) $entry['force-size'] : false );
271
272
			if( $maxheight || $maxwidth )
0 ignored issues
show
Bug Best Practice introduced by
The expression $maxheight of type integer|null is loosely compared to true; this is ambiguous if the integer can be 0. You might want to explicitly use !== null instead.

In PHP, under loose comparison (like ==, or !=, or switch conditions), values of different types might be equal.

For integer values, zero is a special case, in particular the following results might be unexpected:

0   == false // true
0   == null  // true
123 == false // false
123 == null  // false

// It is often better to use strict comparison
0 === false // false
0 === null  // false
Loading history...
Bug Best Practice introduced by
The expression $maxwidth of type integer|null is loosely compared to true; this is ambiguous if the integer can be 0. You might want to explicitly use !== null instead.

In PHP, under loose comparison (like ==, or !=, or switch conditions), values of different types might be equal.

For integer values, zero is a special case, in particular the following results might be unexpected:

0   == false // true
0   == null  // true
123 == false // false
123 == null  // false

// It is often better to use strict comparison
0 === false // false
0 === null  // false
Loading history...
273
			{
274
				$image = $media->scale( $maxwidth, $maxheight, !$fit );
275
				$list[$image->getWidth()] = $image;
276
			}
277
		}
278
279
		if( empty( $list ) )
280
		{
281
			$maxwidth = $config->get( 'controller/common/media/standard/preview/maxwidth', null );
282
			$maxheight = $config->get( 'controller/common/media/standard/preview/maxheight', null );
283
			$fit = (bool) $config->get( 'controller/common/media/standard/preview/force-size', false );
284
285
			if( $maxheight || $maxwidth )
286
			{
287
				$image = $media->scale( $maxwidth, $maxheight, !$fit );
288
				$list[$image->getWidth()] = $image;
289
			}
290
		}
291
292
		return $list;
293
	}
294
295
296
	/**
297
	 * Returns the context item
298
	 *
299
	 * @return \Aimeos\MShop\Context\Item\Iface Context item
300
	 */
301
	protected function getContext()
302
	{
303
		return $this->context;
304
	}
305
306
307
	/**
308
	 * Returns the file content of the file or URL
309
	 *
310
	 * @param string $path Path to the file or URL
311
	 * @param string $fsname File system name the file is located at
312
	 * @return string File content
313
	 * @throws \Aimeos\Controller\Common\Exception If no file is found
314
	 */
315
	protected function getFileContent( $path, $fsname )
316
	{
317
		if( $path !== '' )
318
		{
319
			if( preg_match( '#^[a-zA-Z]{1,10}://#', $path ) === 1 )
320
			{
321
				if( ( $content = @file_get_contents( $path ) ) === false )
322
				{
323
					$msg = sprintf( 'Downloading file "%1$s" failed', $path );
324
					throw new \Aimeos\Controller\Common\Exception( $msg );
325
				}
326
327
				return $content;
328
			}
329
330
			$fs = $this->context->getFilesystemManager()->get( $fsname );
331
332
			if( $fs->has( $path ) !== false ) {
333
				return $fs->read( $path );
334
			}
335
		}
336
337
		throw new \Aimeos\Controller\Common\Exception( sprintf( 'File "%1$s" not found', $path ) );
338
	}
339
340
341
	/**
342
	 * Creates a new file path from the given arguments and random values
343
	 *
344
	 * @param string $filename Original file name, can contain the path as well
345
	 * @param string $type File type, i.e. "files" or "preview"
346
	 * @param string $mimeext Mime type or extension of the file
347
	 * @return string New file name including the file path
348
	 */
349
	protected function getFilePath( $filename, $type, $mimeext )
350
	{
351
		/** controller/common/media/standard/extensions
352
		 * Available files extensions for mime types of uploaded files
353
		 *
354
		 * Uploaded files should have the right file extension (e.g. ".jpg" for
355
		 * JPEG images) so files are recognized correctly if downloaded by users.
356
		 * The extension of the uploaded file can't be trusted and only its mime
357
		 * type can be determined automatically. This configuration setting
358
		 * provides the file extensions for the configured mime types. You can
359
		 * add more mime type / file extension combinations if required.
360
		 *
361
		 * @param array Associative list of mime types as keys and file extensions as values
362
		 * @since 2018.04
363
		 * @category Developer
364
		 */
365
		$list = $this->context->getConfig()->get( 'controller/common/media/standard/extensions', [] );
366
367
		$filename = md5( $filename . getmypid() . microtime( true ) );
368
		$ext = isset( $list[$mimeext] ) ? '.' . $list[$mimeext] : ( ctype_alpha( $mimeext ) ? '.' . $mimeext : '' );
369
370
		return "${type}/${filename[0]}/${filename[1]}/${filename}${ext}";
371
	}
372
373
374
	/**
375
	 * Returns the media object for the given file name
376
	 *
377
	 * @param string $file Path to the file or file content
378
	 * @return \Aimeos\MW\Media\Iface Media object
379
	 */
380
	protected function getMediaFile( $file )
381
	{
382
		/** controller/common/media/standard/options
383
		 * Options used for processing the uploaded media files
384
		 *
385
		 * When uploading a file, a preview image for that file is generated if
386
		 * possible (especially for images). You can configure certain options
387
		 * for the generated images, namely the implementation of the scaling
388
		 * algorithm and the quality of the resulting images with
389
		 *
390
		 *  array(
391
		 *  	'image' => array(
392
		 *  		'name' => 'Imagick',
393
		 *  		'quality' => 75,
394
		 *  	)
395
		 *  )
396
		 *
397
		 * @param array Multi-dimendional list of configuration options
398
		 * @since 2016.01
399
		 * @category Developer
400
		 * @category User
401
		 */
402
		$options = $this->context->getConfig()->get( 'controller/common/media/standard/options', [] );
403
404
		return \Aimeos\MW\Media\Factory::get( $file, $options );
405
	}
406
407
408
	/**
409
	 * Returns the relative path to the mime icon for the given mime type.
410
	 *
411
	 * @param string $mimetype Mime type like "image/png"
412
	 * @return string Relative path to the mime icon
413
	 */
414
	protected function getMimeIcon( $mimetype )
415
	{
416
		$config = $this->context->getConfig();
417
418
		/** controller/common/media/standard/mimeicon/directory
419
		 * Directory that contains the icons for the different mime types
420
		 *
421
		 * If no preview image can be generated from an uploaded file, an icon
422
		 * for its mime type is displayed instead. The directory for the mime
423
		 * icons is structured by the general mime type (e.g. "image") as
424
		 * sub-directory and the specific name of the mime type (e.g. "jpeg")
425
		 * as file name.
426
		 *
427
		 * Avoid leading and trailing slashes for the upload directory string!
428
		 *
429
		 * @param string Path or URL to the base directory
430
		 * @since 2016.01
431
		 * @category Developer
432
		 */
433
		if( ( $mimedir = $config->get( 'controller/common/media/standard/mimeicon/directory' ) ) == null ) {
434
			return '';
435
		}
436
437
		/** controller/common/media/standard/mimeicon/extension
438
		 * File extension of the mime icon images
439
		 *
440
		 * If you would like to use different mime icons that are available in
441
		 * another file format, you have to change the file extension for the
442
		 * mime icons to the actual ones.
443
		 *
444
		 * Note: The configured file extension needs a leading dot!
445
		 *
446
		 * @param string File extension including a leading dot, e.g ".jpg"
447
		 * @since 2016.01
448
		 * @category Developer
449
		 */
450
		$ext = $config->get( 'controller/common/media/standard/mimeicon/extension', '.png' );
451
452
		return $mimedir . DIRECTORY_SEPARATOR . $mimetype . $ext;
453
	}
454
455
456
	/**
457
	 * Returns the mime type for the new image
458
	 *
459
	 * @param \Aimeos\MW\Media\Image\Iface $media Media object
460
	 * @param string $type Type of the image like "preview" or "files"
461
	 * @return string New mime type
462
	 * @throws \Aimeos\Controller\Common\Exception If no mime types are configured
463
	 */
464
	protected function getMimeType( \Aimeos\MW\Media\Image\Iface $media, $type )
465
	{
466
		$mimetype = $media->getMimetype();
467
		$config = $this->context->getConfig();
468
469
		/** controller/common/media/standard/files/allowedtypes
470
		 * A list of image mime types that are allowed for uploaded image files
471
		 *
472
		 * The list of allowed image types must be explicitly configured for the
473
		 * uploaded image files. Trying to upload and store an image file not
474
		 * available in the list of allowed mime types will result in an exception.
475
		 *
476
		 * @param array List of image mime types
477
		 * @since 2016.01
478
		 * @category Developer
479
		 * @category User
480
		 */
481
482
		/** controller/common/media/standard/preview/allowedtypes
483
		 * A list of image mime types that are allowed for preview image files
484
		 *
485
		 * The list of allowed image types must be explicitly configured for the
486
		 * preview image files. Trying to create a preview image whose mime type
487
		 * is not available in the list of allowed mime types will result in an
488
		 * exception.
489
		 *
490
		 * @param array List of image mime types
491
		 * @since 2016.01
492
		 * @category Developer
493
		 * @category User
494
		 */
495
		$default = array( 'image/jpeg', 'image/png', 'image/gif', 'image/svg+xml' );
496
		$allowed = $config->get( 'controller/common/media/standard/' . $type . '/allowedtypes', $default );
497
498
		if( in_array( $mimetype, $allowed ) === false )
499
		{
500
			if( ( $defaulttype = reset( $allowed ) ) === false ) {
501
				throw new \Aimeos\Controller\Common\Exception( sprintf( 'No allowed image types configured for "%1$s"', $type ) );
502
			}
503
504
			return $defaulttype;
505
		}
506
507
		return $mimetype;
508
	}
509
510
511
	/**
512
	 * Scales the image according to the configuration settings
513
	 *
514
	 * @param \Aimeos\MW\Media\Image\Iface $media Media object
515
	 * @param string $type Type of the image like "preview" or "files"
516
	 * @return \Aimeos\MW\Media\Image\Iface Scaled media object
517
	 * @deprecated 2020.01 Will scale main file only
518
	 */
519
	protected function scaleImage( \Aimeos\MW\Media\Image\Iface $media, $type )
520
	{
521
		$config = $this->context->getConfig();
522
523
		/** controller/common/media/standard/files/maxwidth
524
		 * Maximum width of the uploaded images
525
		 *
526
		 * The uploaded image files are scaled down if their width exceeds the
527
		 * configured width of pixels. If the image width in smaller than the
528
		 * configured one, no scaling happens. In case of a value of null or if
529
		 * no configuration for that option is available, the image width isn't
530
		 * scaled at all.
531
		 *
532
		 * The width/height ratio of the image is always kept.
533
		 *
534
		 * @param integer|null Width in pixel or null for no scaling
535
		 * @since 2016.01
536
		 * @category Developer
537
		 * @category User
538
		 */
539
540
		/** controller/common/media/standard/preview/maxwidth
541
		 * Maximum width of the preview images
542
		 *
543
		 * The preview image files are created with the configured width in
544
		 * pixel. If the original image width in smaller than the one configured
545
		 * for the preview image, the width of the original image is used. In
546
		 * case of a value of null or if no configuration for that option is
547
		 * available, the width of the preview image is the same as the width of
548
		 * the original image.
549
		 *
550
		 * The width/height ratio of the preview image is always the same as for
551
		 * the original image.
552
		 *
553
		 * @param integer|null Width in pixel or null for no scaling
554
		 * @since 2016.01
555
		 * @category Developer
556
		 * @category User
557
		 */
558
		$maxwidth = $config->get( 'controller/common/media/standard/' . $type . '/maxwidth', null );
559
560
		/** controller/common/media/standard/files/maxheight
561
		 * Maximum height of the uploaded images
562
		 *
563
		 * The uploaded image files are scaled down if their height exceeds the
564
		 * configured height of pixels. If the image height in smaller than the
565
		 * configured one, no scaling happens. In case of a value of null or if
566
		 * no configuration for that option is available, the image width isn't
567
		 * scaled at all.
568
		 *
569
		 * The width/height ratio of the image is always kept.
570
		 *
571
		 * @param integer|null Height in pixel or null for no scaling
572
		 * @since 2016.01
573
		 * @category Developer
574
		 * @category User
575
		 */
576
577
		/** controller/common/media/standard/preview/maxheight
578
		 * Maximum height of the preview images
579
		 *
580
		 * The preview image files are created with the configured width in
581
		 * pixel. If the original image height in smaller than the one configured
582
		 * for the preview image, the height of the original image is used. In
583
		 * case of a value of null or if no configuration for that option is
584
		 * available, the height of the preview image is the same as the height
585
		 * of the original image.
586
		 *
587
		 * The width/height ratio of the preview image is always the same as for
588
		 * the original image.
589
		 *
590
		 * @param integer|null Height in pixel or null for no scaling
591
		 * @since 2016.01
592
		 * @category Developer
593
		 * @category User
594
		 */
595
		$maxheight = $config->get( 'controller/common/media/standard/' . $type . '/maxheight', null );
596
597
		/** controller/common/media/standard/files/force-size
598
		 * Force exact image size for the uploaded images
599
		 *
600
		 * This configuration forces the output image to have exact the width
601
		 * and height specified in maxwidth / maxheight configuration options
602
		 * by scaling and cropping the original image.
603
		 *
604
		 * @param integer True to enable the feature, false to disable it
605
		 * @since 2018.10
606
		 * @category Developer
607
		 * @category User
608
		 * @see controller/common/media/standard/preview/force-size
609
		 */
610
611
		/** controller/common/media/standard/preview/force-size
612
		 * Force exact image size for the preview images
613
		 *
614
		 * This configuration forces the output image to have exact the width
615
		 * and height specified in maxwidth / maxheight configuration options
616
		 * by scaling and cropping the original image.
617
		 *
618
		 * @param integer True to enable the feature, false to disable it
619
		 * @since 2018.10
620
		 * @category Developer
621
		 * @category User
622
		 * @see controller/common/media/standard/files/force-size
623
		 */
624
		$fit = (bool) $config->get( 'controller/common/media/standard/' . $type . '/force-size', false );
625
626
		if( $maxheight || $maxwidth ) {
627
			return $media->scale( $maxwidth, $maxheight, !$fit );
628
		}
629
630
		return $media;
631
	}
632
633
634
	/**
635
	 * Stores the file content
636
	 *
637
	 * @param string $filepath Path of the new file
638
	 * @param string $content File content
639
	 * @param string $fsname Name of the file system to store the files at
640
	 * @return \Aimeos\Controller\Common\Media\Iface Self object for fluent interface
641
	 */
642
	protected function store( $filepath, $content, $fsname )
643
	{
644
		$this->context->getFilesystemManager()->get( $fsname )->write( $filepath, $content );
645
		return $this;
646
	}
647
648
649
	/**
650
	 * Stores the file content
651
	 *
652
	 * @param string $content File content
653
	 * @param string $fsname Name of the file system to store the files at
654
	 * @param string $filepath Path of the new file
655
	 * @param string $oldpath Path of the old file
656
	 * @deprecated 2020.01
657
	 */
658
	protected function storeFile( $content, $fsname, $filepath, $oldpath )
659
	{
660
		$fs = $this->context->getFilesystemManager()->get( $fsname );
661
662
		try
663
		{
664
			if( $oldpath !== '' && $oldpath !== $filepath && $fs->has( $oldpath ) ) {
665
				$fs->rm( $oldpath );
666
			}
667
		}
668
		catch( \Aimeos\MW\Filesystem\Exception $e ) {} // continue if removing file fails
669
670
		$fs->write( $filepath, $content );
671
	}
672
}
673