summaryrefslogtreecommitdiff
path: root/app/Services/MediaFileService.php
diff options
context:
space:
mode:
authorGreg Roach <fisharebest@webtrees.net>2019-10-31 22:57:40 +0000
committerGreg Roach <fisharebest@webtrees.net>2019-10-31 23:00:35 +0000
commitd4265d07c02c7f5ca2855fe55f3ca0b73a86c7a9 (patch)
treee338de68cd9082f96056c578ad7bf7e06f1a9593 /app/Services/MediaFileService.php
parent852ede8c85e501a9df6f3c9d31e5933428e18cc2 (diff)
downloadwebtrees-d4265d07c02c7f5ca2855fe55f3ca0b73a86c7a9.tar.gz
webtrees-d4265d07c02c7f5ca2855fe55f3ca0b73a86c7a9.tar.bz2
webtrees-d4265d07c02c7f5ca2855fe55f3ca0b73a86c7a9.zip
Refactor controllers as request handlers
Diffstat (limited to 'app/Services/MediaFileService.php')
-rw-r--r--app/Services/MediaFileService.php240
1 files changed, 240 insertions, 0 deletions
diff --git a/app/Services/MediaFileService.php b/app/Services/MediaFileService.php
new file mode 100644
index 0000000000..9532562713
--- /dev/null
+++ b/app/Services/MediaFileService.php
@@ -0,0 +1,240 @@
+<?php
+
+/**
+ * webtrees: online genealogy
+ * Copyright (C) 2019 webtrees development team
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+declare(strict_types=1);
+
+namespace Fisharebest\Webtrees\Services;
+
+use Fisharebest\Webtrees\FlashMessages;
+use Fisharebest\Webtrees\GedcomTag;
+use Fisharebest\Webtrees\I18N;
+use Fisharebest\Webtrees\Tree;
+use Illuminate\Database\Capsule\Manager as DB;
+use InvalidArgumentException;
+use Psr\Http\Message\ServerRequestInterface;
+use Psr\Http\Message\UploadedFileInterface;
+use RuntimeException;
+use Symfony\Component\HttpFoundation\File\UploadedFile;
+
+use function array_combine;
+use function array_diff;
+use function array_filter;
+use function array_map;
+use function assert;
+use function intdiv;
+use function pathinfo;
+use function preg_match;
+use function sha1;
+use function sort;
+use function str_replace;
+use function strpos;
+use function strtolower;
+use function trim;
+
+use const PATHINFO_EXTENSION;
+use const UPLOAD_ERR_OK;
+
+/**
+ * Managing media files.
+ */
+class MediaFileService
+{
+ public const EDIT_RESTRICTIONS = [
+ 'locked',
+ ];
+
+ public const PRIVACY_RESTRICTIONS = [
+ 'none',
+ 'privacy',
+ 'confidential',
+ ];
+
+ /**
+ * What is the largest file a user may upload?
+ */
+ public function maxUploadFilesize(): string
+ {
+ $bytes = UploadedFile::getMaxFilesize();
+ $kb = intdiv($bytes + 1023, 1024);
+
+ return I18N::translate('%s KB', I18N::number($kb));
+ }
+
+ /**
+ * A list of key/value options for media types.
+ *
+ * @param string $current
+ *
+ * @return array
+ */
+ public function mediaTypes($current = ''): array
+ {
+ $media_types = GedcomTag::getFileFormTypes();
+
+ $media_types = ['' => ''] + [$current => $current] + $media_types;
+
+ return $media_types;
+ }
+
+ /**
+ * A list of media files not already linked to a media object.
+ *
+ * @param Tree $tree
+ *
+ * @return array
+ */
+ public function unusedFiles(Tree $tree): array
+ {
+ $used_files = DB::table('media_file')
+ ->where('m_file', '=', $tree->id())
+ ->where('multimedia_file_refn', 'NOT LIKE', 'http://%')
+ ->where('multimedia_file_refn', 'NOT LIKE', 'https://%')
+ ->pluck('multimedia_file_refn')
+ ->all();
+
+ $disk_files = $tree->mediaFilesystem()->listContents('', true);
+
+ $disk_files = array_filter($disk_files, static function (array $item) {
+ // Older versions of webtrees used a couple of special folders.
+ return
+ $item['type'] === 'file' &&
+ strpos($item['path'], '/thumbs/') === false &&
+ strpos($item['path'], '/watermarks/') === false;
+ });
+
+ $disk_files = array_map(static function (array $item): string {
+ return $item['path'];
+ }, $disk_files);
+
+ $unused_files = array_diff($disk_files, $used_files);
+
+ sort($unused_files);
+
+ return array_combine($unused_files, $unused_files);
+ }
+
+ /**
+ * Store an uploaded file (or URL), either to be added to a media object
+ * or to create a media object.
+ *
+ * @param ServerRequestInterface $request
+ *
+ * @return string The value to be stored in the 'FILE' field of the media object.
+ */
+ public function uploadFile(ServerRequestInterface $request): string
+ {
+ $tree = $request->getAttribute('tree');
+ assert($tree instanceof Tree);
+
+ $params = $request->getParsedBody();
+ $file_location = $params['file_location'];
+
+ switch ($file_location) {
+ case 'url':
+ $remote = $params['remote'];
+
+ if (strpos($remote, '://') !== false) {
+ return $remote;
+ }
+
+ return '';
+
+ case 'unused':
+ $unused = $params['unused'];
+
+ if ($tree->mediaFilesystem()->has($unused)) {
+ return $unused;
+ }
+
+ return '';
+
+ case 'upload':
+ default:
+ $folder = $params['folder'];
+ $auto = $params['auto'];
+ $new_file = $params['new_file'];
+
+ /** @var UploadedFileInterface|null $uploaded_file */
+ $uploaded_file = $request->getUploadedFiles()['file'];
+ if ($uploaded_file === null || $uploaded_file->getError() !== UPLOAD_ERR_OK) {
+ return '';
+ }
+
+ // The filename
+ $new_file = str_replace('\\', '/', $new_file);
+ if ($new_file !== '' && strpos($new_file, '/') === false) {
+ $file = $new_file;
+ } else {
+ $file = $uploaded_file->getClientFilename();
+ }
+
+ // The folder
+ $folder = str_replace('\\', '/', $folder);
+ $folder = trim($folder, '/');
+ if ($folder !== '') {
+ $folder .= '/';
+ }
+
+ // Generate a unique name for the file?
+ if ($auto === '1' || $tree->mediaFilesystem()->has($folder . $file)) {
+ $folder = '';
+ $extension = pathinfo($uploaded_file->getClientFilename(), PATHINFO_EXTENSION);
+ $file = sha1((string) $uploaded_file->getStream()) . '.' . $extension;
+ }
+
+ try {
+ $tree->mediaFilesystem()->writeStream($folder . $file, $uploaded_file->getStream()->detach());
+
+ return $folder . $file;
+ } catch (RuntimeException | InvalidArgumentException $ex) {
+ FlashMessages::addMessage(I18N::translate('There was an error uploading your file.'));
+
+ return '';
+ }
+ }
+ }
+
+ /**
+ * Convert the media file attributes into GEDCOM format.
+ *
+ * @param string $file
+ * @param string $type
+ * @param string $title
+ *
+ * @return string
+ */
+ public function createMediaFileGedcom(string $file, string $type, string $title): string
+ {
+ if (preg_match('/\.([a-z0-9]+)/i', $file, $match)) {
+ $extension = strtolower($match[1]);
+ $extension = str_replace('jpg', 'jpeg', $extension);
+ $extension = ' ' . $extension;
+ } else {
+ $extension = '';
+ }
+
+ $gedcom = '1 FILE ' . $file;
+ if ($type !== '') {
+ $gedcom .= "\n2 FORM" . $extension . "\n3 TYPE " . $type;
+ }
+ if ($title !== '') {
+ $gedcom .= "\n2 TITL " . $title;
+ }
+
+ return $gedcom;
+ }
+}