Add ability to credit photographer and uploader

This commit is contained in:
Max Nuding 2023-07-06 20:25:09 +02:00
parent d53391ef5a
commit b7c101f7dc
Signed by: phlaym
GPG Key ID: A06651BAB6777237
3 changed files with 108 additions and 18 deletions

View File

@ -10,7 +10,7 @@ use PhotoPrismUpload\Entities\Album;
/** @var string $footer Footer text which links to the Gitea repo */ /** @var string $footer Footer text which links to the Gitea repo */
$footer = $footer =
'<footer style="position: fixed;bottom: 0;left: 0;">' . '<footer style="position: fixed;bottom: 0;left: 0;">' .
'<a href="https://phlaym.net/git/phlaym/photoprismupload">Ich bin Open Source</a></footer>'; '<!--<a href="https://phlaym.net/git/phlaym/photoprismupload">Ich bin Open Source</a></footer>-->';
?> ?>
<html> <html>
<head> <head>
@ -43,13 +43,21 @@ $footer =
.form-wrapper { .form-wrapper {
display: grid; display: grid;
grid-template-rows: auto auto auto; grid-template-rows: auto auto auto;
grid-auto-columns: minmax(auto, 300px) auto; grid-auto-columns: minmax(auto, 400px) auto;
} }
label[for="album"] { label[for="album"] {
grid-column: 1; grid-column: 1;
grid-row: 1; grid-row: 1;
align-self: center; 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 { #album {
grid-column: 2; grid-column: 2;
grid-row: 1; grid-row: 1;
@ -63,7 +71,7 @@ $footer =
} }
input[type=submit] { input[type=submit] {
grid-column: 2; grid-column: 2;
grid-row: 3; grid-row: 5;
justify-self: right; justify-self: right;
} }
#error, #error,
@ -77,6 +85,7 @@ $footer =
#uploadForm { #uploadForm {
grid-row: 1; grid-row: 1;
grid-column: 1; grid-column: 1;
grid-auto-columns: minmax(100px, auto);
} }
#error { #error {
grid-row: 2; grid-row: 2;
@ -149,13 +158,15 @@ if (!isset($_POST['submit'])) {
<form method="POST" enctype="multipart/form-data" id="uploadForm"> <form method="POST" enctype="multipart/form-data" id="uploadForm">
<label for="album">Zu Album hinzufügen</label> <label for="album">Zu Album hinzufügen</label>
<select name="album" id="album"> <select name="album" id="album">
<option value="" data-url="/">---</option>
<?php <?php
if (!empty($config['noAlbumToken'])) {
echo '<option value="" data-url="/">---</option>';
}
/** @var Album $album Current PhotoPrism albums */ /** @var Album $album Current PhotoPrism albums */
foreach ($albums as $album) { foreach ($albums as $album) {
/** @var string $selected Selected attribute of the option */ /** @var string $selected Selected attribute of the option */
$selected = $album->token === $token ? ' selected ' : ''; $selected = $album->token === $tokens[0] ? ' selected ' : '';
if ($album->token === $token) { if ($album->token === $tokens[0]) {
$album_url = $album->getUrlPath() ?? '/'; $album_url = $album->getUrlPath() ?? '/';
} }
echo '<option value="' . echo '<option value="' .
@ -171,6 +182,10 @@ if (!isset($_POST['submit'])) {
$album_url = "{$api->base_url}{$album_url}"; $album_url = "{$api->base_url}{$album_url}";
?> ?>
</select> </select>
<label for="artist">Fotograf*in</label>
<input type="text" name="artist" id="artist" required/>
<label for="artist">Dein Name</label>
<input type="text" name="uploader" id="uploader"/>
<input multiple type="file" name="files[]" id="input" required/> <input multiple type="file" name="files[]" id="input" required/>
<input type="submit" name="submit" value="Upload" /> <input type="submit" name="submit" value="Upload" />
</form> </form>
@ -187,6 +202,8 @@ if (!isset($_POST['submit'])) {
const form = document.getElementById('uploadForm'); const form = document.getElementById('uploadForm');
const submitButton = form.querySelector('input[type=submit]'); const submitButton = form.querySelector('input[type=submit]');
const albumInput = form.querySelector('select[name=album]'); 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 input = document.getElementById('input');
const fileProgress = document.getElementById('fileProgress'); const fileProgress = document.getElementById('fileProgress');
const totalProgress = document.getElementById('totalProgress'); const totalProgress = document.getElementById('totalProgress');
@ -247,6 +264,8 @@ if (!isset($_POST['submit'])) {
formData.set(input.name, file); formData.set(input.name, file);
formData.set(submitButton.name, submitButton.value); formData.set(submitButton.name, submitButton.value);
formData.set(albumInput.name, albumInput.value); formData.set(albumInput.name, albumInput.value);
formData.set(artistInput.name, artistInput.value);
formData.set(uploaderInput.name, uploaderInput.value);
try { try {
let resp = await postData(form.action, formData, form.method); let resp = await postData(form.action, formData, form.method);
} catch(e) { } catch(e) {
@ -329,7 +348,24 @@ if (!isset($_POST['submit'])) {
<?php die($footer . '</body></html>'); <?php die($footer . '</body></html>');
} }
try { 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) { } catch (\Exception $e) {
die('Fehler: ' . $footer . $e->getMessage() . '</body></html>'); die('Fehler: ' . $footer . $e->getMessage() . '</body></html>');
} }

View File

@ -21,6 +21,9 @@ class PhotoPrism
/** @var string $api_url API URL of the PhotoPrism instance */ /** @var string $api_url API URL of the PhotoPrism instance */
public string $api_url = ''; 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 */ /** @var string|null $session_id Session id of the currently logged in user */
protected ?string $session_id = null; protected ?string $session_id = null;
@ -63,6 +66,7 @@ class PhotoPrism
$this->session_id = $_SESSION['pp_sessionid']; $this->session_id = $_SESSION['pp_sessionid'];
$this->preview_token = $_SESSION['pp_preview_token']; $this->preview_token = $_SESSION['pp_preview_token'];
$this->download_token = $_SESSION['pp_download_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)); $this->logger->debug('postfields ' . json_encode($query_data));
curl_setopt($ch, CURLOPT_URL, $url); 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_HTTPHEADER, $headers);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_HEADER, true); curl_setopt($ch, CURLOPT_HEADER, true);
@ -172,7 +179,6 @@ class PhotoPrism
} }
$output = curl_exec($ch); $output = curl_exec($ch);
// $request = curl_getinfo($ch, CURLINFO_HEADER_OUT);
$http_status = curl_getinfo($ch, CURLINFO_HTTP_CODE); $http_status = curl_getinfo($ch, CURLINFO_HTTP_CODE);
if ($output === false) { if ($output === false) {
@ -241,9 +247,11 @@ class PhotoPrism
$this->session_id = $response['id']; $this->session_id = $response['id'];
$this->download_token = $response['config']['downloadToken']; $this->download_token = $response['config']['downloadToken'];
$this->preview_token = $response['config']['previewToken']; $this->preview_token = $response['config']['previewToken'];
$this->user_id = $response['user']['UID'];
$_SESSION['pp_sessionid'] = $this->session_id; $_SESSION['pp_sessionid'] = $this->session_id;
$_SESSION['pp_preview_token'] = $this->preview_token; $_SESSION['pp_preview_token'] = $this->preview_token;
$_SESSION['pp_download_token'] = $this->download_token; $_SESSION['pp_download_token'] = $this->download_token;
$_SESSION['pp_userid'] = $this->user_id;
$this->logger->debug( $this->logger->debug(
'Session ID: ' . 'Session ID: ' .
$this->session_id . $this->session_id .
@ -362,14 +370,23 @@ class PhotoPrism
* @throws NetworkException on failure * @throws NetworkException on failure
* @param string|null $album -The album uid to which the photos should be aded * @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(); $path = time();
$url = '/upload/' . $path; $url = '/users/' . $this->user_id . '/upload/' . $path;
$import_url = '/import' . $url; $hashes = [];
$this->logger->info('Uploading ' . json_encode($_FILES));
foreach (array_keys($_FILES['files']['tmp_name']) as $key) { foreach (array_keys($_FILES['files']['tmp_name']) as $key) {
$file_tmpname = $_FILES['files']['tmp_name'][$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); $this->logger->info('Uploading ' . $file_tmpname . ' to ' . $url);
$hashes[] = sha1_file($file_tmpname);
$filename = basename($_FILES['files']['name'][$key]); $filename = basename($_FILES['files']['name'][$key]);
$cFile = curl_file_create( $cFile = curl_file_create(
$file_tmpname, $file_tmpname,
@ -385,15 +402,49 @@ class PhotoPrism
'multipart/form-data' 'multipart/form-data'
); );
$this->logger->info('Upload result: ' . $res); $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'); public function getByHash(string $hash): ?Photo
/** @var string[] $albums */ {
$albums = empty($album) ? [] : [$album]; $this->logger->debug('getByHash');
$import_data = ['move' => true, 'albums' => $albums]; $data = [
$res = $this->makeRequest('POST', $import_url, $import_data); 'q' => 'hash:' . $hash,
$this->logger->info('Import result: ' . $res); '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));
} }
/** /**

View File

@ -28,6 +28,8 @@ class Photo
public array $files; public array $files;
public array $details;
/** /**
* Creates a new photo from the api response * Creates a new photo from the api response
* *
@ -48,6 +50,7 @@ class Photo
$this->width = intval($response['Width']); $this->width = intval($response['Width']);
$this->height = intval($response['Height']); $this->height = intval($response['Height']);
$this->logger = LoggerFactory::create('PhotoPrismUpload.Photo'); $this->logger = LoggerFactory::create('PhotoPrismUpload.Photo');
$this->details = $response;
} }
/** /**