Skip to content

Commit

Permalink
Add push-to-Flickr syndication
Browse files Browse the repository at this point in the history
  • Loading branch information
samwilson authored Mar 29, 2022
1 parent 0b33a60 commit f8b4051
Show file tree
Hide file tree
Showing 14 changed files with 266 additions and 13 deletions.
2 changes: 1 addition & 1 deletion assets/css/post.less
Original file line number Diff line number Diff line change
Expand Up @@ -107,7 +107,7 @@ form.post-edit {
#map { height: 300px; }
}

form.commons {
form.posse {
display: flex;

& > .image {
Expand Down
1 change: 0 additions & 1 deletion public/build/app.5d4441fa.css

This file was deleted.

1 change: 1 addition & 0 deletions public/build/app.ab8285ed.css

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion public/build/entrypoints.json
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
"/build/app.103342a2.js"
],
"css": [
"/build/app.5d4441fa.css"
"/build/app.ab8285ed.css"
]
},
"map": {
Expand Down
2 changes: 1 addition & 1 deletion public/build/manifest.json
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
{
"build/app.css": "/build/app.5d4441fa.css",
"build/app.css": "/build/app.ab8285ed.css",
"build/app.js": "/build/app.103342a2.js",
"build/map.css": "/build/map.194bb611.css",
"build/map.js": "/build/map.bc128b20.js",
Expand Down
104 changes: 104 additions & 0 deletions src/Controller/FlickrController.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
<?php

namespace App\Controller;

use App\Filesystems;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Routing\Annotation\Route;
use Samwilson\PhpFlickr\PhpFlickr;
use App\Repository\PostRepository;
use App\Repository\SyndicationRepository;
use App\Settings;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\IsGranted;
use OAuth\OAuth1\Token\StdOAuth1Token;
use Symfony\Component\HttpFoundation\Request;
use App\Entity\Post;
use Symfony\Component\Routing\Generator\UrlGeneratorInterface;

class FlickrController extends ControllerBase
{

private function getPhpFlickr(Settings $settings): PhpFlickr
{
$phpFlickr = new PhpFlickr($settings->flickrApiKey(), $settings->flickrApiSecret());
$accessToken = new StdOAuth1Token();
$accessToken->setAccessToken($settings->flickrToken());
$accessToken->setAccessTokenSecret($settings->flickrTokenSecret());
$phpFlickr->getOauthTokenStorage()->storeAccessToken('Flickr', $accessToken);
return $phpFlickr;
}

/**
* @Route("/P{id}/flickr", name="flickr", methods={"GET"})
* @IsGranted("ROLE_ADMIN")
*/
public function form(
PostRepository $postRepository,
Settings $settings,
string $id
): Response {
$post = $postRepository->find($id);
if (!$post) {
throw $this->createNotFoundException();
}
$userInfo = $this->getPhpFlickr($settings)->test()->login();
return $this->render('post/flickr.html.twig', [
'flickr_user' => $userInfo,
'post' => $post,
]);
}

/**
* @Route("/P{id}/flickr", name="flickr_save", methods={"POST"})
* @IsGranted("ROLE_ADMIN")
*/
public function upload(
PostRepository $postRepository,
SyndicationRepository $syndicationRepository,
Settings $settings,
Filesystems $filesystems,
Request $request,
$id
) {
/** @var Post $post */
$post = $postRepository->find($id);
if (!$post) {
throw $this->createNotFoundException();
}
$fullTempPath = $filesystems->getLocalTempFilepath($post->getFile());
$tags = [];
foreach ($request->get('tags', []) as $tag) {
// implode(' ', $request->get('tags', [])),
$tags[] = '"' . str_replace('"', "'", $tag) . '"';
}
$phpFlickr = $this->getPhpFlickr($settings);
$postUrl = $this->generateUrl('post_view', ['id' => $post->getId()], UrlGeneratorInterface::ABSOLUTE_URL);
$result = $phpFlickr->uploader()->upload(
$fullTempPath,
$request->get('title'),
trim($request->get('description')) . "\n\n" . $postUrl,
implode(' ', $tags),
$request->get('is_public') !== null,
$request->get('is_friend') !== null,
$request->get('is_family') !== null,
);
if (isset($result['message'])) {
$this->addFlash(self::FLASH_NOTICE, $result['message']);
return $this->redirectToRoute('flickr', ['id' => $id]);
}
if (isset($result['stat']) && $result['stat'] === 'ok') {
if ($post->getLocation()) {
$phpFlickr->photosGeo()->setLocation(
$result['photoid'],
$post->getLocation()->getY(),
$post->getLocation()->getX()
);
}
$userInfo = $this->getPhpFlickr($settings)->test()->login();
$flickrUrl = 'https://www.flickr.com/photos/' . $userInfo['path_alias'] . '/' . $result['photoid'];
$syndicationRepository->addSyndication($post, $flickrUrl, 'Flickr');
$this->addFlash(self::FLASH_SUCCESS, 'Uploaded: ' . $flickrUrl);
return $this->redirectToRoute('post_view', ['id' => $id]);
}
}
}
48 changes: 48 additions & 0 deletions src/Controller/SettingController.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,13 @@
namespace App\Controller;

use App\Settings;
use Samwilson\PhpFlickr\PhpFlickr;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\Routing\Annotation\Route;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\IsGranted;
use Symfony\Component\HttpFoundation\Response;
use OAuth\Common\Storage\Session;
use Symfony\Component\Routing\Generator\UrlGeneratorInterface;

class SettingController extends ControllerBase
{
Expand Down Expand Up @@ -36,6 +39,51 @@ public function index()
]);
}

/**
* @Route("/settings/flickr/connect", name="flickr_connect")
* @isGranted("ROLE_ADMIN")
*/
public function flickrConnect(Settings $settings): Response
{
$flickr = new PhpFlickr($settings->flickrApiKey(), $settings->flickrApiSecret());
$flickr->setOauthStorage(new Session());
$callbackUrl = $this->generateUrl('flickr_callback', [], UrlGeneratorInterface::ABSOLUTE_URL);
return $this->redirect($flickr->getAuthUrl('write', $callbackUrl));
}

/**
* @Route("/settings/flickr/callback", name="flickr_callback")
* @isGranted("ROLE_ADMIN")
*/
public function flickrCallback(Settings $settings, Request $request): Response
{
if (!$request->get('oauth_verifier') || !$request->get('oauth_token')) {
$this->addFlash(self::FLASH_NOTICE, 'No OAuth verifier params passed for Flickr callback.');
return $this->redirectToRoute('settings');
}
$flickr = new PhpFlickr($settings->flickrApiKey(), $settings->flickrApiSecret());
$flickr->setOauthStorage(new Session());
$accessToken = $flickr->retrieveAccessToken($request->get('oauth_verifier'), $request->get('oauth_token'));
$settings->saveData([
'flickr_token' => $accessToken->getAccessToken(),
'flickr_token_secret' => $accessToken->getAccessTokenSecret(),
]);
return $this->redirectToRoute('settings');
}

/**
* @Route("/settings/flickr/disconnect", name="flickr_disconnect")
* @isGranted("ROLE_ADMIN")
*/
public function flickrDisconnect(Settings $settings): Response
{
$settings->saveData([
'flickr_token' => '',
'flickr_token_secret' => '',
]);
return $this->redirectToRoute('settings');
}

/**
* @Route("/settings/css", name="settings_css")
* @Route("/settings/js", name="settings_js")
Expand Down
16 changes: 16 additions & 0 deletions src/Filesystems.php
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,22 @@ private function getDataStoragePath(File $file): string
return "/files/$bracket/" . $id . "." . $file->getExtension();
}

/**
* Download the full-sized original of a file to local temp and return its path.
*
* @return string Full local filesystem path the to file.
*/
public function getLocalTempFilepath(File $file): string
{
$outStream = $this->read($file, File::SIZE_FULL);
$tempFilePath = 'local_tmp/' . $file->getPost()->getId() . '.' . $file->getExtension();
$tempFs = $this->temp();
if (!$tempFs->has($tempFilePath)) {
$tempFs->writeStream($tempFilePath, $outStream);
}
return $this->tempRoot() . $tempFilePath;
}

public function write(Filesystem $fs, File $file, string $filePath)
{
$storagePath = $this->getDataStoragePath($file);
Expand Down
11 changes: 6 additions & 5 deletions src/Repository/CommonsRepository.php
Original file line number Diff line number Diff line change
Expand Up @@ -72,13 +72,14 @@ public function getCommonsUrl(): string
*/
public function upload(Post $post, string $title, string $text, string $caption, array $depicts): array
{
$outStream = $this->filesystems->read($post->getFile(), File::SIZE_FULL);
//$outStream = $this->filesystems->read($post->getFile(), File::SIZE_FULL);
$tempFilePath = 'commons/' . $post->getId() . '.' . $post->getFile()->getExtension();
$tempFs = $this->filesystems->temp();
if (!$tempFs->has($tempFilePath)) {
$tempFs->writeStream($tempFilePath, $outStream);
}
$fullTempPath = $this->filesystems->tempRoot() . $tempFilePath;
// if (!$tempFs->has($tempFilePath)) {
// $tempFs->writeStream($tempFilePath, $outStream);
// }
// $fullTempPath = $this->filesystems->tempRoot() . $tempFilePath;
$fullTempPath = $this->filesystems->getLocalTempFilepath($post->getFile(), $tempFilePath);
$api = $this->getMediaWikiApi();
$uploader = new CommonsFileUploader($api);
$uploadResult = $uploader->uploadWithResult($title, $fullTempPath, $text);
Expand Down
6 changes: 3 additions & 3 deletions templates/post/commons.html.twig
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@

<p><a href="{{ path('post_edit', {id:post.id}) }}">&larr; Return to editing this post</a></p>

<form action="{{ path('commons_save', {id:post.id}) }}" method="post" class="commons">
<form action="{{ path('commons_save', {id:post.id}) }}" method="post" class="posse">
<div class="image">
<img src="{{ path('file', {id:post.id, size:'D', ext:'jpg'}) }}" alt="Image of the file attached to this post." />
</div>
Expand All @@ -26,10 +26,10 @@
</p>
<p>
<label for="depicts">Depicts:</label>
<select id="depicts" name="depicts[]">
<select id="depicts" name="depicts[]" multiple>
{% for tag in post.tags %}
{% if tag.wikidata %}
<option value="{{ tag.wikidata }}">{{ tag.title }}</option>
<option value="{{ tag.wikidata }}" selected>{{ tag.title }}</option>
{% endif %}
{% endfor %}
</select>
Expand Down
62 changes: 62 additions & 0 deletions templates/post/flickr.html.twig
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
{% extends 'base.html.twig' %}

{% block title %}
{{'posts.flickr.copy_to'|trans}}
{% endblock %}

{% block body %}

<h1>{{'posts.flickr.copy_to'|trans}}</h1>

<p><a href="{{ path('post_edit', {id:post.id}) }}">&larr; Return to editing this post</a></p>

<form action="{{ path('flickr_save', {id:post.id}) }}" method="post" class="posse">
<div class="image">
<img src="{{ path('file', {id:post.id, size:'D', ext:'jpg'}) }}" alt="Image of the file attached to this post." />
</div>
<div class="form">
<p>
{% set flickr_link -%}
<a href="https://flickr.com/photos/{% if flickr_user.path_alias %}{{flickr_user.path_alias}}{% else %}{{flickr_user.id}}{% endif %}">
{{- flickr_user.username -}}
</a>
{%- endset %}
{{ 'posts.flickr.logged_in'|trans({'%username_link%': flickr_link})|raw }}
</p>
<p>
<label for="title">{{'posts.flickr.title'|trans}}</label>
<input type="text" id="title" name="title" value="{{ post.title }}" />
</p>
<p>
<label for="description">{{'posts.flickr.description'|trans}}</label>
<textarea id="description" name="description">{{ post.body }}</textarea>
</p>
<p>
<label for="tags">Tags:</label>
<select id="tags" name="tags[]" multiple>
{% for tag in post.tags %}
<option value="{{ tag.title }}" selected>{{ tag.title }}</option>
{% endfor %}
</select>
</p>
<p>
<label for="is_public">
<input type="checkbox" name="is_public" id="is_public" />
{{'posts.flickr.is_public'|trans}}
</label>
<label for="is_friend">
<input type="checkbox" name="is_friend" id="is_friend" />
{{'posts.flickr.is_friend'|trans}}
</label>
<label for="is_family">
<input type="checkbox" name="is_family" id="is_family" />
{{'posts.flickr.is_family'|trans}}
</label>
</p>
<p>
<input type="submit" value="Upload" />
</p>
</div>
</form>

{% endblock %}
7 changes: 7 additions & 0 deletions templates/post/form.html.twig
Original file line number Diff line number Diff line change
Expand Up @@ -141,6 +141,13 @@
</td>
</tr>
{% endif %}
{% if post.id %}
<tr>
<td colspan="3">
<a href="{{ path('flickr', {id:post.id}) }}">{{'posts.flickr.copy_to'|trans}}</a>
</td>
</tr>
{% endif %}
</tfoot>
</table>
<p>
Expand Down
9 changes: 8 additions & 1 deletion templates/setting/index.html.twig
Original file line number Diff line number Diff line change
Expand Up @@ -36,13 +36,20 @@
</span>
<span class="field size-1">
<label for="flickr_api_secret">API Secret:</label>
<input id="flickr_api_secret" type="text" value="{{ settings.flickrApiSecret }}" name="settings[flickr_api_secret]" />
<input id="flickr_api_secret" type="password" value="{{ settings.flickrApiSecret }}" name="settings[flickr_api_secret]" />
</span>
</p>
<p>
Access Token? {% if settings.flickrToken %}&check;{% else %}&cross;{% endif %}
Access Token Secret? {% if settings.flickrTokenSecret %}&check;{% else %}&cross;{% endif %}
</p>
<p>
{% if settings.flickrToken %}
<a href="{{path('flickr_disconnect')}}">Disconnect from Flickr</a>
{% else %}
<a href="{{path('flickr_connect')}}">Connect to Flickr</a>
{% endif %}
</a>
</fieldset>

<fieldset>
Expand Down
8 changes: 8 additions & 0 deletions translations/messages.en.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,14 @@ posts:
save_tooltip: 'Save the full version of this file'
delete:
gone-will-be-added: 'An HTTP status of "410 Gone" will be added for this post. See %redirects_link% for more information.'
flickr:
copy_to: 'Copy to Flickr'
logged_in: 'You are logged in as %username_link%.'
title: 'Title:'
description: 'Description:'
is_public: 'Public'
is_friend: 'Friend'
is_family: 'Famiy'
settings:
title: 'Site Settings'
location_legend: 'GPS tracking'
Expand Down

0 comments on commit f8b4051

Please sign in to comment.