Initial commit - Typo3 11.5.41
This commit is contained in:
@@ -0,0 +1,169 @@
|
||||
<?php
|
||||
|
||||
namespace GeorgRinger\News\Domain\Service;
|
||||
|
||||
use GeorgRinger\News\Domain\Model\Dto\EmConfiguration;
|
||||
use GeorgRinger\News\Domain\Repository\CategoryRepository;
|
||||
use Psr\EventDispatcher\EventDispatcherInterface;
|
||||
use Psr\Log\LoggerAwareInterface;
|
||||
use Psr\Log\LoggerAwareTrait;
|
||||
use TYPO3\CMS\Core\Resource\File;
|
||||
use TYPO3\CMS\Core\Resource\Folder;
|
||||
use TYPO3\CMS\Core\Resource\Index\FileIndexRepository;
|
||||
use TYPO3\CMS\Core\Resource\ProcessedFile;
|
||||
use TYPO3\CMS\Core\Resource\ResourceFactory;
|
||||
use TYPO3\CMS\Core\Resource\ResourceStorage;
|
||||
use TYPO3\CMS\Core\Utility\GeneralUtility;
|
||||
use TYPO3\CMS\Extbase\Object\ObjectManager;
|
||||
use TYPO3\CMS\Extbase\Persistence\Generic\PersistenceManager;
|
||||
|
||||
/**
|
||||
* This file is part of the "news" Extension for TYPO3 CMS.
|
||||
*
|
||||
* For the full copyright and license information, please read the
|
||||
* LICENSE.txt file that was distributed with this source code.
|
||||
*/
|
||||
class AbstractImportService implements LoggerAwareInterface
|
||||
{
|
||||
use LoggerAwareTrait;
|
||||
|
||||
const UPLOAD_PATH = 'uploads/tx_news/';
|
||||
|
||||
/**
|
||||
* @var ObjectManager
|
||||
*/
|
||||
protected $objectManager;
|
||||
|
||||
/**
|
||||
* @var PersistenceManager
|
||||
*/
|
||||
protected $persistenceManager;
|
||||
|
||||
/**
|
||||
* @var array
|
||||
*/
|
||||
protected $postPersistQueue = [];
|
||||
|
||||
/**
|
||||
* @var EmConfiguration
|
||||
*/
|
||||
protected $emSettings;
|
||||
|
||||
/**
|
||||
* @var Folder
|
||||
*/
|
||||
protected $importFolder;
|
||||
|
||||
/**
|
||||
* @var EventDispatcherInterface
|
||||
*/
|
||||
protected $eventDispatcher;
|
||||
|
||||
/**
|
||||
* @var CategoryRepository
|
||||
*/
|
||||
protected $categoryRepository;
|
||||
/**
|
||||
* AbstractImportService constructor.
|
||||
* @param PersistenceManager $persistenceManager
|
||||
* @param EmConfiguration $emSettings
|
||||
* @param ObjectManager $objectManager
|
||||
* @param CategoryRepository $categoryRepository
|
||||
* @param EventDispatcherInterface $eventDispatcher
|
||||
*/
|
||||
public function __construct(
|
||||
PersistenceManager $persistenceManager,
|
||||
ObjectManager $objectManager,
|
||||
CategoryRepository $categoryRepository,
|
||||
EventDispatcherInterface $eventDispatcher
|
||||
) {
|
||||
$this->emSettings = GeneralUtility::makeInstance(EmConfiguration::class);
|
||||
$this->persistenceManager = $persistenceManager;
|
||||
$this->objectManager = $objectManager;
|
||||
$this->categoryRepository = $categoryRepository;
|
||||
$this->eventDispatcher = $eventDispatcher;
|
||||
}
|
||||
|
||||
/**
|
||||
* Compares 2 files by using its filesize
|
||||
*
|
||||
* @param string $file1 Absolute path and filename to file1
|
||||
* @param string $file2 Absolute path and filename to file2
|
||||
* @return bool
|
||||
*/
|
||||
protected function filesAreEqual($file1, $file2): bool
|
||||
{
|
||||
return filesize($file1) === filesize($file2);
|
||||
}
|
||||
|
||||
/**
|
||||
* Find a existing file by its hash
|
||||
*
|
||||
* @param string $hash
|
||||
*
|
||||
* @return File|ProcessedFile|null
|
||||
*/
|
||||
protected function findFileByHash($hash)
|
||||
{
|
||||
$file = null;
|
||||
|
||||
$files = $this->getFileIndexRepository()->findByContentHash($hash);
|
||||
if (count($files)) {
|
||||
foreach ($files as $fileInfo) {
|
||||
if ($fileInfo['storage'] > 0) {
|
||||
$file = $this->getResourceFactory()->getFileObjectByStorageAndIdentifier(
|
||||
$fileInfo['storage'],
|
||||
$fileInfo['identifier']
|
||||
);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return $file;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get import Folder
|
||||
*
|
||||
* TODO: catch exception when storage/folder does not exist and return readable message to the user
|
||||
*
|
||||
* @return Folder
|
||||
*/
|
||||
protected function getImportFolder(): Folder
|
||||
{
|
||||
if ($this->importFolder === null) {
|
||||
$this->importFolder = $this->getResourceFactory()->getFolderObjectFromCombinedIdentifier($this->emSettings->getStorageUidImporter() . ':' . $this->emSettings->getResourceFolderImporter());
|
||||
}
|
||||
return $this->importFolder;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an instance of the FileIndexRepository
|
||||
*
|
||||
* @return FileIndexRepository
|
||||
*/
|
||||
protected function getFileIndexRepository(): FileIndexRepository
|
||||
{
|
||||
return FileIndexRepository::getInstance();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get resource storage
|
||||
*
|
||||
* @return ResourceStorage
|
||||
*/
|
||||
protected function getResourceStorage(): ResourceStorage
|
||||
{
|
||||
return $this->getResourceFactory()->getStorageObject($this->emSettings->getStorageUidImporter());
|
||||
}
|
||||
|
||||
/**
|
||||
* @return ResourceFactory
|
||||
*/
|
||||
protected function getResourceFactory(): ResourceFactory
|
||||
{
|
||||
/** @var ResourceFactory $resourceFactory */
|
||||
$resourceFactory = GeneralUtility::makeInstance(ResourceFactory::class);
|
||||
return $resourceFactory;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,263 @@
|
||||
<?php
|
||||
|
||||
namespace GeorgRinger\News\Domain\Service;
|
||||
|
||||
use GeorgRinger\News\Domain\Model\Category;
|
||||
use GeorgRinger\News\Domain\Model\Dto\EmConfiguration;
|
||||
use GeorgRinger\News\Domain\Model\FileReference;
|
||||
use GeorgRinger\News\Domain\Repository\CategoryRepository;
|
||||
use GeorgRinger\News\Event\CategoryImportPostHydrateEvent;
|
||||
use Psr\EventDispatcher\EventDispatcherInterface;
|
||||
use TYPO3\CMS\Core\Resource\Exception\ResourceDoesNotExistException;
|
||||
use TYPO3\CMS\Core\Resource\File;
|
||||
use TYPO3\CMS\Core\Utility\GeneralUtility;
|
||||
use TYPO3\CMS\Extbase\Object\ObjectManager;
|
||||
use TYPO3\CMS\Extbase\Persistence\Generic\PersistenceManager;
|
||||
|
||||
/**
|
||||
* This file is part of the "news" Extension for TYPO3 CMS.
|
||||
*
|
||||
* For the full copyright and license information, please read the
|
||||
* LICENSE.txt file that was distributed with this source code.
|
||||
*/
|
||||
class CategoryImportService extends AbstractImportService
|
||||
{
|
||||
const ACTION_SET_PARENT_CATEGORY = 1;
|
||||
const ACTION_CREATE_L10N_CHILDREN_CATEGORY = 2;
|
||||
|
||||
/**
|
||||
* CategoryImportService constructor.
|
||||
* @param PersistenceManager $persistenceManager
|
||||
* @param EmConfiguration $emSettings
|
||||
* @param ObjectManager $objectManager
|
||||
* @param CategoryRepository $categoryRepository
|
||||
* @param EventDispatcherInterface $eventDispatcher
|
||||
*/
|
||||
public function __construct(
|
||||
PersistenceManager $persistenceManager,
|
||||
ObjectManager $objectManager,
|
||||
CategoryRepository $categoryRepository,
|
||||
EventDispatcherInterface $eventDispatcher
|
||||
) {
|
||||
parent::__construct($persistenceManager, $objectManager, $categoryRepository, $eventDispatcher);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array $importArray
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function import(array $importArray): void
|
||||
{
|
||||
$this->logger->info(sprintf('Starting import for %s categories', count($importArray)));
|
||||
|
||||
// Sort import array to import the default language first
|
||||
foreach ($importArray as $importItem) {
|
||||
$category = $this->hydrateCategory($importItem);
|
||||
|
||||
if (!empty($importItem['title_lang_ol'])) {
|
||||
$this->postPersistQueue[$importItem['import_id']] = [
|
||||
'category' => $category,
|
||||
'importItem' => $importItem,
|
||||
'action' => self::ACTION_CREATE_L10N_CHILDREN_CATEGORY,
|
||||
'titleLanguageOverlay' => $importItem['title_lang_ol']
|
||||
];
|
||||
}
|
||||
|
||||
if ($importItem['parentcategory']) {
|
||||
$this->postPersistQueue[$importItem['import_id']] = [
|
||||
'category' => $category,
|
||||
'action' => self::ACTION_SET_PARENT_CATEGORY,
|
||||
'parentCategoryOriginUid' => $importItem['parentcategory']
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
$this->persistenceManager->persistAll();
|
||||
|
||||
foreach ($this->postPersistQueue as $queueItem) {
|
||||
switch ($queueItem['action']) {
|
||||
case self::ACTION_SET_PARENT_CATEGORY:
|
||||
$this->setParentCategory($queueItem);
|
||||
break;
|
||||
case self::ACTION_CREATE_L10N_CHILDREN_CATEGORY:
|
||||
$this->createL10nChildrenCategory($queueItem);
|
||||
break;
|
||||
default:
|
||||
// do nothing
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
$this->persistenceManager->persistAll();
|
||||
}
|
||||
|
||||
/**
|
||||
* Hydrate a category record with the given array
|
||||
*
|
||||
* @param array $importItem
|
||||
*
|
||||
* @return array|object
|
||||
*/
|
||||
protected function hydrateCategory(array $importItem)
|
||||
{
|
||||
$category = $this->categoryRepository->findOneByImportSourceAndImportId(
|
||||
$importItem['import_source'],
|
||||
$importItem['import_id']
|
||||
);
|
||||
|
||||
$this->logger->info(sprintf(
|
||||
'Import of category from source "%s" with id "%s"',
|
||||
$importItem['import_source'],
|
||||
$importItem['import_id']
|
||||
));
|
||||
|
||||
if (is_null($category)) {
|
||||
$this->logger->info('Category is new');
|
||||
|
||||
$category = GeneralUtility::makeInstance(Category::class);
|
||||
$this->categoryRepository->add($category);
|
||||
} else {
|
||||
$this->logger->info(sprintf('Category exists already with id "%s".', $category->getUid()));
|
||||
}
|
||||
|
||||
$category->setPid($importItem['pid']);
|
||||
$category->setHidden($importItem['hidden']);
|
||||
$category->setStarttime($importItem['starttime']);
|
||||
$category->setEndtime($importItem['endtime']);
|
||||
$category->setCrdate($importItem['crdate']);
|
||||
$category->setTstamp($importItem['tstamp']);
|
||||
$category->setTitle($importItem['title']);
|
||||
$category->setDescription($importItem['description']);
|
||||
if (!empty($importItem['image'])) {
|
||||
$this->setFileRelationFromImage($category, $importItem['image']);
|
||||
}
|
||||
$category->setShortcut($importItem['shortcut']);
|
||||
$category->setSinglePid($importItem['single_pid']);
|
||||
|
||||
$category->setImportId($importItem['import_id']);
|
||||
$category->setImportSource($importItem['import_source']);
|
||||
|
||||
$event = $this->eventDispatcher->dispatch(new CategoryImportPostHydrateEvent($this, $importItem, $category));
|
||||
|
||||
return $event->getCategory();
|
||||
}
|
||||
|
||||
/**
|
||||
* Add category image when not already present
|
||||
*
|
||||
* @param Category $category
|
||||
* @param $image
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
protected function setFileRelationFromImage($category, $image)
|
||||
{
|
||||
|
||||
// get fileObject by given identifier (file UID, combined identifier or path/filename)
|
||||
try {
|
||||
$newImage = $this->getResourceFactory()->retrieveFileOrFolderObject($image);
|
||||
} catch (ResourceDoesNotExistException $exception) {
|
||||
$newImage = false;
|
||||
}
|
||||
|
||||
// only proceed if image is found
|
||||
if (!$newImage instanceof File) {
|
||||
return;
|
||||
}
|
||||
|
||||
// new image found check if this isn't already
|
||||
$existingImages = $category->getImages();
|
||||
if (!is_null($existingImages) && $existingImages->count() !== 0) {
|
||||
/** @var $item FileReference */
|
||||
foreach ($existingImages as $item) {
|
||||
// only check already persisted items
|
||||
if ($item->getFileUid() === (int)$newImage->getUid()
|
||||
||
|
||||
($item->getUid() &&
|
||||
$item->getOriginalResource()->getName() === $newImage->getName() &&
|
||||
$item->getOriginalResource()->getSize() === (int)$newImage->getSize())
|
||||
) {
|
||||
$newImage = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ($newImage) {
|
||||
// file not inside a storage then search for existing file or copy the one form storage 0 to the import folder
|
||||
if ($newImage->getStorage()->getUid() === 0) {
|
||||
|
||||
// search DB for same file based on hash (to prevent duplicates)
|
||||
$existingFile = $this->findFileByHash($newImage->getSha1());
|
||||
|
||||
// no exciting file then copy file to import folder
|
||||
if ($existingFile === null) {
|
||||
$newImage = $this->getResourceStorage()->copyFile($newImage, $this->getImportFolder());
|
||||
} else {
|
||||
$newImage = $existingFile;
|
||||
}
|
||||
}
|
||||
|
||||
$fileReference = GeneralUtility::makeInstance(FileReference::class);
|
||||
$fileReference->setFileUid($newImage->getUid());
|
||||
$fileReference->setPid($category->getPid());
|
||||
$category->addImage($fileReference);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Set parent category
|
||||
*
|
||||
* @param array $queueItem
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
protected function setParentCategory(array $queueItem): void
|
||||
{
|
||||
/** @var $category Category */
|
||||
$category = $queueItem['category'];
|
||||
$parentCategoryOriginUid = $queueItem['parentCategoryOriginUid'];
|
||||
|
||||
if (is_null($parentCategory = $this->postPersistQueue[$parentCategoryOriginUid]['category'])) {
|
||||
$parentCategory = $this->categoryRepository->findOneByImportSourceAndImportId(
|
||||
$category->getImportSource(),
|
||||
$parentCategoryOriginUid
|
||||
);
|
||||
}
|
||||
|
||||
if ($parentCategory !== null) {
|
||||
$category->setParentcategory($parentCategory);
|
||||
$this->categoryRepository->update($category);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Create l10n relation
|
||||
*
|
||||
* @param array $queueItem
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
protected function createL10nChildrenCategory(array $queueItem): void
|
||||
{
|
||||
/** @var $category Category */
|
||||
$category = $queueItem['category'];
|
||||
$titleLanguageOverlay = GeneralUtility::trimExplode('|', $queueItem['titleLanguageOverlay']);
|
||||
|
||||
foreach ($titleLanguageOverlay as $key => $title) {
|
||||
$sysLanguageUid = $key + 1;
|
||||
|
||||
$importItem = $queueItem['importItem'];
|
||||
$importItem['import_id'] = $importItem['import_id'] . '|L:' . $sysLanguageUid;
|
||||
|
||||
/** @var $l10nChildrenCategory Category */
|
||||
$l10nChildrenCategory = $this->hydrateCategory($importItem);
|
||||
$this->categoryRepository->add($l10nChildrenCategory);
|
||||
|
||||
$l10nChildrenCategory->setTitle($title);
|
||||
$l10nChildrenCategory->setL10nParent((int)$category->getUid());
|
||||
$l10nChildrenCategory->setSysLanguageUid((int)$sysLanguageUid);
|
||||
}
|
||||
}
|
||||
}
|
||||
411
typo3conf/ext/news/Classes/Domain/Service/NewsImportService.php
Normal file
411
typo3conf/ext/news/Classes/Domain/Service/NewsImportService.php
Normal file
@@ -0,0 +1,411 @@
|
||||
<?php
|
||||
|
||||
namespace GeorgRinger\News\Domain\Service;
|
||||
|
||||
use GeorgRinger\News\Domain\Model\Dto\EmConfiguration;
|
||||
use GeorgRinger\News\Domain\Model\FileReference;
|
||||
use GeorgRinger\News\Domain\Model\Link;
|
||||
use GeorgRinger\News\Domain\Model\News;
|
||||
use GeorgRinger\News\Domain\Repository\CategoryRepository;
|
||||
use GeorgRinger\News\Domain\Repository\NewsRepository;
|
||||
use GeorgRinger\News\Domain\Repository\TtContentRepository;
|
||||
use GeorgRinger\News\Event\NewsImportPostHydrateEvent;
|
||||
use GeorgRinger\News\Event\NewsImportPreHydrateEvent;
|
||||
use Psr\EventDispatcher\EventDispatcherInterface;
|
||||
use TYPO3\CMS\Core\Resource\Exception\ResourceDoesNotExistException;
|
||||
use TYPO3\CMS\Core\Resource\File;
|
||||
use TYPO3\CMS\Core\Utility\GeneralUtility;
|
||||
use TYPO3\CMS\Extbase\Object\ObjectManager;
|
||||
use TYPO3\CMS\Extbase\Persistence\Generic\PersistenceManager;
|
||||
use TYPO3\CMS\Extbase\Persistence\ObjectStorage;
|
||||
|
||||
/**
|
||||
* This file is part of the "news" Extension for TYPO3 CMS.
|
||||
*
|
||||
* For the full copyright and license information, please read the
|
||||
* LICENSE.txt file that was distributed with this source code.
|
||||
*/
|
||||
class NewsImportService extends AbstractImportService
|
||||
{
|
||||
const ACTION_IMPORT_L10N_OVERLAY = 1;
|
||||
|
||||
/**
|
||||
* @var NewsRepository
|
||||
*/
|
||||
protected $newsRepository;
|
||||
|
||||
/**
|
||||
* @var TtContentRepository
|
||||
*/
|
||||
protected $ttContentRepository;
|
||||
|
||||
/**
|
||||
* @var array
|
||||
*/
|
||||
protected $settings = [];
|
||||
|
||||
/**
|
||||
* NewsImportService constructor.
|
||||
* @param PersistenceManager $persistenceManager
|
||||
* @param EmConfiguration $emSettings
|
||||
* @param ObjectManager $objectManager
|
||||
* @param CategoryRepository $categoryRepository
|
||||
* @param EventDispatcherInterface $eventDispatcher
|
||||
* @param NewsRepository $newsRepository
|
||||
* @param TtContentRepository $ttContentRepository
|
||||
*/
|
||||
public function __construct(
|
||||
PersistenceManager $persistenceManager,
|
||||
ObjectManager $objectManager,
|
||||
CategoryRepository $categoryRepository,
|
||||
EventDispatcherInterface $eventDispatcher,
|
||||
NewsRepository $newsRepository,
|
||||
TtContentRepository $ttContentRepository
|
||||
) {
|
||||
parent::__construct($persistenceManager, $objectManager, $categoryRepository, $eventDispatcher);
|
||||
$this->newsRepository = $newsRepository;
|
||||
$this->ttContentRepository = $ttContentRepository;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array $importItem
|
||||
*
|
||||
* @return array|object
|
||||
*/
|
||||
protected function initializeNewsRecord(array $importItem)
|
||||
{
|
||||
$news = null;
|
||||
|
||||
$this->logger->info(sprintf(
|
||||
'Import of news from source "%s" with id "%s"',
|
||||
$importItem['import_source'],
|
||||
$importItem['import_id']
|
||||
));
|
||||
|
||||
if ($importItem['import_source'] && $importItem['import_id']) {
|
||||
$news = $this->newsRepository->findOneByImportSourceAndImportId(
|
||||
$importItem['import_source'],
|
||||
$importItem['import_id']
|
||||
);
|
||||
}
|
||||
|
||||
if ($news === null) {
|
||||
$news = GeneralUtility::makeInstance(News::class);
|
||||
$this->newsRepository->add($news);
|
||||
} else {
|
||||
$this->logger->info(sprintf('News exists already with id "%s".', $news->getUid()));
|
||||
$this->newsRepository->update($news);
|
||||
}
|
||||
|
||||
return $news;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param News $news
|
||||
* @param array $importItem
|
||||
* @param array $importItemOverwrite
|
||||
* @return News
|
||||
*/
|
||||
protected function hydrateNewsRecord(
|
||||
News $news,
|
||||
array $importItem,
|
||||
array $importItemOverwrite
|
||||
): News {
|
||||
if (!empty($importItemOverwrite)) {
|
||||
$importItem = array_merge($importItem, $importItemOverwrite);
|
||||
}
|
||||
$news->setPid($importItem['pid']);
|
||||
$news->setHidden($importItem['hidden']);
|
||||
if ($importItem['starttime']) {
|
||||
$news->setStarttime($importItem['starttime']);
|
||||
}
|
||||
if ($importItem['endtime']) {
|
||||
$news->setStarttime($importItem['endtime']);
|
||||
}
|
||||
if (!empty($importItem['fe_group'])) {
|
||||
$news->setFeGroup((string)$importItem['fe_group']);
|
||||
}
|
||||
$news->setTstamp($importItem['tstamp']);
|
||||
$news->setCrdate($importItem['crdate']);
|
||||
$news->setSysLanguageUid($importItem['sys_language_uid']);
|
||||
$news->setSorting((int)$importItem['sorting']);
|
||||
|
||||
$news->setTitle($importItem['title']);
|
||||
$news->setTeaser($importItem['teaser']);
|
||||
$news->setBodytext($importItem['bodytext']);
|
||||
|
||||
$news->setType((string)$importItem['type']);
|
||||
$news->setKeywords($importItem['keywords']);
|
||||
$news->setDescription($importItem['description']);
|
||||
$news->setDatetime(new \DateTime(date('Y-m-d H:i:sP', $importItem['datetime'])));
|
||||
$news->setArchive(new \DateTime(date('Y-m-d H:i:sP', $importItem['archive'])));
|
||||
|
||||
$contentElementUidArray = GeneralUtility::trimExplode(',', $importItem['content_elements'], true);
|
||||
foreach ($contentElementUidArray as $contentElementUid) {
|
||||
if (is_object($contentElement = $this->ttContentRepository->findByUid($contentElementUid))) {
|
||||
$news->addContentElement($contentElement);
|
||||
}
|
||||
}
|
||||
|
||||
$news->setInternalurl($importItem['internalurl']);
|
||||
$news->setExternalurl($importItem['externalurl']);
|
||||
|
||||
$news->setAuthor($importItem['author']);
|
||||
$news->setAuthorEmail($importItem['author_email']);
|
||||
|
||||
$news->setImportId($importItem['import_id']);
|
||||
$news->setImportSource($importItem['import_source']);
|
||||
|
||||
$news->setPathSegment($importItem['path_segment']);
|
||||
|
||||
if (is_array($importItem['categories'])) {
|
||||
foreach ($importItem['categories'] as $categoryUid) {
|
||||
if ($this->settings['findCategoriesByImportSource']) {
|
||||
$category = $this->categoryRepository->findOneByImportSourceAndImportId(
|
||||
$this->settings['findCategoriesByImportSource'],
|
||||
$categoryUid
|
||||
);
|
||||
} else {
|
||||
$category = $this->categoryRepository->findByUid($categoryUid);
|
||||
}
|
||||
|
||||
if ($category) {
|
||||
$news->addCategory($category);
|
||||
} else {
|
||||
$this->logger->warning(sprintf('Category with ID "%s" was not found', $categoryUid));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// media relation
|
||||
if (is_array($importItem['media'])) {
|
||||
foreach ($importItem['media'] as $mediaItem) {
|
||||
// get fileobject by given identifier (file UID, combined identifier or path/filename)
|
||||
try {
|
||||
$file = $this->getResourceFactory()->retrieveFileOrFolderObject($mediaItem['image']);
|
||||
} catch (ResourceDoesNotExistException $exception) {
|
||||
$file = null;
|
||||
}
|
||||
|
||||
// no file found skip processing of this item
|
||||
if ($file === null) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// file not inside a storage then search for same file based on hash (to prevent duplicates)
|
||||
if ($file->getStorage()->getUid() === 0) {
|
||||
$existingFile = $this->findFileByHash($file->getSha1());
|
||||
if ($existingFile !== null) {
|
||||
$file = $existingFile;
|
||||
}
|
||||
}
|
||||
|
||||
/** @var $media FileReference */
|
||||
if (!$media = $this->getIfFalRelationIfAlreadyExists($news->getFalMedia(), $file)) {
|
||||
|
||||
// file not inside a storage copy the one form storage 0 to the import folder
|
||||
if ($file->getStorage()->getUid() === 0) {
|
||||
$file = $this->getResourceStorage()->copyFile($file, $this->getImportFolder());
|
||||
}
|
||||
|
||||
$media = GeneralUtility::makeInstance(FileReference::class);
|
||||
$media->setFileUid($file->getUid());
|
||||
$news->addFalMedia($media);
|
||||
}
|
||||
|
||||
if ($media) {
|
||||
$media->setTitle($mediaItem['title']);
|
||||
$media->setAlternative($mediaItem['alt']);
|
||||
$media->setDescription($mediaItem['caption']);
|
||||
$media->setShowinpreview($mediaItem['showinpreview']);
|
||||
$media->setPid($importItem['pid']);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// related files
|
||||
if (is_array($importItem['related_files'])) {
|
||||
foreach ($importItem['related_files'] as $fileItem) {
|
||||
|
||||
// get fileObject by given identifier (file UID, combined identifier or path/filename)
|
||||
try {
|
||||
$file = $this->getResourceFactory()->retrieveFileOrFolderObject($fileItem['file']);
|
||||
} catch (ResourceDoesNotExistException $exception) {
|
||||
$file = null;
|
||||
}
|
||||
|
||||
// no file found skip processing of this item
|
||||
if ($file === null) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// file not inside a storage then search for same file based on hash (to prevent duplicates)
|
||||
if ($file->getStorage()->getUid() === 0) {
|
||||
$existingFile = $this->findFileByHash($file->getSha1());
|
||||
if ($existingFile !== null) {
|
||||
$file = $existingFile;
|
||||
}
|
||||
}
|
||||
|
||||
/** @var $relatedFile FileReference */
|
||||
if (!$relatedFile = $this->getIfFalRelationIfAlreadyExists($news->getFalRelatedFiles(), $file)) {
|
||||
|
||||
// file not inside a storage copy the one form storage 0 to the import folder
|
||||
if ($file->getStorage()->getUid() === 0) {
|
||||
$file = $this->getResourceStorage()->copyFile($file, $this->getImportFolder());
|
||||
}
|
||||
|
||||
$relatedFile = GeneralUtility::makeInstance(FileReference::class);
|
||||
$relatedFile->setFileUid($file->getUid());
|
||||
$news->addFalRelatedFile($relatedFile);
|
||||
}
|
||||
|
||||
if ($relatedFile) {
|
||||
$relatedFile->setTitle($fileItem['title']);
|
||||
$relatedFile->setDescription($fileItem['description']);
|
||||
$relatedFile->setPid($importItem['pid']);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (is_array($importItem['related_links'])) {
|
||||
foreach ($importItem['related_links'] as $link) {
|
||||
/** @var $relatedLink Link */
|
||||
if (($relatedLink = $this->getRelatedLinkIfAlreadyExists($news, $link['uri'])) === false) {
|
||||
$relatedLink = GeneralUtility::makeInstance(Link::class);
|
||||
$relatedLink->setUri($link['uri']);
|
||||
$news->addRelatedLink($relatedLink);
|
||||
}
|
||||
$relatedLink->setTitle($link['title']);
|
||||
$relatedLink->setDescription($link['description']);
|
||||
$relatedLink->setPid($importItem['pid']);
|
||||
}
|
||||
}
|
||||
$event = $this->eventDispatcher->dispatch(new NewsImportPostHydrateEvent($this, $importItem, $news));
|
||||
|
||||
return $event->getNews();
|
||||
}
|
||||
|
||||
/**
|
||||
* Import
|
||||
*
|
||||
* @param array $importData
|
||||
* @param array $importItemOverwrite
|
||||
* @param array $settings
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function import(array $importData, array $importItemOverwrite = [], $settings = []): void
|
||||
{
|
||||
$this->settings = $settings;
|
||||
$this->logger->info(sprintf('Starting import for %s news', count($importData)));
|
||||
|
||||
foreach ($importData as $importItem) {
|
||||
$event = $this->eventDispatcher->dispatch(new NewsImportPreHydrateEvent($this, $importItem));
|
||||
$importItem = $event->getImportItem();
|
||||
|
||||
// Store language overlay in post persist queue
|
||||
if ((int)$importItem['sys_language_uid'] > 0 && (string)$importItem['l10n_parent'] !== '0') {
|
||||
$this->postPersistQueue[$importItem['import_id']] = [
|
||||
'action' => self::ACTION_IMPORT_L10N_OVERLAY,
|
||||
'category' => null,
|
||||
'importItem' => $importItem
|
||||
];
|
||||
continue;
|
||||
}
|
||||
|
||||
$news = $this->initializeNewsRecord($importItem);
|
||||
|
||||
$this->hydrateNewsRecord($news, $importItem, $importItemOverwrite);
|
||||
}
|
||||
|
||||
$this->persistenceManager->persistAll();
|
||||
|
||||
foreach ($this->postPersistQueue as $queueItem) {
|
||||
if ($queueItem['action'] == self::ACTION_IMPORT_L10N_OVERLAY) {
|
||||
$this->importL10nOverlay($queueItem, $importItemOverwrite);
|
||||
}
|
||||
}
|
||||
|
||||
$this->persistenceManager->persistAll();
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array $queueItem
|
||||
* @param array $importItemOverwrite
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
protected function importL10nOverlay(array $queueItem, array $importItemOverwrite): void
|
||||
{
|
||||
$importItem = $queueItem['importItem'];
|
||||
$parentNews = $this->newsRepository->findOneByImportSourceAndImportId(
|
||||
$importItem['import_source'],
|
||||
$importItem['l10n_parent'],
|
||||
true
|
||||
);
|
||||
|
||||
if (!empty($parentNews)) {
|
||||
$news = $this->initializeNewsRecord($importItem);
|
||||
|
||||
$this->hydrateNewsRecord($news, $importItem, $importItemOverwrite);
|
||||
|
||||
$news->setSysLanguageUid($importItem['sys_language_uid']);
|
||||
$news->setL10nParent($parentNews['uid']);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get an existing items from the references that matches the file
|
||||
*
|
||||
* @param ObjectStorage $items
|
||||
* @param \TYPO3\CMS\Core\Resource\File $file
|
||||
*
|
||||
* @return bool|FileReference
|
||||
*/
|
||||
protected function getIfFalRelationIfAlreadyExists(
|
||||
ObjectStorage $items,
|
||||
File $file
|
||||
) {
|
||||
$result = false;
|
||||
if ($items->count() !== 0) {
|
||||
/** @var $item FileReference */
|
||||
foreach ($items as $item) {
|
||||
// only check already persisted items
|
||||
if ($item->getFileUid() === (int)$file->getUid()
|
||||
||
|
||||
($item->getUid() &&
|
||||
$item->getOriginalResource()->getName() === $file->getName() &&
|
||||
$item->getOriginalResource()->getSize() === (int)$file->getSize())
|
||||
) {
|
||||
$result = $item;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get an existing related link object
|
||||
*
|
||||
* @param News $news
|
||||
* @param string $uri
|
||||
* @return bool|Link
|
||||
*/
|
||||
protected function getRelatedLinkIfAlreadyExists(News $news, $uri)
|
||||
{
|
||||
$result = false;
|
||||
$links = $news->getRelatedLinks();
|
||||
|
||||
if (!empty($links) && $links->count() !== 0) {
|
||||
foreach ($links as $link) {
|
||||
if ($link->getUri() === $uri) {
|
||||
$result = $link;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return $result;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user