Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add featured image feature #85

Merged
merged 20 commits into from
Jun 2, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
20 commits
Select commit Hold shift + click to select a range
1d00645
Add featured image relationship to entity classes
gothick May 30, 2021
a40732a
Add test fixtures for image testing
gothick May 30, 2021
b031647
Firm up our relationship between Featured Image and Wander
gothick May 30, 2021
15faf91
Added next text (currently failing, but that's basically a 'TODO'
gothick May 30, 2021
a8df84f
Last little fixes to Featured Image relationship
gothick May 31, 2021
a9eaaa8
Don't bother with text code coverage report for dev
gothick May 31, 2021
c353eeb
Our relationship should actually work the *other* way around. Otherwi…
gothick May 31, 2021
3cbfc38
Fix first couple of test failures following reversal of featured imag…
gothick May 31, 2021
2c94a48
Fix up wander deletion so we don't break referential integrity becaus…
gothick May 31, 2021
0c4ccff
Fix up the final issues having reversed the featured image relationship
gothick May 31, 2021
30658dd
Show featured image on Wander admin (show) page.
gothick May 31, 2021
88badca
Fix bug that caused integrity constraint violation when changing feat…
gothick May 31, 2021
7a8c78b
Improve featured image testing; make sure we test changes of an exist…
gothick May 31, 2021
c618366
Add UI for changing featured image from Wander Edit page
gothick May 31, 2021
69106f1
Add star rating for featured Image drop-down
gothick May 31, 2021
b0d0172
Show featured image on main wander page
gothick May 31, 2021
3935e0b
Add featured image to RSS/Atom feeds if available.
gothick May 31, 2021
4f0e023
Add featured image to Twitter card on Wander page.
gothick May 31, 2021
103ed89
Various formatting standards fixes.
gothick May 31, 2021
f6ac84e
More minor formatting fixes.
gothick May 31, 2021
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion config/packages/liip_imagine.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ liip_imagine:
filters:
scale:
dim: [600, 600]
open_graph_image:
open_graph_image: # Also used for RSS/Atom feed
quality: 75
filters:
relative_resize:
Expand Down
10 changes: 10 additions & 0 deletions config/packages/test/messenger.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
framework:
messenger:
transports:
# If we just use a sync queue for test, it might avoid
# a clash between the creation of the messenger_messages
# table and our use of transactions around our tests to
# keep the database tidy.
async:
dsn: 'sync://' # psych!

2 changes: 1 addition & 1 deletion config/services.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -102,7 +102,7 @@ services:

App\EventListener\WanderDeleteListener:
tags:
- { name: 'doctrine.orm.entity_listener' }
- { name: 'doctrine.orm.entity_listener', entity: 'App\Entity\Wander', lazy: true }

App\EventListener\ImageCalculatedFieldSetterListener:
tags:
Expand Down
7 changes: 7 additions & 0 deletions config/services_test.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
services:
# default configuration for services in *this* file
_defaults:
autowire: true # Automatically injects dependencies in your services.
autoconfigure: true # Automatically registers your services as commands, event subscribers, etc.

App\Service\ImageTaggingServiceInterface: '@App\Service\DummyImageTaggingService'
35 changes: 35 additions & 0 deletions migrations/Version20210531094747.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
<?php

declare(strict_types=1);

namespace DoctrineMigrations;

use Doctrine\DBAL\Schema\Schema;
use Doctrine\Migrations\AbstractMigration;

/**
* Auto-generated Migration: Please modify to your needs!
*/
final class Version20210531094747 extends AbstractMigration
{
public function getDescription(): string
{
return '';
}

public function up(Schema $schema): void
{
// this up() migration is auto-generated, please modify it to your needs
$this->addSql('ALTER TABLE image ADD featuring_wander_id INT DEFAULT NULL');
$this->addSql('ALTER TABLE image ADD CONSTRAINT FK_C53D045F5ED948F0 FOREIGN KEY (featuring_wander_id) REFERENCES wander (id)');
$this->addSql('CREATE UNIQUE INDEX UNIQ_C53D045F5ED948F0 ON image (featuring_wander_id)');
}

public function down(Schema $schema): void
{
// this down() migration is auto-generated, please modify it to your needs
$this->addSql('ALTER TABLE image DROP FOREIGN KEY FK_C53D045F5ED948F0');
$this->addSql('DROP INDEX UNIQ_C53D045F5ED948F0 ON image');
$this->addSql('ALTER TABLE image DROP featuring_wander_id');
}
}
11 changes: 9 additions & 2 deletions phpunit.xml.dev
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
<?xml version="1.0" encoding="UTF-8"?>

<!-- https://phpunit.readthedocs.io/en/latest/configuration.html -->
<phpunit xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="bin/.phpunit/phpunit.xsd"
Expand All @@ -16,10 +15,16 @@
<!-- Should be the *real* path to exiftool on the test environment -->
<env name="TEST_EXIFTOOL_PATH" value="/usr/bin/exiftool" />
</php>
<groups>
<exclude>
<!-- skip over Twig's weird legacy tests -->
<group>legacy</group>
</exclude>
</groups>

<testsuites>
<testsuite name="Project Test Suite">
<directory>tests</directory>
<directory>tests</directory>
</testsuite>
</testsuites>

Expand All @@ -34,6 +39,8 @@
</listeners>
<logging>
<log type="coverage-html" target="coverage" />
<!-- I'd rather just look at the HTML occasionally.
<log type="coverage-text" target="php://stdout" />
-->
</logging>
</phpunit>
39 changes: 39 additions & 0 deletions src/DataFixtures/TwoImageFixtures.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
<?php

namespace App\DataFixtures;

use Doctrine\Bundle\FixturesBundle\Fixture;
use Doctrine\Bundle\FixturesBundle\FixtureGroupInterface;
use Doctrine\Persistence\ObjectManager;
use Symfony\Component\Filesystem\Filesystem;
use Symfony\Component\Finder\Finder;
use App\Entity\Image;
use Symfony\Component\HttpFoundation\File\File;
use Symfony\Component\HttpFoundation\File\UploadedFile;
use Symfony\Component\Routing\Generator\UrlGenerator;


class TwoImageFixtures extends Fixture implements FixtureGroupInterface
{
public static function getGroups(): array
{
return ['image'];
}

public function load(ObjectManager $manager): void
{
$fs = new Filesystem();
$finder = new Finder();
foreach ($finder->in(__DIR__ . '/image/two')->name('/\.jpg$/i') as $source) {

$image = new Image();

$targetPath = sys_get_temp_dir() . '/' . $source->getFilename();
$fs->copy($source->getPathname(), $targetPath);
$uploadedFake = new UploadedFile($targetPath, $source->getFilename(), 'image/jpeg', null, true);
$image->setImageFile($uploadedFake);
$manager->persist($image);
}
$manager->flush();
}
}
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
54 changes: 53 additions & 1 deletion src/Entity/Image.php
Original file line number Diff line number Diff line change
Expand Up @@ -231,6 +231,14 @@ public function getTitle(): ?string
return $this->title;
}

