-
Notifications
You must be signed in to change notification settings - Fork 13
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: add test button and active field
- Loading branch information
Showing
21 changed files
with
445 additions
and
9 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,141 @@ | ||
<?php declare(strict_types=1); | ||
|
||
namespace Frosh\ThumbnailProcessor\Controller\Api; | ||
|
||
use Shopware\Core\Content\Media\Aggregate\MediaThumbnail\MediaThumbnailEntity; | ||
use Shopware\Core\Content\Media\File\FileFetcher; | ||
use Shopware\Core\Content\Media\File\FileSaver; | ||
use Shopware\Core\Content\Media\MediaEntity; | ||
use Shopware\Core\Content\Media\Pathname\UrlGeneratorInterface; | ||
use Shopware\Core\Framework\Context; | ||
use Shopware\Core\Framework\DataAbstractionLayer\EntityRepository; | ||
use Shopware\Core\Framework\DataAbstractionLayer\Search\Criteria; | ||
use Shopware\Core\Framework\DataAbstractionLayer\Search\Filter\EqualsFilter; | ||
use Shopware\Core\Framework\Validation\DataBag\RequestDataBag; | ||
use Shopware\Core\PlatformRequest; | ||
use Symfony\Component\HttpFoundation\JsonResponse; | ||
use Symfony\Component\HttpFoundation\Request; | ||
use Symfony\Component\Routing\Annotation\Route; | ||
|
||
#[Route(defaults: ['_routeScope' => ['api']])] | ||
class TestController | ||
{ | ||
public const REQUEST_ATTRIBUTE_TEST_ACTIVE = 'FroshPlatformThumbnailProcessorTestActive'; | ||
|
||
public function __construct( | ||
private readonly UrlGeneratorInterface $urlGenerator, | ||
private readonly EntityRepository $mediaRepository, | ||
private readonly EntityRepository $mediaFolderRepository, | ||
private readonly FileSaver $fileSaver, | ||
private readonly FileFetcher $fileFetcher | ||
) { | ||
} | ||
|
||
#[Route(path: '/api/_action/thumbnail-processor-test/get-sample-image')] | ||
public function check(Request $request, RequestDataBag $dataBag): JsonResponse | ||
{ | ||
if (!$dataBag->has('salesChannelId')) { | ||
return new JsonResponse(['success' => false]); | ||
} | ||
|
||
$testFile = \realpath(__DIR__ . '/../../Resources/data/froshthumbnailprocessortestimage.jpg'); | ||
|
||
if (!\is_string($testFile) || !\is_file($testFile)) { | ||
throw new \RuntimeException(\sprintf('Test file at "%s" is missing', $testFile)); | ||
} | ||
|
||
$fileContent = \file_get_contents($testFile); | ||
|
||
if (!\is_string($fileContent)) { | ||
throw new \RuntimeException(\sprintf('Test file at "%s" could not be read', $testFile)); | ||
} | ||
|
||
$request->attributes->set(self::REQUEST_ATTRIBUTE_TEST_ACTIVE, '1'); | ||
|
||
$salesChannelId = $dataBag->get('salesChannelId'); | ||
if (\is_string($salesChannelId)) { | ||
$request->attributes->set(PlatformRequest::ATTRIBUTE_SALES_CHANNEL_ID, $salesChannelId); | ||
} | ||
|
||
$media = $this->getSampleMedia($fileContent, $testFile); | ||
|
||
$thumbnail = new MediaThumbnailEntity(); | ||
$thumbnail->setWidth(200); | ||
$thumbnail->setHeight(200); | ||
|
||
return new JsonResponse(['url' => $this->urlGenerator->getAbsoluteThumbnailUrl($media, $thumbnail)]); | ||
} | ||
|
||
private function getProductFolderId(Context $context): string | ||
{ | ||
$criteria = (new Criteria()) | ||
->addFilter(new EqualsFilter('media_folder.defaultFolder.entity', 'product')) | ||
->addAssociation('defaultFolder') | ||
->setLimit(1); | ||
|
||
$ids = $this->mediaFolderRepository | ||
->searchIds($criteria, $context) | ||
->getIds(); | ||
|
||
if (\is_string($ids[0])) { | ||
return $ids[0]; | ||
} | ||
|
||
throw new \RuntimeException('Media folder for product could not have been found!'); | ||
} | ||
|
||
private function getSampleMedia(string $fileContent, string $testFile): MediaEntity | ||
{ | ||
$context = Context::createDefaultContext(); | ||
$mediaId = \hash('xxh128', $fileContent); | ||
|
||
$existingMedia = $this->getMediaById($mediaId, $context); | ||
if ($existingMedia) { | ||
return $existingMedia; | ||
} | ||
|
||
$mediaFolderId = $this->getProductFolderId($context); | ||
|
||
$this->mediaRepository->upsert( | ||
[ | ||
[ | ||
'id' => $mediaId, | ||
'mediaFolderId' => $mediaFolderId, | ||
], | ||
], | ||
$context | ||
); | ||
|
||
$pathInfo = pathinfo($testFile); | ||
if (empty($pathInfo['extension'])) { | ||
$pathInfo['extension'] = 'jpg'; | ||
} | ||
|
||
$uploadedFile = $this->fileFetcher->fetchBlob( | ||
$fileContent, | ||
$pathInfo['extension'], | ||
'image/' . $pathInfo['extension'] | ||
); | ||
|
||
$this->fileSaver->persistFileToMedia( | ||
$uploadedFile, | ||
$pathInfo['filename'], | ||
$mediaId, | ||
$context | ||
); | ||
|
||
$existingMedia = $this->getMediaById($mediaId, $context); | ||
if ($existingMedia) { | ||
return $existingMedia; | ||
} | ||
|
||
throw new \RuntimeException('Media has not been saved!'); | ||
} | ||
|
||
private function getMediaById(string $id, Context $context): ?MediaEntity | ||
{ | ||
$criteria = new Criteria([$id]); | ||
|
||
return $this->mediaRepository->search($criteria, $context)->getEntities()->first(); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,57 @@ | ||
<?php declare(strict_types=1); | ||
|
||
namespace Frosh\ThumbnailProcessor\Migration; | ||
|
||
use Doctrine\DBAL\Connection; | ||
use Shopware\Core\Framework\Migration\MigrationStep; | ||
|
||
class Migration1686772873AddActiveConfig extends MigrationStep | ||
{ | ||
public function getCreationTimestamp(): int | ||
{ | ||
return 1686772873; | ||
} | ||
|
||
public function update(Connection $connection): void | ||
{ | ||
$currentPluginVersion = $this->getPluginVersion($connection); | ||
|
||
if (empty($currentPluginVersion)) { | ||
return; | ||
} | ||
|
||
// we added the active flag with version 3.0.3, so we don't need to set the default value afterward | ||
if (\version_compare($currentPluginVersion, '3.0.3', '>')) { | ||
return; | ||
} | ||
|
||
$connection->update( | ||
'system_config', | ||
[ | ||
'configuration_value' => '{"_value": true}', | ||
], | ||
['configuration_key' => 'FroshPlatformThumbnailProcessor.config.Active'] | ||
); | ||
} | ||
|
||
public function updateDestructive(Connection $connection): void | ||
{ | ||
} | ||
|
||
private function getPluginVersion(Connection $connection): ?string | ||
{ | ||
$builder = $connection->createQueryBuilder()->select('`version`') | ||
->from('plugin') | ||
->where('`name` = :pluginName') | ||
->andWhere('`active` = 1') | ||
->setParameter('pluginName', 'FroshPlatformThumbnailProcessor'); | ||
|
||
$result = $builder->executeQuery()->fetchOne(); | ||
|
||
if (\is_string($result)) { | ||
return $result; | ||
} | ||
|
||
return null; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1 +1,3 @@ | ||
import './frosh-thumbnail-processor-info-texts'; | ||
import './module/frosh-thumbnail-processor/frosh-thumbnail-processor-info-texts'; | ||
import './module/frosh-thumbnail-processor/test-button' | ||
import './service/thumbnailProcessorTestService'; |
File renamed without changes.
File renamed without changes.
File renamed without changes.
12 changes: 12 additions & 0 deletions
12
src/Resources/app/administration/src/module/frosh-thumbnail-processor/snippet/en-GB.json
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
{ | ||
"thumbnail-processor": { | ||
"test": { | ||
"title": "Service Test", | ||
"success": "Seems good! Please check the displayed sample image to contain lighten trees view.", | ||
"error": { | ||
"general": "There was an error loading the image. Please check the url and setting.", | ||
"noResize": "The used service does not resize the image." | ||
} | ||
} | ||
} | ||
} |
122 changes: 122 additions & 0 deletions
122
src/Resources/app/administration/src/module/frosh-thumbnail-processor/test-button/index.js
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,122 @@ | ||
const {Component, Mixin} = Shopware; | ||
import template from './test-button.html.twig'; | ||
import './style.css'; | ||
|
||
Component.register('thumbnailprocessor-test', { | ||
template, | ||
|
||
props: ['btnLabel'], | ||
inject: ['thumbnailProcessorTest'], | ||
|
||
mixins: [ | ||
Mixin.getByName('notification') | ||
], | ||
|
||
data() { | ||
return { | ||
isLoading: false, | ||
isSuccessful: false, | ||
}; | ||
}, | ||
|
||
computed: { | ||
pluginSalesChannelId() { | ||
let configData = this.$parent; | ||
for (let i = 0; i < 20; i++) { | ||
if (typeof configData.currentSalesChannelId != "undefined") { | ||
return configData.currentSalesChannelId; | ||
} | ||
|
||
configData = configData.$parent; | ||
} | ||
|
||
throw "Can not get pluginConfigData"; | ||
} | ||
}, | ||
|
||
methods: { | ||
finish() { | ||
this.isSuccessful = false; | ||
}, | ||
|
||
showError(message, sampleUrl) { | ||
this.isSuccessful = false; | ||
|
||
if (sampleUrl) { | ||
message += ' sample url: ' + sampleUrl; | ||
} | ||
|
||
this.createNotificationError({ | ||
title: this.$tc('thumbnail-processor.test.title'), | ||
message: message | ||
}); | ||
}, | ||
|
||
saveAndCheck() { | ||
this.isLoading = true; | ||
this.systemConfigSaveAll(); | ||
}, | ||
|
||
check() { | ||
const me = this; | ||
|
||
me.thumbnailProcessorTest.getUrl(this.pluginSalesChannelId).then((res) => { | ||
if (res.url) { | ||
me.isSuccessful = true; | ||
|
||
const img = document.createElement('img'); | ||
img.width = 200; | ||
img.height = 200; | ||
|
||
img.onload = function() { | ||
if (img.naturalWidth !== 200) { | ||
me.showError(me.$tc('thumbnail-processor.test.error.noResize'), res.url); | ||
} | ||
}; | ||
|
||
img.onerror = function() { | ||
me.showError(me.$tc('thumbnail-processor.test.error.general'), res.url); | ||
}; | ||
|
||
img.src = res.url; | ||
|
||
const testElement = document.querySelector('[name="FroshPlatformThumbnailProcessor.config.test"]'); | ||
const testImage = testElement.querySelector('.frosh-thumbnail-processor-testimage img'); | ||
|
||
if (testImage) { | ||
testImage.replaceWith(img); | ||
} else { | ||
const testImageContainer = document.createElement('p'); | ||
testImageContainer.classList.add('frosh-thumbnail-processor-testimage'); | ||
testImageContainer.appendChild(img); | ||
testElement.appendChild(testImageContainer); | ||
} | ||
} else { | ||
me.showError(me.$tc('thumbnail-processor.test.error.general')); | ||
} | ||
|
||
setTimeout(() => { | ||
this.isLoading = false; | ||
}, 2500); | ||
}); | ||
}, | ||
|
||
systemConfigSaveAll() { | ||
const me = this; | ||
let el = this.$parent; | ||
|
||
for (let i = 0; i < 30; i++) { | ||
if (typeof el.$refs.systemConfig != "undefined") { | ||
return el.$refs.systemConfig.saveAll() | ||
.then(() => { | ||
me.check(); | ||
}) | ||
} | ||
|
||
el = el.$parent; | ||
} | ||
|
||
throw "Can not get systemConfig"; | ||
} | ||
} | ||
}) |
3 changes: 3 additions & 0 deletions
3
src/Resources/app/administration/src/module/frosh-thumbnail-processor/test-button/style.css
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
.frosh-thumbnail-processor-testimage { | ||
margin: 20px 0; | ||
} |
8 changes: 8 additions & 0 deletions
8
...app/administration/src/module/frosh-thumbnail-processor/test-button/test-button.html.twig
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
<div> | ||
<sw-button-process | ||
:isLoading="isLoading" | ||
:processSuccess="isSuccessful" | ||
@process-finish="finish" | ||
@click="saveAndCheck" | ||
>{{ btnLabel }}</sw-button-process> | ||
</div> |
Oops, something went wrong.