From b7c101f7dc6814f4915cd9519e7faf292dea8cd8 Mon Sep 17 00:00:00 2001 From: Max Nuding Date: Thu, 6 Jul 2023 20:25:09 +0200 Subject: [PATCH] Add ability to credit photographer and uploader --- index.php | 50 +++++++++++++++++++++++++---- src/API/PhotoPrism.php | 73 +++++++++++++++++++++++++++++++++++------- src/Entities/Photo.php | 3 ++ 3 files changed, 108 insertions(+), 18 deletions(-) diff --git a/index.php b/index.php index f8a27c2..23ba3bf 100644 --- a/index.php +++ b/index.php @@ -10,7 +10,7 @@ use PhotoPrismUpload\Entities\Album; /** @var string $footer Footer text which links to the Gitea repo */ $footer = ''; + ''; ?> @@ -43,13 +43,21 @@ $footer = .form-wrapper { display: grid; grid-template-rows: auto auto auto; - grid-auto-columns: minmax(auto, 300px) auto; + grid-auto-columns: minmax(auto, 400px) auto; } label[for="album"] { grid-column: 1; grid-row: 1; align-self: center; } + label[for="artist"], label[for="uploader"] { + grid-column: 1; + align-self: center; + } + input[type=text] { + grid-column: 2; + justify-self: right; + } #album { grid-column: 2; grid-row: 1; @@ -63,7 +71,7 @@ $footer = } input[type=submit] { grid-column: 2; - grid-row: 3; + grid-row: 5; justify-self: right; } #error, @@ -77,6 +85,7 @@ $footer = #uploadForm { grid-row: 1; grid-column: 1; + grid-auto-columns: minmax(100px, auto); } #error { grid-row: 2; @@ -149,13 +158,15 @@ if (!isset($_POST['submit'])) {
+ + + +
@@ -187,6 +202,8 @@ if (!isset($_POST['submit'])) { const form = document.getElementById('uploadForm'); const submitButton = form.querySelector('input[type=submit]'); const albumInput = form.querySelector('select[name=album]'); + const artistInput = form.querySelector('input[name=artist]'); + const uploaderInput = form.querySelector('input[name=uploader]'); const input = document.getElementById('input'); const fileProgress = document.getElementById('fileProgress'); const totalProgress = document.getElementById('totalProgress'); @@ -247,6 +264,8 @@ if (!isset($_POST['submit'])) { formData.set(input.name, file); formData.set(submitButton.name, submitButton.value); formData.set(albumInput.name, albumInput.value); + formData.set(artistInput.name, artistInput.value); + formData.set(uploaderInput.name, uploaderInput.value); try { let resp = await postData(form.action, formData, form.method); } catch(e) { @@ -329,7 +348,24 @@ if (!isset($_POST['submit'])) { '); } try { - $api->uploadPhotos($_POST['album']); + $hashes = $api->uploadPhotos($_POST['album']); + foreach ($hashes as $hash) { + $photo = $api->getByHash($hash); + if (!isset($photo)) { + continue; + } + $details = [ + 'Artist' => $_POST['artist'], + 'ArtistSrc' => 'manual', + 'Copyright' => $_POST['artist'], + 'CopyrightSrc' => 'manual', + ]; + if (!empty($_POST['uploader'])) { + $details['Notes'] = 'Hochgeladen von: ' . $_POST['uploader']; + $details['NotesSrc'] = 'manual'; + } + $api->updatePhotoDetails($photo, $details); + } } catch (\Exception $e) { die('Fehler: ' . $footer . $e->getMessage() . ''); } diff --git a/src/API/PhotoPrism.php b/src/API/PhotoPrism.php index f1bbd3f..af802ce 100644 --- a/src/API/PhotoPrism.php +++ b/src/API/PhotoPrism.php @@ -21,6 +21,9 @@ class PhotoPrism /** @var string $api_url API URL of the PhotoPrism instance */ public string $api_url = ''; + /** @var string|null $user_id Id of the currently logged in user */ + protected ?string $user_id = null; + /** @var string|null $session_id Session id of the currently logged in user */ protected ?string $session_id = null; @@ -63,6 +66,7 @@ class PhotoPrism $this->session_id = $_SESSION['pp_sessionid']; $this->preview_token = $_SESSION['pp_preview_token']; $this->download_token = $_SESSION['pp_download_token']; + $this->user_id = $_SESSION['pp_userid']; } } @@ -161,7 +165,10 @@ class PhotoPrism $this->logger->debug('postfields ' . json_encode($query_data)); curl_setopt($ch, CURLOPT_URL, $url); - curl_setopt($ch, CURLOPT_POST, $method !== 'get'); + curl_setopt($ch, CURLOPT_POST, $method !== 'get' && $method !== 'put'); + if ($method === 'put') { + curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'PUT'); + } curl_setopt($ch, CURLOPT_HTTPHEADER, $headers); curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); curl_setopt($ch, CURLOPT_HEADER, true); @@ -172,7 +179,6 @@ class PhotoPrism } $output = curl_exec($ch); - // $request = curl_getinfo($ch, CURLINFO_HEADER_OUT); $http_status = curl_getinfo($ch, CURLINFO_HTTP_CODE); if ($output === false) { @@ -241,9 +247,11 @@ class PhotoPrism $this->session_id = $response['id']; $this->download_token = $response['config']['downloadToken']; $this->preview_token = $response['config']['previewToken']; + $this->user_id = $response['user']['UID']; $_SESSION['pp_sessionid'] = $this->session_id; $_SESSION['pp_preview_token'] = $this->preview_token; $_SESSION['pp_download_token'] = $this->download_token; + $_SESSION['pp_userid'] = $this->user_id; $this->logger->debug( 'Session ID: ' . $this->session_id . @@ -362,14 +370,23 @@ class PhotoPrism * @throws NetworkException on failure * @param string|null $album -The album uid to which the photos should be aded */ - public function uploadPhotos(?string $album = null): void + public function uploadPhotos(?string $album = null): array { + $albums = empty($album) ? [] : [$album]; + $import_data = ['albums' => $albums]; + $path = time(); - $url = '/upload/' . $path; - $import_url = '/import' . $url; + $url = '/users/' . $this->user_id . '/upload/' . $path; + $hashes = []; + $this->logger->info('Uploading ' . json_encode($_FILES)); foreach (array_keys($_FILES['files']['tmp_name']) as $key) { $file_tmpname = $_FILES['files']['tmp_name'][$key]; + if (empty($file_tmpname)) { + $this->logger->warning('file tmp_name is empty. All file info: ' . json_encode($_FILES)); + continue; + } $this->logger->info('Uploading ' . $file_tmpname . ' to ' . $url); + $hashes[] = sha1_file($file_tmpname); $filename = basename($_FILES['files']['name'][$key]); $cFile = curl_file_create( $file_tmpname, @@ -385,15 +402,49 @@ class PhotoPrism 'multipart/form-data' ); $this->logger->info('Upload result: ' . $res); + $this->logger->info('Importing files'); + $res = $this->makeRequest( + 'PUT', + $url, + $import_data + ); + $this->logger->info('Import result: ' . $res); } + return $hashes; + } - $this->logger->info('Importing files'); - /** @var string[] $albums */ - $albums = empty($album) ? [] : [$album]; + public function getByHash(string $hash): ?Photo + { + $this->logger->debug('getByHash'); - $import_data = ['move' => true, 'albums' => $albums]; - $res = $this->makeRequest('POST', $import_url, $import_data); - $this->logger->info('Import result: ' . $res); + $data = [ + 'q' => 'hash:' . $hash, + 'count' => 1, + 'offset' => 0 + ]; + $res = $this->makeRequest('GET', '/photos', $data, 'text/plain'); + $this->logger->debug('getByHash response: ' . $res); + $response = json_decode($res, true); + if (!empty($response['error'])) { + throw new NetworkException($response['error']); + } + if (empty($response)) { + return null; + } + $photo = new Photo($response[0]); + $photo->thumbnail_token = $this->preview_token; + $this->logger->debug('getByHash photo: ' . json_encode($photo)); + return $photo; + } + + public function updatePhotoDetails(Photo $photo, array $updatedDetails): void + { + $updatedDetails['PhotoID'] = $photo->id; + foreach ($updatedDetails as $key => $value) { + $details[$key] = $value; + } + $res = $this->makeRequest('PUT', '/photos/' . $photo->uid, ['Details' => $details]); + $this->logger->debug('updatePhotoDetails response: ' . json_encode($res)); } /** diff --git a/src/Entities/Photo.php b/src/Entities/Photo.php index eb5f848..8833ecf 100644 --- a/src/Entities/Photo.php +++ b/src/Entities/Photo.php @@ -28,6 +28,8 @@ class Photo public array $files; + public array $details; + /** * Creates a new photo from the api response * @@ -48,6 +50,7 @@ class Photo $this->width = intval($response['Width']); $this->height = intval($response['Height']); $this->logger = LoggerFactory::create('PhotoPrismUpload.Photo'); + $this->details = $response; } /**