public function getTitleOrId(): string
{
if ($this->title !== null && $this->title != "") {
return $this->title;
}
return (string) "Image " . $this->id;
}

public function setTitle(?string $title): self
{
$this->title = $title;
Expand Down Expand Up @@ -406,7 +414,8 @@ public function getTagsText(): ?string
/**
* @ORM\PostLoad
*/
public function postLoad(): void {
public function postLoad(): void
{
// Bodge to workaround behaviour of BeelabTagBundle, which updates
// tags on persist, but only from the text tags. So if you don't
// get/set the tags text, when you persist your entity all its
Expand Down Expand Up @@ -446,6 +455,11 @@ public function setWander(?Wander $wander): self
return $this;
}

public function hasWander(): bool
{
return ($this->wander !== null);
}

public function getRating(): ?int
{
return $this->rating;
Expand Down Expand Up @@ -491,6 +505,10 @@ public function setRating(?int $rating): self
*/
private $location;

/**
* @ORM\OneToOne(targetEntity=Wander::class, inversedBy="featuredImage", cascade={"persist"})
*/
private $featuringWander;

public function setImageUri($imageUri) {
$this->imageUri = $imageUri;
Expand Down Expand Up @@ -555,5 +573,39 @@ public function setLocation(?string $location): self

return $this;
}

public function getFeaturingWander(): ?Wander
{
return $this->featuringWander;
}

public function setFeaturingWander(?Wander $featuringWander): self
{
$this->featuringWander = $featuringWander;

return $this;
}

public function setAsFeaturedImage(): void
{
$wander = $this->wander;
if ($wander === null) {
throw new \Exception("Can't call setAsFeaturedImage unless the Image is associated with a Wander.");
}
$this->setFeaturingWander($wander);
}

// Used when building drop-down list of Images to choose as selection on Wander edit screen
public function __toString(): string
{
$result = $this->title ?? (string) $this->id;
if (isset($this->capturedAt)) {
$result .= ' (' . $this->capturedAt->format('j M Y') . ')';
}
if (isset($this->rating)) {
$result .= ' ' . str_repeat('★', $this->rating);
}
return $result;
}
}

32 changes: 32 additions & 0 deletions src/Entity/Wander.php
Original file line number Diff line number Diff line change
Expand Up @@ -466,6 +466,11 @@ public function setAngleFromHome(?float $angleFromHome): self
*/
private $geoJson;

/**
* @ORM\OneToOne(targetEntity=Image::class, mappedBy="featuringWander", cascade={"persist"})
*/
private $featuredImage;

public function getSector(): ?string
{
if ($this->angleFromHome !== null) {
Expand Down Expand Up @@ -511,4 +516,31 @@ public function setGeoJson(?string $geoJson): self

return $this;
}

public function getFeaturedImage(): ?Image
{
return $this->featuredImage;
}

public function hasFeaturedImage(): bool
{
return $this->featuredImage !== null;
}

public function setFeaturedImage(?Image $featuredImage): self
{
// unset the owning side of the relation if necessary
if ($this->featuredImage !== null) {
$this->featuredImage->setFeaturingWander(null);
}

// set the owning side of the relation if necessary
if ($featuredImage !== null && $featuredImage->getFeaturingWander() !== $this) {
$featuredImage->setFeaturingWander($this);
}

$this->featuredImage = $featuredImage;

return $this;
}
}
20 changes: 16 additions & 4 deletions src/EventListener/WanderDeleteListener.php
Original file line number Diff line number Diff line change
Expand Up @@ -21,11 +21,23 @@ public function __construct(LoggerInterface $logger, GpxService $gpxService)
$this->gpxService = $gpxService;
}

public function preRemove(
Wander $wander,
/** @scrutinizer ignore-unused */ LifecycleEventArgs $event
): void {
// If we're about to delete a wander, we want to remove it as a featuring
// wander from the related Image first, otherwise we'll break referential
// integrity.
$image = $wander->getFeaturedImage();
if ($image !== null) {
$image->setFeaturingWander(null);
}
}

public function postRemove(
Wander $wander,
/** @scrutinizer ignore-unused */ LifecycleEventArgs $event
): void
{
Wander $wander,
/** @scrutinizer ignore-unused */ LifecycleEventArgs $event
): void {
$path = $this->gpxService->getFullGpxFilePathFromWander($wander);
if (!file_exists($path)) {
$this->logger->debug("Could not find GPX file " . $path . " to remove");
Expand Down
16 changes: 14 additions & 2 deletions src/Form/WanderType.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,10 @@

namespace App\Form;

use App\Entity\Image;
use App\Entity\Wander;
use Doctrine\ORM\EntityRepository;
use Symfony\Bridge\Doctrine\Form\Type\EntityType;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\Extension\Core\Type\DateTimeType;
use Symfony\Component\Form\FormBuilderInterface;
Expand All @@ -23,12 +26,21 @@ public function buildForm(FormBuilderInterface $builder, array $options)
'attr' => ['rows' => 10]
]);
if ('standard' === $options['type']) {
/** @var Wander */
$wander = $builder->getData();
$builder
->add('startTime', DateTimeType::class)
->add('endTime', DateTimeType::class)
->add('gpxFilename', TextType::class, ['label' => 'GPX Filename', 'disabled' => true]);
->add('gpxFilename', TextType::class, ['label' => 'GPX Filename', 'disabled' => true])
->add('featuredImage', EntityType::class, [
'required' => false,
'class' => Image::class,
'choices' => $wander->getImages(),
'multiple' => false,
]);

} elseif ('new' === $options['type']) {
// Our form for new Wanders includes a GPX file upload. We don't
// Our form for new Wanders includes a GPX file upload. We don't
// let anything else change that.
$builder
->add('gpxFilename', FileType::class, [
Expand Down
23 changes: 23 additions & 0 deletions templates/admin/wander/show.html.twig
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,29 @@
<th>Number of Images</th>
<td>{{ wander.images.count }}</td>
</tr>
<tr>
<th>Featured Image</th>
<td>
{% if wander.featuredImage %}

<a class="d-block mb-0 h-100" href="{{ path('admin_image_show', {'id': wander.featuredImage.id}) }}">
<img
class="img-fluid img-thumbnail"
src="{{ vich_uploader_asset(wander.featuredImage) }}"
title="{{ wander.featuredImage.description }}"
srcset="{{ wander.featuredImage | srcset }}"
sizes="(min-width: 1200px) 262.5px,
(min-width: 992px) 25vw,
(min-width: 768px) 33.3333vw,
50vw "
/>
</a>
<div class="mx-2 image-details">{{ wander.featuredImage.title }}</div>
{% else %}
- None -
{% endif %}
</td>
</tr>
<tr>
<th>StartTime</th>
<td class="text-nowrap {{ wander.isTimeLengthSuspicious ? 'text-danger' }}">{{ wander.startTime ? wander.startTime|date('Y-m-d H:i:s T') : '' }}</td>
Expand Down
8 changes: 7 additions & 1 deletion templates/wander/feed.atom.twig
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,13 @@
<uri>https://gothick.org.uk</uri>
</author>
<content type="html">
<![CDATA[{{ wander.description |striptags|markdown }}]]>
<![CDATA[
{{ wander.description |striptags|markdown }}
{% if wander.hasFeaturedImage %}
<br />
<img src="{{ vich_uploader_asset(wander.featuredImage) | imagine_filter('open_graph_image') }}" alt="{{ wander.featuredImage.titleOrId }}" />
{% endif %}
]]>
</content>
</entry>
{% endfor %}
Expand Down
Loading