Skip to content

Commit

Permalink
Merge pull request #7 from pagemachine/rework_settings
Browse files Browse the repository at this point in the history
Rework settings and generation page
  • Loading branch information
fseipel authored Oct 10, 2024
2 parents e1f25c1 + f475f8d commit be34697
Show file tree
Hide file tree
Showing 56 changed files with 3,071 additions and 668 deletions.
4 changes: 2 additions & 2 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -32,8 +32,8 @@ jobs:
env:
PHP_VERSION: ${{matrix.php}}
TYPO3_VERSION: ${{matrix.typo3}}
run: docker-compose run --rm app composer build
run: docker compose run --rm app composer build

- name: Cleanup
if: ${{ always() }}
run: docker-compose down --volumes
run: docker compose down --volumes
72 changes: 72 additions & 0 deletions Classes/Controller/Backend/CreditsController.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
<?php

declare(strict_types=1);

namespace Pagemachine\AItools\Controller\Backend;

use Pagemachine\AItools\Service\ImageMetaDataService;
use Psr\Http\Message\ResponseInterface;
use Psr\Http\Message\ServerRequestInterface;
use TYPO3\CMS\Core\Resource\AbstractFile;
use TYPO3\CMS\Core\Resource\FileInterface;
use TYPO3\CMS\Core\Resource\ResourceFactory;
use TYPO3\CMS\Extbase\Mvc\Controller\ActionController;

class CreditsController extends ActionController
{
public function __construct(
private readonly ImageMetaDataService $imageMetaDataService,
private readonly ResourceFactory $resourceFactory,
) {
}

protected function imageRecognition(ServerRequestInterface $request): string
{
$fileIdentifier = $this->getParameter($request, 'fileIdentifier');
if ($fileIdentifier) {
$fileObject = $this->resourceFactory->retrieveFileOrFolderObject($fileIdentifier);
if ($fileObject instanceof FileInterface) {
if ($fileObject->getType() !== AbstractFile::FILETYPE_IMAGE) {
return '';
}

return $this->imageMetaDataService->priceForImageDescription($fileObject, $this->getParameter($request, 'textPrompt'));
}
}

return '';
}


public function ajaxCreditsAction(ServerRequestInterface $request): ResponseInterface
{
$text = '';
try {
switch ($this->getParameter($request, 'type')) {
case 'imageRecognition':
$text = $this->imageRecognition($request);
break;
case 'remaining':
break;
default:
throw new \Exception('Invalid type');
}
} catch (\Exception $e) {
return $this->responseFactory->createResponse()
->withHeader('Content-Type', 'application/json')
->withBody($this->streamFactory->createStream(json_encode(['error' => $e->getMessage()], JSON_THROW_ON_ERROR)));
}

return $this->responseFactory->createResponse()
->withHeader('Content-Type', 'application/json')
->withBody($this->streamFactory->createStream(json_encode(['credits' => $text])));
}

protected function getParameter(ServerRequestInterface $request, string $key): string
{
$parsedBody = $request->getParsedBody();
$queryParams = $request->getQueryParams();

return $parsedBody[$key] ?? $queryParams[$key] ?? '';
}
}
82 changes: 57 additions & 25 deletions Classes/Controller/Backend/ImageRecognizeController.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@

namespace Pagemachine\AItools\Controller\Backend;

use Pagemachine\AItools\Domain\Model\Prompt;
use Exception;
use Pagemachine\AItools\Domain\Repository\PromptRepository;
use Pagemachine\AItools\Service\ImageMetaDataService;
use Pagemachine\AItools\Service\SettingsService;
Expand Down Expand Up @@ -124,7 +124,6 @@ protected function getView(string $templateName = 'Default', $request = null): S

/**
* Gets the file object from the request target value (which is the file combined identifier)
* @return FileInterface[]|null
* @throws ResourceDoesNotExistException
*/
private function getFileObjectFromRequestTarget(ServerRequestInterface $request): ?array
Expand All @@ -133,18 +132,23 @@ private function getFileObjectFromRequestTarget(ServerRequestInterface $request)
$queryParams = $request->getQueryParams();
// Setting target, which must be a file reference to a file within the mounts.
$target = $parsedBody['target'] ?? $queryParams['target'] ?? '';
$target_language = $parsedBody['target-language'] ?? $queryParams['target-language'] ?? '';

