+ /**
+ * Tries to resize image to wanted maximum size
+ *
+ * @param Image $image Image instance
+ * @return Image|null Image instance on success, null on error
+ */
+ private static function fitImageSize(Image $image)
+ {
+ $max_length = DI::config()->get('system', 'max_image_length');
+ if ($max_length > 0) {
+ $image->scaleDown($max_length);
+ Logger::info('File upload: Scaling picture to new size', ['max-length' => $max_length]);
+ }
+
+ $filesize = strlen($image->asString());
+ $width = $image->getWidth();
+ $height = $image->getHeight();
+
+ $maximagesize = Strings::getBytesFromShorthand(DI::config()->get('system', 'maximagesize'));
+
+ if ($maximagesize && ($filesize > $maximagesize)) {
+ // Scale down to multiples of 640 until the maximum size isn't exceeded anymore
+ foreach ([5120, 2560, 1280, 640] as $pixels) {
+ if (($filesize > $maximagesize) && (max($width, $height) > $pixels)) {
+ Logger::info('Resize', ['size' => $filesize, 'width' => $width, 'height' => $height, 'max' => $maximagesize, 'pixels' => $pixels]);
+ $image->scaleDown($pixels);
+ $filesize = strlen($image->asString());
+ $width = $image->getWidth();
+ $height = $image->getHeight();
+ }
+ }
+ if ($filesize > $maximagesize) {
+ Logger::notice('Image size is too big', ['size' => $filesize, 'max' => $maximagesize]);
+ return null;
+ }
+ }
+
+ return $image;
+ }
+
+ /**
+ * Fetches image from URL and returns an array with instance and local file name
+ *
+ * @param string $image_url URL to image
+ * @return array With: 'image' and 'filename' fields or empty array on error
+ */
+ private static function loadImageFromURL(string $image_url): array
+ {
+ $filename = basename($image_url);
+ if (!empty($image_url)) {
+ $ret = DI::httpClient()->get($image_url, HttpClientAccept::IMAGE);
+ Logger::debug('Got picture', ['Content-Type' => $ret->getHeader('Content-Type'), 'url' => $image_url]);
+ $img_str = $ret->getBody();
+ $type = $ret->getContentType();
+ } else {
+ $img_str = '';
+ $type = '';
+ }
+
+ if (empty($img_str)) {
+ Logger::notice('Empty content');
+ return [];
+ }
+
+ $type = Images::getMimeTypeByData($img_str, $image_url, $type);
+
+ $image = new Image($img_str, $type);
+
+ $image = self::fitImageSize($image);
+ if (empty($image)) {
+ return [];
+ }
+
+ return ['image' => $image, 'filename' => $filename];
+ }
+
+ /**
+ * Inserts uploaded image into database and removes local temporary file
+ *
+ * @param array $files File array
+ * @return array With 'image' for Image instance and 'filename' for local file name or empty array on error
+ */
+ private static function uploadImage(array $files): array