// create the file object
if ($target) {
$fileObject = $this->resourceFactory->retrieveFileOrFolderObject($target);
if ($fileObject instanceof FileInterface) {
if ($fileObject->getType() !== AbstractFile::FILETYPE_IMAGE) {
return null;
}
return [$fileObject];

return [$this->addMetaToFile($fileObject, [$target_language])];
}
if ($fileObject instanceof FolderInterface) {
$files = $fileObject->getFiles();
$files = array_filter($files, fn($file) => $file->getType() === AbstractFile::FILETYPE_IMAGE);
$files = array_map(fn($file) => $this->addMetaToFile($file, [$target_language]), $files);

return $files;
}
}
Expand Down Expand Up @@ -190,30 +194,44 @@ public function ajaxMetaGenerateAction(ServerRequestInterface $request): Respons
return $this->responseFactory->createResponse(500, 'Insufficient permissions');
}

$version = GeneralUtility::makeInstance(VersionNumberUtility::class)->getNumericTypo3Version();
$parsedBody = $request->getParsedBody();
$queryParams = $request->getQueryParams();
$action = $parsedBody['action'] ?? $queryParams['action'] ?? null;

if (!is_null($action)) {
try {
return $this->ajaxData($request);
} catch (Exception $e) {
return $this->responseFactory->createResponse()
->withHeader('Content-Type', 'application/json')
->withBody($this->streamFactory->createStream(json_encode(['error' => $e->getMessage()], JSON_THROW_ON_ERROR)));
}
}

return $this->ajaxData($request);
}

protected function ajaxData(ServerRequestInterface $request): ResponseInterface
{
$parsedBody = $request->getParsedBody();
$queryParams = $request->getQueryParams();

$fileObjects = $this->getFileObjectFromRequestTarget($request);

$allPrompts = $this->promptRepository->findAll();
if (version_compare($version, '11.0', '>=') && version_compare($version, '12.0', '<')) {
// for TYPO3 v11
// @phpstan-ignore-next-line
$defaultPrompt = $this->promptRepository->findOneByDefault(true);
} else {
/**
* @var Prompt $defaultPrompt
* @phpstan-ignore-next-line
*/
$defaultPrompt = $this->promptRepository->findOneBy(['default' => true]);
}

$defaultPrompt = $this->promptRepository->getDefaultPromptText();

$siteLanguages = $this->getAllSiteLanguages();

// get default language
$defaultLanguage = $this->getLanguageById(0);
$defaultTwoLetterIsoCode = $this->getLocaleLanguageCode($defaultLanguage);
$modal = $parsedBody['modal'] ?? $queryParams['modal'] ?? false;

$target_language = $parsedBody['target-language'] ?? $queryParams['target-language'] ?? null;
if (is_null($target_language)) {
throw new Exception("No target language", 1727169730);
}
$targetLanguage = $this->getLanguageById((int) $target_language);
$targetTwoLetterIsoCode = $this->getLocaleLanguageCode($targetLanguage);

// Setting target, which must be a file reference to a file within the mounts.
$action = $parsedBody['action'] ?? $queryParams['action'] ?? '';
Expand All @@ -222,15 +240,15 @@ public function ajaxMetaGenerateAction(ServerRequestInterface $request): Respons
case 'saveMetaData':
$altText = $parsedBody['altText'] ?? $queryParams['altText'] ?? '';
$doTranslate = $parsedBody['translate'] ?? $queryParams['translate'] ?? false;
$saved = $this->imageMetaDataService->saveMetaData($target, $altText);
$saved = $this->imageMetaDataService->saveMetaData($target, $altText, (int) $target_language);

$translations = [];
if ($doTranslate) {
// fetch all site languages and translate the altText
foreach ($siteLanguages as $siteLanguage) {
// only translate additional languages (skip default language)
if ($siteLanguage->getLanguageId() > 0) {
$altTextTranslated = $this->translationService->translateText($altText, $defaultTwoLetterIsoCode, $this->getLocaleLanguageCode($siteLanguage));
// only translate additional languages (skip current language)
if ($siteLanguage->getLanguageId() !== (int) $target_language) {
$altTextTranslated = $this->translationService->translateText($altText, $targetTwoLetterIsoCode, $this->getLocaleLanguageCode($siteLanguage));
$metaDataUid = $this->imageMetaDataService->saveMetaData($target, $altTextTranslated, $siteLanguage->getLanguageId());
$translations[] = [
'languageId' => $siteLanguage->getLanguageId(),
Expand All @@ -252,12 +270,12 @@ public function ajaxMetaGenerateAction(ServerRequestInterface $request): Respons
->withHeader('Content-Type', 'application/json')
->withBody($this->streamFactory->createStream(json_encode($returnArray)));
case 'generateMetaData':
$textPrompt = $parsedBody['textPrompt'] ?? $queryParams['textPrompt'] ?: ($defaultPrompt != null ? $defaultPrompt->getPrompt() : '');
$textPrompt = $parsedBody['textPrompt'] ?? $queryParams['textPrompt'] ?: ($defaultPrompt != null ? $defaultPrompt : '');
$altTextFromImage = $this->imageMetaDataService->generateImageDescription(
fileObject: $fileObjects[0],
fileObject: $fileObjects[0]['file'],
textPrompt: $textPrompt,
);
$altText = $this->translationService->translateText($altTextFromImage, 'en', $defaultTwoLetterIsoCode);
$altText = $this->translationService->translateText($altTextFromImage, 'en', $targetTwoLetterIsoCode);
$data = ['alternative' => $altText, 'baseAlternative' => $altTextFromImage];
return $this->responseFactory->createResponse()
->withHeader('Content-Type', 'application/json')
Expand All @@ -268,10 +286,14 @@ public function ajaxMetaGenerateAction(ServerRequestInterface $request): Respons
// create custom fluid template html view
$view = $this->getView('AjaxMetaGenerate', $request);

$moduleTemplate->getDocHeaderComponent()->disable();

$view->assign('siteLanguages', $siteLanguages);
$view->assign('action', $action);
$view->assign('target', $target);
$view->assign('fileObjects', $fileObjects ?? null);
$view->assign('targetLanguage', (int) $target_language);
$view->assign('modal', $modal);

$view->assign(
'textPrompt',
Expand All @@ -290,6 +312,16 @@ public function ajaxMetaGenerateAction(ServerRequestInterface $request): Respons
}
}

protected function addMetaToFile($fileObject, $languages): array
{
$meta = $this->imageMetaDataService->getMetaDataLanguages($fileObject, $languages);

return [
'file' => $fileObject,
'meta' => $meta[0],
];
}

public function getLocaleLanguageCode(SiteLanguage $siteLanguage): string
{
$version = GeneralUtility::makeInstance(VersionNumberUtility::class)->getNumericTypo3Version();
Expand Down
72 changes: 72 additions & 0 deletions Classes/Controller/Backend/PromptsController.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
<?php

declare(strict_types=1);

namespace Pagemachine\AItools\Controller\Backend;

use Pagemachine\AItools\Domain\Repository\PromptRepository;
use Psr\Http\Message\ResponseInterface;
use TYPO3\CMS\Backend\Routing\UriBuilder;
use TYPO3\CMS\Backend\Template\Components\ButtonBar;
use TYPO3\CMS\Backend\Template\ModuleTemplate;
use TYPO3\CMS\Backend\Template\ModuleTemplateFactory;
use TYPO3\CMS\Core\Imaging\Icon;
use TYPO3\CMS\Core\Imaging\IconFactory;
use TYPO3\CMS\Core\Localization\LanguageService;
use TYPO3\CMS\Core\Utility\GeneralUtility;
use TYPO3\CMS\Extbase\Mvc\Controller\ActionController;

class PromptsController extends ActionController
{

public function __construct(
private readonly PromptRepository $promptRepository,
private readonly ModuleTemplateFactory $moduleTemplateFactory,
private readonly IconFactory $iconFactory,
) {
}

private function setDocHeader(ModuleTemplate $moduleTemplate, $requestUri): void
{
$uriBuilder = GeneralUtility::makeInstance(UriBuilder::class);

$buttonBar = $moduleTemplate->getDocHeaderComponent()->getButtonBar();

$newRecordButton = $buttonBar->makeLinkButton()
->setHref((string)$uriBuilder->buildUriFromRoute(
'record_edit',
[
'edit' => [
'tx_aitools_domain_model_prompt' => ['new'],
],
'returnUrl' => (string)$requestUri,
]
))
->setTitle('Add')
->setIcon($this->iconFactory->getIcon('actions-add', Icon::SIZE_SMALL));

$buttonBar->addButton($newRecordButton, ButtonBar::BUTTON_POSITION_LEFT, 10);
}

public function listAction(): ResponseInterface
{
$moduleTemplate = $this->moduleTemplateFactory->create($this->request);

$requestUri = $this->request->getAttribute('normalizedParams')->getRequestUri();

$this->view->assignMultiple([
'prompts' => $this->promptRepository->listAllPrompts(),
'returnUrl' => $requestUri,
]);


$moduleTemplate->setContent($this->view->render());
$this->setDocHeader($moduleTemplate, $requestUri);
return $this->htmlResponse($moduleTemplate->renderContent());
}

protected function getLanguageService(): LanguageService
{
return $GLOBALS['LANG'];
}
}
Loading

0 comments on commit be34697

Please sign in to comment.