diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..42cd73d
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1 @@
+/vendor/
\ No newline at end of file
diff --git a/Classes/Command/DestinationDataImportCommand.php b/Classes/Command/DestinationDataImportCommand.php
new file mode 100644
index 0000000..79e45b1
--- /dev/null
+++ b/Classes/Command/DestinationDataImportCommand.php
@@ -0,0 +1,59 @@
+setDescription('Import Destination Data Events');
+ $this->setHelp('Destination Data Events are imported');
+
+ $this->addArgument(
+ 'storage-pid',
+ InputArgument::OPTIONAL,
+ 'What is the storage pid?',
+ '6'
+ );
+ $this->addArgument(
+ 'region-uid',
+ InputArgument::OPTIONAL,
+ 'What is the region uid?',
+ '1'
+ );
+ $this->addArgument('rest-experience',
+ InputArgument::OPTIONAL,
+ 'What is the rest experience?',
+ 'stadtmarketing-erfurt'
+ );
+ $this->addArgument('files-folder',
+ InputArgument::OPTIONAL,
+ 'Where to save the image files?',
+ 'staedte/erfurt/events/'
+ );
+ }
+
+ protected function execute(InputInterface $input, OutputInterface $output)
+ {
+ Bootstrap::initializeBackendAuthentication();
+
+ return GeneralUtility::makeInstance(ObjectManager::class)
+ ->get(DestinationDataImportService::class)
+ ->import(
+ $input->getArgument('rest-experience'),
+ $input->getArgument('storage-pid'),
+ $input->getArgument('region-uid'),
+ $input->getArgument('files-folder')
+ );
+ }
+}
\ No newline at end of file
diff --git a/Classes/Command/RemoveAllCommand.php b/Classes/Command/RemoveAllCommand.php
new file mode 100644
index 0000000..38306ab
--- /dev/null
+++ b/Classes/Command/RemoveAllCommand.php
@@ -0,0 +1,28 @@
+setDescription('Remove all event data');
+ $this->setHelp('All events and associated data will be removed.');
+ }
+
+ protected function execute(InputInterface $input, OutputInterface $output)
+ {
+ Bootstrap::initializeBackendAuthentication();
+
+ return GeneralUtility::makeInstance(ObjectManager::class)
+ ->get(CleanupService::class)
+ ->deleteAllData();
+ }
+}
diff --git a/Classes/Command/RemovePastCommand.php b/Classes/Command/RemovePastCommand.php
new file mode 100644
index 0000000..c661c39
--- /dev/null
+++ b/Classes/Command/RemovePastCommand.php
@@ -0,0 +1,28 @@
+setDescription('Remove past events');
+ $this->setHelp('Past dates are removed, together with events that do not have any left dates.');
+ }
+
+ protected function execute(InputInterface $input, OutputInterface $output)
+ {
+ Bootstrap::initializeBackendAuthentication();
+
+ return GeneralUtility::makeInstance(ObjectManager::class)
+ ->get(CleanupService::class)
+ ->deletePastData();
+ }
+}
diff --git a/Classes/Controller/DateController.php b/Classes/Controller/DateController.php
new file mode 100644
index 0000000..7b5d5f1
--- /dev/null
+++ b/Classes/Controller/DateController.php
@@ -0,0 +1,182 @@
+regionRepository = $regionRepository;
+ $this->dateRepository = $dateRepository;
+ }
+
+ /**
+ * Action initializer
+ */
+ protected function initializeAction()
+ {
+ $this->pluginSettings = $this->configurationManager->getConfiguration(
+ ConfigurationManagerInterface::CONFIGURATION_TYPE_FRAMEWORK
+ );
+ }
+
+ /**
+ * action list
+ *
+ * @return void
+ */
+ public function listAction()
+ {
+ if (($this->request->hasArgument('searchword') && $this->request->getArgument('searchword') != '') ||
+ ($this->request->hasArgument('region') && $this->request->getArgument('region') != '') ||
+ ($this->request->hasArgument('start') && $this->request->getArgument('start') != '') ||
+ ($this->request->hasArgument('end') && $this->request->getArgument('end') != ''))
+ {
+ $demand = $this->createDemandFromSearch();
+ $dates = $this->dateRepository->findByDemand($demand);
+ } else {
+ $demand = $this->createDemandFromSettings();
+ $dates = $this->dateRepository->findByDemand($demand);
+ }
+ $this->view->assign('dates', $dates);
+ }
+
+ /**
+ * @return void
+ */
+ public function searchAction()
+ {
+ $arguments = GeneralUtility::_GET('tx_events_datelist');
+ $searchword = $arguments['searchword'];
+ $selRegion = $arguments['region'];
+ $start = $arguments['start'];
+ $end = $arguments['end'];
+ $considerDate = $arguments['considerDate'];
+
+ $regions = $this->regionRepository->findAll();
+ $this->view->assign('regions', $regions);
+
+ $this->view->assign('searchword', $searchword);
+ $this->view->assign('selRegion', $selRegion);
+ $this->view->assign('start', $start);
+ $this->view->assign('end', $end);
+ $this->view->assign('considerDate', $considerDate);
+ }
+
+ /**
+ * action teaser
+ *
+ * @return void
+ */
+ public function teaserAction()
+ {
+ $dates = $this->dateRepository->findByUids($this->settings['eventUids']);
+ $this->view->assign('dates', $dates);
+ }
+
+ /**
+ * action show
+ *
+ * @param \Wrm\Events\Domain\Model\Date $date
+ * @return void
+ */
+ public function showAction(\Wrm\Events\Domain\Model\Date $date)
+ {
+ $this->view->assign('date', $date);
+ }
+
+ /**
+ * @return DateDemand
+ */
+ protected function createDemandFromSettings(): DateDemand
+ {
+ $demand = $this->objectManager->get(DateDemand::class);
+
+ $demand->setRegion((string)$this->settings['region']);
+ $demand->setCategories((string)$this->settings['categories']);
+ $categoryCombination = (int)$this->settings['categoryCombination'] === 1 ? 'or' : 'and';
+ $demand->setCategoryCombination($categoryCombination);
+ $demand->setIncludeSubCategories((bool)$this->settings['includeSubcategories']);
+ $demand->setSortBy((string)$this->settings['sortByDate']);
+ $demand->setSortOrder((string)$this->settings['sortOrder']);
+ $demand->setHighlight((int)$this->settings['highlight']);
+
+ if (!empty($this->settings['limit'])) {
+ $demand->setLimit($this->settings['limit']);
+ }
+
+ return $demand;
+ }
+
+ /**
+ * @return DateDemand
+ */
+ protected function createDemandFromSearch(): DateDemand
+ {
+ $demand = $this->objectManager->get(DateDemand::class);
+
+ if ($this->request->hasArgument('region') && $this->request->getArgument('region') != '')
+ $demand->setRegion((string)$this->request->getArgument('region'));
+
+ if ($this->request->hasArgument('highlight') && $this->request->hasArgument('highlight') != '')
+ $demand->setHighlight((int)$this->settings['highlight']);
+
+ if ($this->request->hasArgument('searchword') && $this->request->getArgument('searchword') != '')
+ $demand->setSearchword((string)$this->request->getArgument('searchword'));
+
+ if ($this->request->hasArgument('start') && $this->request->getArgument('start') != '')
+ $demand->setStart(strtotime($this->request->getArgument('start') . ' 00:00'));
+
+ if ($this->request->hasArgument('end') && $this->request->getArgument('end') != '')
+ $demand->setEnd(strtotime($this->request->getArgument('end') . ' 23:59'));
+
+ if ($this->request->hasArgument('considerDate') && $this->request->getArgument('considerDate') != '')
+ $demand->setConsiderDate(strtotime($this->request->getArgument('considerDate')));
+
+ $demand->setSortBy((string)$this->settings['sortByDate']);
+ $demand->setSortOrder((string)$this->settings['sortOrder']);
+
+ if (!empty($this->settings['limit'])) {
+ $demand->setLimit($this->settings['limit']);
+ }
+
+ return $demand;
+ }
+}
diff --git a/Classes/Controller/EventController.php b/Classes/Controller/EventController.php
new file mode 100644
index 0000000..805b2a4
--- /dev/null
+++ b/Classes/Controller/EventController.php
@@ -0,0 +1,130 @@
+eventRepository = $eventRepository;
+ }
+
+ /**
+ * Action initializer
+ */
+ protected function initializeAction()
+ {
+ $this->pluginSettings = $this->configurationManager->getConfiguration(
+ ConfigurationManagerInterface::CONFIGURATION_TYPE_FRAMEWORK
+ );
+ }
+
+ /**
+ * Action list
+ *
+ * @return void
+ */
+ public function listAction()
+ {
+
+ $demand = $this->createDemandFromSettings();
+ $events = $this->eventRepository->findByDemand($demand);
+ $this->view->assign('events', $events);
+
+ }
+
+ /**
+ * Action show
+ *
+ * @param Event $event
+ * @return void
+ */
+ public function showAction(Event $event)
+ {
+ $this->view->assign('event', $event);
+ }
+
+ /**
+ * action teaser
+ *
+ * @return void
+ */
+ public function teaserAction()
+ {
+ $events = $this->eventRepository->findByUids($this->settings['eventUids']);
+ $this->view->assign('events', $events);
+ }
+
+ /**
+ * @param string $search
+ */
+ public function searchAction(): void
+ {
+ $search = '';
+ if ($this->request->hasArgument('search')) {
+ $search = $this->request->getArgument('search');
+ }
+
+ $this->view->assign('search', $search);
+ $this->view->assign('events', $this->eventRepository->findSearchWord($search));
+
+ }
+
+ /**
+ * @return EventDemand
+ */
+
+ protected function createDemandFromSettings(): EventDemand
+ {
+ $demand = $this->objectManager->get(EventDemand::class);
+
+ $demand->setRegion((string)$this->settings['region']);
+
+ $demand->setCategories((string)$this->settings['categories']);
+ $categoryCombination = (int)$this->settings['categoryCombination'] === 1 ? 'or' : 'and';
+
+ $demand->setCategoryCombination($categoryCombination);
+
+ $demand->setIncludeSubCategories((bool)$this->settings['includeSubcategories']);
+
+ $demand->setSortBy((string)$this->settings['sortByEvent']);
+ $demand->setSortOrder((string)$this->settings['sortOrder']);
+
+ $demand->setHighlight((bool)$this->settings['highlight']);
+
+ if (!empty($this->settings['limit'])) {
+ $demand->setLimit($this->settings['limit']);
+ }
+
+ return $demand;
+ }
+}
diff --git a/Classes/Domain/Model/Date.php b/Classes/Domain/Model/Date.php
new file mode 100644
index 0000000..84d596b
--- /dev/null
+++ b/Classes/Domain/Model/Date.php
@@ -0,0 +1,97 @@
+start;
+ }
+
+ /**
+ * @param \DateTime $start
+ * @return void
+ */
+ public function setStart(\DateTime $start)
+ {
+ $this->start = $start;
+ }
+
+ /**
+ * @return \DateTime end
+ */
+ public function getEnd()
+ {
+ return $this->end;
+ }
+
+ /**
+ * @param \DateTime $end
+ * @return void
+ */
+ public function setEnd(\DateTime $end)
+ {
+ $this->end = $end;
+ }
+
+ /**
+ * @return Event
+ */
+ public function getEvent(): Event
+ {
+ return $this->event;
+ }
+
+ /**
+ * @param Event $event
+ */
+ public function setEvent(Event $event): self
+ {
+ $this->event = $event;
+ return $this;
+ }
+
+ /**
+ * @param int $languageUid
+ * @return void
+ */
+ public function setLanguageUid($languageUid) {
+ $this->_languageUid = $languageUid;
+ }
+
+ /**
+ * @return int
+ */
+ public function getLanguageUid() {
+ return $this->_languageUid;
+ }
+
+}
diff --git a/Classes/Domain/Model/Dto/DateDemand.php b/Classes/Domain/Model/Dto/DateDemand.php
new file mode 100644
index 0000000..a1c3087
--- /dev/null
+++ b/Classes/Domain/Model/Dto/DateDemand.php
@@ -0,0 +1,259 @@
+sortBy;
+ }
+
+ /**
+ * @param string $sortBy
+ */
+ public function setSortBy(string $sortBy)
+ {
+ $this->sortBy = $sortBy;
+ }
+
+ /**
+ * @return string
+ */
+ public function getSortOrder(): string
+ {
+ return $this->sortOrder;
+ }
+
+ /**
+ * @param string $sortOrder
+ */
+ public function setSortOrder(string $sortOrder)
+ {
+ $this->sortOrder = $sortOrder;
+ }
+
+ /**
+ * @return string
+ */
+ public function getCategories(): string
+ {
+ return $this->categories;
+ }
+
+ /**
+ * @param string $categories
+ */
+ public function setCategories(string $categories)
+ {
+ $this->categories = $categories;
+ }
+
+ /**
+ * @return bool
+ */
+ public function getIncludeSubCategories(): bool
+ {
+ return $this->includeSubCategories;
+ }
+
+ /**
+ * @param bool $includeSubCategories
+ */
+ public function setIncludeSubCategories(bool $includeSubCategories)
+ {
+ $this->includeSubCategories = $includeSubCategories;
+ }
+
+ /**
+ * @return string
+ */
+ public function getCategoryCombination(): string
+ {
+ return $this->categoryCombination;
+ }
+
+ /**
+ * @param string $categoryCombination
+ */
+ public function setCategoryCombination(string $categoryCombination)
+ {
+ $this->categoryCombination = $categoryCombination;
+ }
+
+ /**
+ * @return string
+ */
+ public function getRegion(): string
+ {
+ return $this->region;
+ }
+
+ /**
+ * @param \Wrm\DdEvents\Domain\Model\Region $region
+ */
+ public function setRegion(string $region): void
+ {
+ $this->region = $region;
+ }
+
+ /**
+ * @return bool
+ */
+ public function getHighlight(): bool
+ {
+ return $this->highlight;
+ }
+
+ /**
+ * @param bool $highlight
+ */
+ public function setHighlight(string $highlight): void
+ {
+ $this->highlight = $highlight;
+ }
+
+ /**
+ * @return string
+ */
+ public function getLimit(): string
+ {
+ return $this->limit;
+ }
+
+ /**
+ * @param string $limit
+ */
+ public function setLimit(string $limit): void
+ {
+ $this->limit = $limit;
+ }
+
+ /**
+ * @return string
+ */
+ public function getSearchword(): string
+ {
+ return $this->searchword;
+ }
+
+ /**
+ * @param string $searchword
+ */
+ public function setSearchword(string $searchword): void
+ {
+ $this->searchword = $searchword;
+ }
+
+ /**
+ * @return string
+ */
+ public function getStart(): string
+ {
+ return $this->start;
+ }
+
+ /**
+ * @param string $start
+ */
+ public function setStart(string $start): void
+ {
+ $this->start = $start;
+ }
+
+ /**
+ * @return string
+ */
+ public function getEnd(): string
+ {
+ return $this->end;
+ }
+
+ /**
+ * @param string $end
+ */
+ public function setEnd(string $end): void
+ {
+ $this->end = $end;
+ }
+
+ /**
+ * @return bool
+ */
+ public function getConsiderDate(): bool
+ {
+ return $this->considerDate;
+ }
+
+ /**
+ * @param bool $considerDate
+ */
+ public function setConsiderDate(string $considerDate): void
+ {
+ $this->considerDate = $considerDate;
+ }
+
+}
\ No newline at end of file
diff --git a/Classes/Domain/Model/Dto/EventDemand.php b/Classes/Domain/Model/Dto/EventDemand.php
new file mode 100644
index 0000000..0367554
--- /dev/null
+++ b/Classes/Domain/Model/Dto/EventDemand.php
@@ -0,0 +1,177 @@
+sortBy;
+ }
+
+ /**
+ * @param string $sortBy
+ */
+ public function setSortBy(string $sortBy)
+ {
+ $this->sortBy = $sortBy;
+ }
+
+ /**
+ * @return string
+ */
+ public function getSortOrder(): string
+ {
+ return $this->sortOrder;
+ }
+
+ /**
+ * @param string $sortOrder
+ */
+ public function setSortOrder(string $sortOrder)
+ {
+ $this->sortOrder = $sortOrder;
+ }
+
+ /**
+ * @return string
+ */
+ public function getCategories(): string
+ {
+ return $this->categories;
+ }
+
+ /**
+ * @param string $categories
+ */
+ public function setCategories(string $categories)
+ {
+ $this->categories = $categories;
+ }
+
+ /**
+ * @return bool
+ */
+ public function getIncludeSubCategories(): bool
+ {
+ return $this->includeSubCategories;
+ }
+
+ /**
+ * @param bool $includeSubCategories
+ */
+ public function setIncludeSubCategories(bool $includeSubCategories)
+ {
+ $this->includeSubCategories = $includeSubCategories;
+ }
+
+ /**
+ * @return string
+ */
+ public function getCategoryCombination(): string
+ {
+ return $this->categoryCombination;
+ }
+
+ /**
+ * @param string $categoryCombination
+ */
+ public function setCategoryCombination(string $categoryCombination)
+ {
+ $this->categoryCombination = $categoryCombination;
+ }
+
+ /**
+ * @return string
+ */
+ public function getRegion(): string
+ {
+ return $this->region;
+ }
+
+ /**
+ * @param \Wrm\DdEvents\Domain\Model\Region $region
+ */
+ public function setRegion(string $region): void
+ {
+ $this->region = $region;
+ }
+
+ /**
+ * @return bool
+ */
+ public function getHighlight(): bool
+ {
+ return $this->highlight;
+ }
+
+ /**
+ * @param bool $hightlight
+ */
+ public function setHighlight(bool $highlight): void
+ {
+ $this->highlight = $highlight;
+ }
+
+ /**
+ * @return string
+ */
+ public function getLimit(): string
+ {
+ return $this->limit;
+ }
+
+ /**
+ * @param string $limit
+ */
+ public function setLimit(string $limit): void
+ {
+ $this->limit = $limit;
+ }
+
+
+
+}
\ No newline at end of file
diff --git a/Classes/Domain/Model/Event.php b/Classes/Domain/Model/Event.php
new file mode 100644
index 0000000..1e82129
--- /dev/null
+++ b/Classes/Domain/Model/Event.php
@@ -0,0 +1,725 @@
+
+ * @cascade remove
+ */
+ protected $dates = null;
+
+ /**
+ * organizer
+ *
+ * @var \Wrm\Events\Domain\Model\Organizer
+ */
+ protected $organizer = null;
+
+ /**
+ * region
+ *
+ * @var \Wrm\Events\Domain\Model\Region
+ */
+ protected $region = null;
+
+ /**
+ * categories
+ *
+ * @var \TYPO3\CMS\Extbase\Persistence\ObjectStorage<\TYPO3\CMS\Extbase\Domain\Model\Category>
+ */
+ protected $categories;
+
+ /**
+ * @var int
+ */
+ protected $_languageUid;
+
+ /**
+ * __construct
+ */
+ public function __construct()
+ {
+
+ //Do not remove the next line: It would break the functionality
+ $this->initStorageObjects();
+ }
+
+ /**
+ * @return void
+ */
+ protected function initStorageObjects()
+ {
+ $this->dates = new ObjectStorage();
+ }
+
+ /**
+ * Returns the globalId
+ *
+ * @return string $globalId
+ */
+ public function getGlobalId()
+ {
+ return $this->globalId;
+ }
+
+ /**
+ * @param string $globalId
+ * @return void
+ */
+ public function setGlobalId($globalId)
+ {
+ $this->globalId = $globalId;
+ }
+
+ /**
+ * @return string $title
+ */
+ public function getTitle()
+ {
+ return $this->title;
+ }
+
+ /**
+ * @param string $title
+ * @return void
+ */
+ public function setTitle($title)
+ {
+ $this->title = $title;
+ }
+
+ /**
+ * @return string $teaser
+ */
+ public function getTeaser()
+ {
+ return $this->teaser;
+ }
+
+ /**
+ * @param string $teaser
+ * @return void
+ */
+ public function setTeaser($teaser)
+ {
+ $this->teaser = $teaser;
+ }
+
+ /**
+ * @return string $details
+ */
+ public function getDetails()
+ {
+ return $this->details;
+ }
+
+ /**
+ * @param string $details
+ * @return void
+ */
+ public function setDetails($details)
+ {
+ $this->details = $details;
+ }
+
+ /**
+ * @return string $priceInfo
+ */
+ public function getPriceInfo()
+ {
+ return $this->priceInfo;
+ }
+
+ /**
+ * @param string $priceInfo
+ * @return void
+ */
+ public function setPriceInfo($priceInfo)
+ {
+ $this->priceInfo = $priceInfo;
+ }
+
+ /**
+ * @return string $name
+ */
+ public function getName()
+ {
+ return $this->name;
+ }
+
+ /**
+ * @param string $name
+ * @return void
+ */
+ public function setName($name)
+ {
+ $this->name = $name;
+ }
+
+ /**
+ * @return string $street
+ */
+ public function getStreet()
+ {
+ return $this->street;
+ }
+
+ /**
+ * @param string $street
+ * @return void
+ */
+ public function setStreet($street)
+ {
+ $this->street = $street;
+ }
+
+ /**
+ * @return string $district
+ */
+ public function getDistrict()
+ {
+ return $this->district;
+ }
+
+ /**
+ * @param string $district
+ * @return void
+ */
+ public function setDistrict($district)
+ {
+ $this->district = $district;
+ }
+
+ /**
+ * @return string $city
+ */
+ public function getCity()
+ {
+ return $this->city;
+ }
+
+ /**
+ * @param string $city
+ * @return void
+ */
+ public function setCity($city)
+ {
+ $this->city = $city;
+ }
+
+ /**
+ * @return string $zip
+ */
+ public function getZip()
+ {
+ return $this->zip;
+ }
+
+ /**
+ * @param string $zip
+ * @return void
+ */
+ public function setZip($zip)
+ {
+ $this->zip = $zip;
+ }
+
+ /**
+ * @return string
+ */
+ public function getPhone()
+ {
+ return $this->phone;
+ }
+
+ /**
+ * @param string $phone
+ */
+ public function setPhone($phone)
+ {
+ $this->phone = $phone;
+ }
+
+ /**
+ * @return string $web
+ */
+ public function getWeb()
+ {
+ return $this->web;
+ }
+
+ /**
+ * @param string $web
+ * @return void
+ */
+ public function setWeb($web)
+ {
+ $this->web = $web;
+ }
+
+ /**
+ * @return string $ticket
+ */
+ public function getTicket()
+ {
+ return $this->ticket;
+ }
+
+ /**
+ * @param string $ticket
+ * @return void
+ */
+ public function setTicket($ticket)
+ {
+ $this->ticket = $ticket;
+ }
+
+ /**
+ * @return string $facebook
+ */
+ public function getFacebook()
+ {
+ return $this->facebook;
+ }
+
+ /**
+ * @param string $facebook
+ * @return void
+ */
+ public function setFacebook($facebook)
+ {
+ $this->facebook = $facebook;
+ }
+
+ /**
+ * @return string $youtube
+ */
+ public function getYoutube()
+ {
+ return $this->youtube;
+ }
+
+ /**
+ * @param string $youtube
+ * @return void
+ */
+ public function setYoutube($youtube)
+ {
+ $this->youtube = $youtube;
+ }
+
+ /**
+ * @return string $instagram
+ */
+ public function getInstagram()
+ {
+ return $this->instagram;
+ }
+
+ /**
+ * @param string $instagram
+ */
+ public function setInstagram(string $instagram)
+ {
+ $this->instagram = $instagram;
+ }
+
+ /**
+ * @return string $latitude
+ */
+ public function getLatitude()
+ {
+ return $this->latitude;
+ }
+
+ /**
+ * @param string $latitude
+ * @return void
+ */
+ public function setLatitude($latitude)
+ {
+ $this->latitude = $latitude;
+ }
+
+ /**
+ * @return string $longitude
+ */
+ public function getLongitude()
+ {
+ return $this->longitude;
+ }
+
+ /**
+ * @param string $longitude
+ * @return void
+ */
+ public function setLongitude($longitude)
+ {
+ $this->longitude = $longitude;
+ }
+
+ /**
+ * @return \TYPO3\CMS\Extbase\Domain\Model\FileReference $images
+ */
+ public function getImages()
+ {
+ return $this->images;
+ }
+
+ /**
+ * @param \TYPO3\CMS\Extbase\Domain\Model\FileReference $images
+ * @return void
+ */
+ public function setImages(\TYPO3\CMS\Extbase\Domain\Model\FileReference $images)
+ {
+ $this->images = $images;
+ }
+
+ /**
+ * @return string $slug
+ */
+ public function getSlug()
+ {
+ return $this->slug;
+ }
+
+ /**
+ * @param string $slug
+ * @return void
+ */
+ public function setSlug($slug)
+ {
+ $this->slug = $slug;
+ }
+
+ /**
+ * @param Date $date
+ * @return Event
+ */
+ public function addDate(Date $date): self
+ {
+ $this->dates->attach($date);
+ return $this;
+ }
+
+ /**
+ * @param Date $date
+ * @return Event
+ */
+ public function removeDate(Date $date): self
+ {
+ $this->dates->detach($date);
+ return $this;
+ }
+
+ /**
+ * @return ObjectStorage
+ */
+ public function getDates(): ObjectStorage
+ {
+ return $this->dates;
+ }
+
+ /**
+ * @param ObjectStorage $dates
+ *
+ * @return Event
+ */
+ public function setDates($dates): self
+ {
+ $this->dates = $dates;
+ return $this;
+ }
+
+ /**
+ * @param ObjectStorage $dates
+ * @return void
+ */
+ public function removeAllDates(ObjectStorage $dates) {
+ $this->dates->removeAll($dates);
+ }
+
+ /**
+ * @return \Wrm\Events\Domain\Model\Organizer $organizer
+ */
+ public function getOrganizer()
+ {
+ return $this->organizer;
+ }
+
+ /**
+ * @param \Wrm\Events\Domain\Model\Organizer $organizer
+ * @return void
+ */
+ public function setOrganizer(\Wrm\Events\Domain\Model\Organizer $organizer)
+ {
+ $this->organizer = $organizer;
+ }
+
+ /**
+ * @return \Wrm\Events\Domain\Model\Region $region
+ */
+ public function getRegion()
+ {
+ return $this->region;
+ }
+
+ /**
+ * @param \Wrm\Events\Domain\Model\Region $region
+ * @return void
+ */
+ public function setRegion(\Wrm\Events\Domain\Model\Region $region)
+ {
+ $this->region = $region;
+ }
+
+ /**
+ * @return bool $highlight
+ */
+ public function getHighlight()
+ {
+ return $this->highlight;
+ }
+
+ /**
+ * @param bool $highlight
+ * @return void
+ */
+ public function setHighlight($highlight)
+ {
+ $this->highlight = $highlight;
+ }
+
+ /**
+ * @return bool
+ */
+ public function isHighlight()
+ {
+ return $this->highlight;
+ }
+
+ /**
+ * @return string $country
+ */
+ public function getCountry()
+ {
+ return $this->country;
+ }
+
+ /**
+ * @param string $country
+ * @return void
+ */
+ public function setCountry($country)
+ {
+ $this->country = $country;
+ }
+
+ /**
+ * @param \TYPO3\CMS\Extbase\Domain\Model\Category<\TYPO3\CMS\Extbase\Domain\Model\Category> $category
+ */
+ public function addCategory(\TYPO3\CMS\Extbase\Domain\Model\Category $category)
+ {
+ $this->categories->attach($category);
+ }
+
+ /**
+ * @return $categories
+ */
+ public function getCategories()
+ {
+ return $this->categories;
+ }
+
+ /**
+ * @param TYPO3\CMS\Extbase\Persistence\ObjectStorage<\TYPO3\CMS\Extbase\Domain\Model\Category> $categories
+ */
+ public function setCategories(\TYPO3\CMS\Extbase\Persistence\ObjectStorage $categories)
+ {
+ $this->categories = $categories;
+ }
+
+ /**
+ * @param int $languageUid
+ * @return void
+ */
+ public function setLanguageUid($languageUid) {
+ $this->_languageUid = $languageUid;
+ }
+
+ /**
+ * @return int
+ */
+ public function getLanguageUid() {
+ return $this->_languageUid;
+ }
+}
diff --git a/Classes/Domain/Model/Organizer.php b/Classes/Domain/Model/Organizer.php
new file mode 100644
index 0000000..b0c73d0
--- /dev/null
+++ b/Classes/Domain/Model/Organizer.php
@@ -0,0 +1,286 @@
+
+ *
+ ***/
+/**
+ * Organizer
+ */
+class Organizer extends \TYPO3\CMS\Extbase\DomainObject\AbstractEntity
+{
+
+ /**
+ * name
+ *
+ * @var string
+ */
+ protected $name = '';
+
+ /**
+ * street
+ *
+ * @var string
+ */
+ protected $street = '';
+
+ /**
+ * district
+ *
+ * @var string
+ */
+ protected $district = '';
+
+ /**
+ * city
+ *
+ * @var string
+ */
+ protected $city = '';
+
+ /**
+ * zip
+ *
+ * @var string
+ */
+ protected $zip = '';
+
+ /**
+ * phone
+ *
+ * @var string
+ */
+ protected $phone = '';
+
+ /**
+ * web
+ *
+ * @var string
+ */
+ protected $web = '';
+
+ /**
+ * email
+ *
+ * @var string
+ */
+ protected $email = '';
+
+ /**
+ * @var int
+ */
+ protected $_languageUid;
+
+ /**
+ * Returns the name
+ *
+ * @return string $name
+ */
+ public function getName()
+ {
+ return $this->name;
+ }
+
+ /**
+ * Sets the name
+ *
+ * @param string $name
+ * @return void
+ */
+ public function setName($name)
+ {
+ $this->name = $name;
+ }
+
+ /**
+ * Returns the street
+ *
+ * @return string $street
+ */
+ public function getStreet()
+ {
+ return $this->street;
+ }
+
+ /**
+ * Sets the street
+ *
+ * @param string $street
+ * @return void
+ */
+ public function setStreet($street)
+ {
+ $this->street = $street;
+ }
+
+ /**
+ * Returns the district
+ *
+ * @return string $district
+ */
+ public function getDistrict()
+ {
+ return $this->district;
+ }
+
+ /**
+ * Sets the district
+ *
+ * @param string $district
+ * @return void
+ */
+ public function setDistrict($district)
+ {
+ $this->district = $district;
+ }
+
+ /**
+ * Returns the city
+ *
+ * @return string $city
+ */
+ public function getCity()
+ {
+ return $this->city;
+ }
+
+ /**
+ * Sets the city
+ *
+ * @param string $city
+ * @return void
+ */
+ public function setCity($city)
+ {
+ $this->city = $city;
+ }
+
+ /**
+ * Returns the zip
+ *
+ * @return string $zip
+ */
+ public function getZip()
+ {
+ return $this->zip;
+ }
+
+ /**
+ * Sets the zip
+ *
+ * @param string $zip
+ * @return void
+ */
+ public function setZip($zip)
+ {
+ $this->zip = $zip;
+ }
+
+ /**
+ * Returns the phone
+ *
+ * @return string $phone
+ */
+ public function getPhone()
+ {
+ return $this->phone;
+ }
+
+ /**
+ * Sets the phone
+ *
+ * @param string $phone
+ * @return void
+ */
+ public function setPhone($phone)
+ {
+ $this->phone = $phone;
+ }
+
+ /**
+ * Returns the web
+ *
+ * @return string $web
+ */
+ public function getWeb()
+ {
+ return $this->web;
+ }
+
+ /**
+ * Sets the web
+ *
+ * @param string $web
+ * @return void
+ */
+ public function setWeb($web)
+ {
+ $this->web = $web;
+ }
+
+ /**
+ * Returns the email
+ *
+ * @return string $email
+ */
+ public function getEmail()
+ {
+ return $this->email;
+ }
+
+ /**
+ * Sets the email
+ *
+ * @param string $email
+ * @return void
+ */
+ public function setEmail($email)
+ {
+ $this->email = $email;
+ }
+
+ /**
+ * __construct
+ */
+ public function __construct()
+ {
+
+ //Do not remove the next line: It would break the functionality
+ $this->initStorageObjects();
+ }
+
+ /**
+ * Initializes all ObjectStorage properties
+ * Do not modify this method!
+ * It will be rewritten on each save in the extension builder
+ * You may modify the constructor of this class instead
+ *
+ * @return void
+ */
+ protected function initStorageObjects()
+ {
+ }
+
+ /**
+ * @param int $languageUid
+ * @return void
+ */
+ public function setLanguageUid($languageUid) {
+ $this->_languageUid = $languageUid;
+ }
+
+ /**
+ * @return int
+ */
+ public function getLanguageUid() {
+ return $this->_languageUid;
+ }
+}
diff --git a/Classes/Domain/Model/Region.php b/Classes/Domain/Model/Region.php
new file mode 100644
index 0000000..8a2b74e
--- /dev/null
+++ b/Classes/Domain/Model/Region.php
@@ -0,0 +1,90 @@
+
+ *
+ ***/
+/**
+ * Region
+ */
+class Region extends \TYPO3\CMS\Extbase\DomainObject\AbstractEntity
+{
+
+ /**
+ * title
+ *
+ * @var string
+ */
+ protected $title = '';
+
+ /**
+ * @var int
+ */
+ protected $_languageUid;
+
+ /**
+ * Returns the title
+ *
+ * @return string $title
+ */
+ public function getTitle()
+ {
+ return $this->title;
+ }
+
+ /**
+ * Sets the title
+ *
+ * @param string $title
+ * @return void
+ */
+ public function setTitle($title)
+ {
+ $this->title = $title;
+ }
+
+ /**
+ * __construct
+ */
+ public function __construct()
+ {
+
+ //Do not remove the next line: It would break the functionality
+ $this->initStorageObjects();
+ }
+
+ /**
+ * Initializes all ObjectStorage properties
+ * Do not modify this method!
+ * It will be rewritten on each save in the extension builder
+ * You may modify the constructor of this class instead
+ *
+ * @return void
+ */
+ protected function initStorageObjects()
+ {
+ }
+
+ /**
+ * @param int $languageUid
+ * @return void
+ */
+ public function setLanguageUid($languageUid) {
+ $this->_languageUid = $languageUid;
+ }
+
+ /**
+ * @return int
+ */
+ public function getLanguageUid() {
+ return $this->_languageUid;
+ }
+}
diff --git a/Classes/Domain/Repository/DateRepository.php b/Classes/Domain/Repository/DateRepository.php
new file mode 100644
index 0000000..be63ddb
--- /dev/null
+++ b/Classes/Domain/Repository/DateRepository.php
@@ -0,0 +1,160 @@
+createQuery();
+ $query->matching(
+ $query->in('uid', $uids)
+ );
+ return $query->execute();
+ }
+
+ /**
+ * @param DateDemand $demand
+ * @return QueryResultInterface
+ * @throws InvalidQueryException
+ */
+ public function findByDemand(DateDemand $demand)
+ {
+ $query = $this->createDemandQuery($demand);
+ return $query->execute();
+
+ // For testing purposes
+ // $query = $this->createDemandQueryViaBuilder($demand);
+ // return $query->execute()->fetchAll();
+ }
+
+ /**
+ * @param DateDemand $demand
+ * @return QueryInterface
+ * @throws InvalidQueryException
+ */
+ protected function createDemandQuery(DateDemand $demand): QueryInterface
+ {
+ $query = $this->createQuery();
+ $constraints = [];
+ $categories = $demand->getCategories();
+
+ if ($categories) {
+ $categoryConstraints = $this->createCategoryConstraint($query, $categories, $demand->getIncludeSubCategories());
+ if ($demand->getCategoryCombination() === 'or') {
+ $constraints['categories'] = $query->logicalOr($categoryConstraints);
+ } else {
+ $constraints['categories'] = $query->logicalAnd($categoryConstraints);
+ }
+ }
+
+ if ($demand->getRegion() !== '') {
+ $constraints['region'] = $query->equals('event.region', $demand->getRegion());
+ }
+
+ if ($demand->getHighlight() !== FALSE) {
+ $constraints['highlight'] = $query->equals('event.highlight', $demand->getHighlight());
+ }
+
+ if ($demand->getSearchword() !== '') {
+ $constraints['searchword'] = $query->logicalOr(
+ [
+ $query->like('event.title', '%' . $demand->getSearchword() . '%'),
+ $query->like('event.teaser', '%' . $demand->getSearchword() . '%')
+ ]
+ );
+ }
+
+ if ($demand->getStart() !== '' && $demand->getEnd() != '') {
+ $constraints['daterange'] = $query->logicalAnd(
+ [
+ $query->greaterThanOrEqual('start', $demand->getStart()),
+ $query->lessThanOrEqual('end', $demand->getEnd())
+ ]
+ );
+ } else {
+ $now = new \DateTime('now', new \DateTimeZone('Europe/Berlin'));
+ $constraints['untilnow'] = $query->greaterThanOrEqual('start', $now);
+ }
+
+ if ($demand->getLimit() !== '') {
+ $query->setLimit((int) $demand->getLimit());
+ }
+
+ if (!empty($constraints)) {
+ $query->matching($query->logicalAnd($constraints));
+ }
+
+ $query->setOrderings([$demand->getSortBy() => $demand->getSortOrder()]);
+
+ return $query;
+ }
+
+ /**
+ * @param QueryInterface $query
+ * @param string $categories
+ * @param bool $includeSubCategories
+ * @return array
+ * @throws InvalidQueryException
+ */
+ protected function createCategoryConstraint(QueryInterface $query, $categories, bool $includeSubCategories = false): array
+ {
+ $constraints = [];
+
+ if ($includeSubCategories) {
+ $categoryService = GeneralUtility::makeInstance(CategoryService::class);
+ $allCategories = $categoryService->getChildrenCategories($categories);
+ if (!\is_array($allCategories)) {
+ $allCategories = GeneralUtility::intExplode(',', $allCategories, true);
+ }
+ } else {
+ $allCategories = GeneralUtility::intExplode(',', $categories, true);
+ }
+
+ foreach ($allCategories as $category) {
+ $constraints[] = $query->contains('event.categories', $category);
+ }
+ return $constraints;
+ }
+
+ /**
+ * findSearchWord with Query Builder
+ * @param $search
+ */
+ public function findSearchWord($search)
+ {
+
+ $connection = GeneralUtility::makeInstance(ConnectionPool::class)
+ ->getConnectionForTable('tx_events_domain_model_date');
+
+ $queryBuilder = $connection->createQueryBuilder();
+
+ $statement = $queryBuilder
+ ->select('*')
+ ->from('tx_events_domain_model_date')
+ ->join(
+ 'tx_events_domain_model_date',
+ 'tx_events_domain_model_event',
+ 'event',
+ $queryBuilder->expr()->eq('tx_events_domain_model_date.event', $queryBuilder->quoteIdentifier('event.uid'))
+ )->where(
+ $queryBuilder->expr()->like('event.title', $queryBuilder->createNamedParameter('%' . $search . '%'))
+ )->orderBy('tx_events_domain_model_date.start');
+
+ return $statement->execute()->fetchAll();
+ }
+
+}
\ No newline at end of file
diff --git a/Classes/Domain/Repository/EventRepository.php b/Classes/Domain/Repository/EventRepository.php
new file mode 100644
index 0000000..c20a99e
--- /dev/null
+++ b/Classes/Domain/Repository/EventRepository.php
@@ -0,0 +1,146 @@
+createQuery();
+ //$query->getQuerySettings()->setRespectStoragePage(false);
+
+ $query->matching(
+ $query->in('uid', $uids)
+ );
+
+ //return $this->orderByField($query->execute(), $uids);
+
+ return $query->execute();
+ }
+
+ /**
+ * @param EventDemand $demand
+ * @return QueryResultInterface
+ * @throws InvalidQueryException
+ */
+ public function findByDemand(EventDemand $demand)
+ {
+ $query = $this->createDemandQuery($demand);
+ return $query->execute();
+ }
+
+ /**
+ * @param EventDemand $demand
+ * @return QueryInterface
+ * @throws InvalidQueryException
+ */
+ protected function createDemandQuery(EventDemand $demand): QueryInterface
+ {
+ $query = $this->createQuery();
+
+ // sorting
+ $sortBy = $demand->getSortBy();
+ if ($sortBy && $sortBy !== 'singleSelection' && $sortBy !== 'default') {
+ $order = strtolower($demand->getSortOrder()) === 'desc' ? QueryInterface::ORDER_DESCENDING : QueryInterface::ORDER_ASCENDING;
+ $query->setOrderings([$sortBy => $order]);
+ }
+
+ $constraints = [];
+
+ $categories = $demand->getCategories();
+
+ if ($categories) {
+ $categoryConstraints = $this->createCategoryConstraint($query, $categories, $demand->getIncludeSubCategories());
+ if ($demand->getCategoryCombination() === 'or') {
+ $constraints['categories'] = $query->logicalOr($categoryConstraints);
+ } else {
+ $constraints['categories'] = $query->logicalAnd($categoryConstraints);
+ }
+ }
+
+ if ($demand->getRegion() !== '') {
+ $constraints['region'] = $query->equals('region', $demand->getRegion());
+ }
+
+ if ($demand->getHighlight()) {
+ $constraints['highlight'] = $query->equals('highlight', $demand->getHighlight());
+ }
+
+ if ($demand->getLimit() !== '') {
+ $query->setLimit((int) $demand->getLimit());
+ }
+
+ if (!empty($constraints)) {
+ $query->matching($query->logicalAnd($constraints));
+ }
+ return $query;
+ }
+
+ /**
+ * @param QueryInterface $query
+ * @param string $categories
+ * @param bool $includeSubCategories
+ * @return array
+ * @throws InvalidQueryException
+ */
+ protected function createCategoryConstraint(QueryInterface $query, $categories, bool $includeSubCategories = false): array
+ {
+ $constraints = [];
+
+ if ($includeSubCategories) {
+ $categoryService = GeneralUtility::makeInstance(CategoryService::class);
+ $allCategories = $categoryService->getChildrenCategories($categories);
+ if (!\is_array($allCategories)) {
+ $allCategories = GeneralUtility::intExplode(',', $allCategories, true);
+ }
+ } else {
+ $allCategories = GeneralUtility::intExplode(',', $categories, true);
+ }
+
+ foreach ($allCategories as $category) {
+ $constraints[] = $query->contains('categories', $category);
+ }
+ return $constraints;
+ }
+
+
+ public function findSearchWord($search)
+ {
+ $query = $this->createQuery();
+ $query->matching(
+ $query->like('title', '%' . $search . '%')
+ );
+ $query->setOrderings(['title' => QueryInterface::ORDER_ASCENDING]);
+ $query->setLimit(20);
+ return $query->execute();
+ }
+
+}
\ No newline at end of file
diff --git a/Classes/Domain/Repository/OrganizerRepository.php b/Classes/Domain/Repository/OrganizerRepository.php
new file mode 100644
index 0000000..cc2b07f
--- /dev/null
+++ b/Classes/Domain/Repository/OrganizerRepository.php
@@ -0,0 +1,22 @@
+timeTracker = GeneralUtility::makeInstance(TimeTracker::class);
+ $this->cache = GeneralUtility::makeInstance(CacheManager::class)->getCache('cache_Events_category');
+ }
+
+ /**
+ * Get child categories by calling recursive function
+ * and using the caching framework to save some queries
+ *
+ * @param string $idList list of category ids to start
+ * @param int $counter
+ * @return string comma separated list of category ids
+ */
+ public function getChildrenCategories($idList, int $counter = 0)
+ {
+ $cacheIdentifier = sha1('children' . $idList);
+
+ $entry = $this->cache->get($cacheIdentifier);
+ if (!$entry) {
+ $entry = $this->getChildrenCategoriesRecursive($idList, $counter);
+ $this->cache->set($cacheIdentifier, $entry);
+ }
+
+ return $entry;
+ }
+
+ /**
+ * Get child categories
+ *
+ * @param string $idList list of category ids to start
+ * @param int $counter
+ * @return string comma separated list of category ids
+ */
+ protected function getChildrenCategoriesRecursive($idList, $counter = 0): string
+ {
+ $result = [];
+
+ // add id list to the output
+ if ($counter === 0) {
+ $newList = $this->getUidListFromRecords($idList);
+ if ($newList) {
+ $result[] = $newList;
+ }
+ }
+
+ $queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)
+ ->getQueryBuilderForTable('sys_category');
+ $res = $queryBuilder
+ ->select('uid')
+ ->from('sys_category')
+ ->where(
+ $queryBuilder->expr()->in('parent', $queryBuilder->createNamedParameter(explode(',', $idList), Connection::PARAM_INT_ARRAY))
+ )
+ ->execute();
+
+ while ($row = $res->fetch()) {
+ $counter++;
+ if ($counter > 10000) {
+ $this->timeTracker->setTSlogMessage('EXT:dd_events: one or more recursive categories where found');
+ return implode(',', $result);
+ }
+ $subcategories = $this->getChildrenCategoriesRecursive($row['uid'], $counter);
+ $result[] = $row['uid'] . ($subcategories ? ',' . $subcategories : '');
+ }
+
+ $result = implode(',', $result);
+ return $result;
+ }
+
+ /**
+ * Fetch ids again from DB to avoid false positives
+ *
+ * @param string $idList
+ * @return string
+ */
+ protected function getUidListFromRecords(string $idList): string
+ {
+ $list = [];
+ $queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)
+ ->getQueryBuilderForTable('sys_category');
+ $rows = $queryBuilder
+ ->select('uid')
+ ->from('sys_category')
+ ->where(
+ $queryBuilder->expr()->in('uid', $queryBuilder->createNamedParameter(explode(',', $idList), Connection::PARAM_INT_ARRAY))
+ )
+ ->execute()
+ ->fetchAll();
+ foreach ($rows as $row) {
+ $list[] = $row['uid'];
+ }
+
+ return implode(',', $list);
+ }
+}
diff --git a/Classes/Service/Cleanup/Database.php b/Classes/Service/Cleanup/Database.php
new file mode 100644
index 0000000..93a04bd
--- /dev/null
+++ b/Classes/Service/Cleanup/Database.php
@@ -0,0 +1,131 @@
+
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+use TYPO3\CMS\Core\Database\Connection;
+use TYPO3\CMS\Core\Database\ConnectionPool;
+use TYPO3\CMS\Core\Database\Query\QueryBuilder;
+use TYPO3\CMS\Core\Utility\GeneralUtility;
+
+class Database
+{
+ const DATE_TABLE = 'tx_events_domain_model_date';
+ const EVENT_TABLE = 'tx_events_domain_model_event';
+ const ORGANIZER_TABLE = 'tx_events_domain_model_organizer';
+
+ public function truncateTables(string ...$tableNames): void
+ {
+ foreach ($tableNames as $tableName) {
+ GeneralUtility::makeInstance(ConnectionPool::class)
+ ->getConnectionForTable($tableName)
+ ->truncate($tableName);
+ }
+ }
+
+ public function getDeletionStructureForEvents(): array
+ {
+ $dataStructure = [static::EVENT_TABLE => []];
+
+ foreach ($this->getAllRecords(static::EVENT_TABLE) as $recordToDelete) {
+ $dataStructure[static::EVENT_TABLE][$recordToDelete] = ['delete' => 1];
+ }
+
+ return $dataStructure;
+ }
+
+ private function getAllRecords(string $tableName): array
+ {
+ /* @var QueryBuilder $queryBuilder */
+ $queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)
+ ->getConnectionForTable($tableName)
+ ->createQueryBuilder();
+
+ $records = $queryBuilder->select('uid')
+ ->from($tableName)
+ ->execute()
+ ->fetchAll();
+
+ return array_map(function (array $record) {
+ return $record['uid'];
+ }, $records);
+ }
+
+ public function getPastDates(): array
+ {
+ $midnightToday = new \DateTimeImmutable('midnight today');
+
+ /* @var QueryBuilder $queryBuilder */
+ $queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)
+ ->getConnectionForTable(static::DATE_TABLE)
+ ->createQueryBuilder();
+
+ $queryBuilder->getRestrictions()->removeAll();
+
+ $records = $queryBuilder->select('uid')
+ ->from(static::DATE_TABLE)
+ ->where($queryBuilder->expr()->lte(
+ 'end',
+ $queryBuilder->createNamedParameter($midnightToday->format('Y-m-d H:i:s'))
+ ))
+ ->execute()
+ ->fetchAll();
+
+ return array_map(function (array $record) {
+ return $record['uid'];
+ }, $records);
+ }
+
+ public function deleteDates(int ...$uids)
+ {
+ /* @var QueryBuilder $queryBuilder */
+ $queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)
+ ->getQueryBuilderForTable(static::DATE_TABLE);
+
+ $queryBuilder->delete(static::DATE_TABLE)
+ ->where('uid in (:uids)')
+ ->setParameter(':uids', $uids, Connection::PARAM_INT_ARRAY)
+ ->execute();
+ }
+
+ public function getDeletionStructureForEventsWithoutDates(): array
+ {
+ $dataStructure = [static::EVENT_TABLE => []];
+ /* @var QueryBuilder $queryBuilder */
+ $queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)
+ ->getConnectionForTable(static::EVENT_TABLE)
+ ->createQueryBuilder();
+
+ $queryBuilder->getRestrictions()->removeAll();
+
+ $records = $queryBuilder->select('event.uid')
+ ->from(static::EVENT_TABLE, 'event')
+ ->leftJoin('event', static::DATE_TABLE, 'date', $queryBuilder->expr()->eq('date.event', 'event.uid'))
+ ->where($queryBuilder->expr()->isNull('date.uid'))
+ ->execute()
+ ->fetchAll();
+
+ foreach ($records as $record) {
+ $dataStructure[static::EVENT_TABLE][$record['uid']] = ['delete' => 1];
+ }
+ return $dataStructure;
+ }
+}
diff --git a/Classes/Service/Cleanup/Files.php b/Classes/Service/Cleanup/Files.php
new file mode 100644
index 0000000..367e47d
--- /dev/null
+++ b/Classes/Service/Cleanup/Files.php
@@ -0,0 +1,115 @@
+
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+use TYPO3\CMS\Core\Database\Connection;
+use TYPO3\CMS\Core\Database\ConnectionPool;
+use TYPO3\CMS\Core\Database\Query\QueryBuilder;
+use TYPO3\CMS\Core\Resource\ResourceStorage;
+use TYPO3\CMS\Core\Resource\StorageRepository;
+use TYPO3\CMS\Core\Utility\GeneralUtility;
+
+class Files
+{
+ public function deleteAll()
+ {
+ $this->delete($this->getFilesFromDb());
+ }
+
+ public function deleteDangling()
+ {
+ $this->delete($this->getFilesFromDb(function (QueryBuilder $queryBuilder) {
+ $queryBuilder->leftJoin(
+ 'file',
+ 'sys_file_reference',
+ 'reference',
+ $queryBuilder->expr()->eq('file.uid', $queryBuilder->quoteIdentifier('reference.uid_local'))
+ );
+ $queryBuilder->andWhere(
+ $queryBuilder->expr()->orX(
+ $queryBuilder->expr()->isNull('reference.uid'),
+ $queryBuilder->expr()->eq('reference.deleted', 1),
+ $queryBuilder->expr()->eq('reference.hidden', 1)
+ )
+ );
+ }));
+ }
+
+ private function delete(array $filesToDelete)
+ {
+ $uidsToRemove = [];
+
+ foreach ($filesToDelete as $fileToDelete) {
+ $this->deleteFromFal($fileToDelete['storage'], $fileToDelete['identifier']);
+ $uidsToRemove[] = $fileToDelete['uid'];
+ }
+
+ $this->deleteFromDb(... $uidsToRemove);
+ }
+
+ private function getFilesFromDb(callable $whereGenerator = null): array
+ {
+ /* @var QueryBuilder $queryBuilder */
+ $queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)
+ ->getQueryBuilderForTable('sys_file');
+
+ $queryBuilder->getRestrictions()->removeAll();
+
+ $queryBuilder->select('file.identifier', 'file.storage', 'file.uid')
+ ->from('sys_file', 'file')
+ ->where($queryBuilder->expr()->like(
+ 'file.identifier',
+ $queryBuilder->createNamedParameter('/staedte/%/events/%')
+ ));
+
+ if ($whereGenerator !== null) {
+ $whereGenerator($queryBuilder);
+ }
+
+ return $queryBuilder->execute()->fetchAll();
+ }
+
+ private function deleteFromFal(int $storageUid, string $filePath)
+ {
+ /* @var ResourceStorage $storage */
+ $storage = GeneralUtility::makeInstance(StorageRepository::class)
+ ->findByUid($storageUid);
+
+ if ($storage->hasFile($filePath) === false) {
+ return;
+ }
+
+ $storage->deleteFile($storage->getFile($filePath));
+ }
+
+ private function deleteFromDb(int ...$uids)
+ {
+ /* @var QueryBuilder $queryBuilder */
+ $queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)
+ ->getQueryBuilderForTable('sys_file');
+
+ $queryBuilder->delete('sys_file')
+ ->where('uid in (:uids)')
+ ->setParameter(':uids', $uids, Connection::PARAM_INT_ARRAY)
+ ->execute();
+ }
+}
diff --git a/Classes/Service/CleanupService.php b/Classes/Service/CleanupService.php
new file mode 100644
index 0000000..d5dbb41
--- /dev/null
+++ b/Classes/Service/CleanupService.php
@@ -0,0 +1,49 @@
+database = $database;
+ $this->files = $files;
+ }
+
+ public function deleteAllData()
+ {
+ $this->database->truncateTables(... [Database::DATE_TABLE, Database::ORGANIZER_TABLE]);
+ $this->removeViaDataHandler($this->database->getDeletionStructureForEvents());
+ $this->files->deleteAll();
+ }
+
+ public function deletePastData()
+ {
+ $this->database->deleteDates(... $this->database->getPastDates());
+ $this->removeViaDataHandler($this->database->getDeletionStructureForEventsWithoutDates());
+ $this->files->deleteDangling();
+ }
+
+ private function removeViaDataHandler(array $structure)
+ {
+ /* @var DataHandler $dataHandler */
+ $dataHandler = GeneralUtility::makeInstance(DataHandler::class);
+ $dataHandler->start([], $structure);
+ $dataHandler->process_cmdmap();
+ }
+}
diff --git a/Classes/Service/DestinationDataImportService.php b/Classes/Service/DestinationDataImportService.php
new file mode 100644
index 0000000..118f970
--- /dev/null
+++ b/Classes/Service/DestinationDataImportService.php
@@ -0,0 +1,768 @@
+eventRepository = $eventRepository;
+ $this->regionRepository = $regionRepository;
+ $this->organizerRepository = $organizerRepository;
+ $this->dateRepository = $dateRepository;
+ $this->sysCategoriesRepository = $sysCategoriesRepository;
+ $this->fileRepository = $fileRepository;
+ $this->metaDataRepository = $metaDataRepository;
+ $this->configurationManager = $configurationManager;
+ $this->persistenceManager = $persistenceManager;
+ $this->resourceFactory = $resourceFactory;
+ $this->objectManager = $objectManager;
+ $this->environment = $environment;
+
+ // Get Typoscript Settings
+ $this->settings = $this->configurationManager->getConfiguration(
+ ConfigurationManagerInterface::CONFIGURATION_TYPE_SETTINGS,
+ 'Events',
+ 'Pi1'
+ );
+
+ // Set properties
+ $this->restUrl = $this->settings['destinationData']['restUrl'];
+ $this->restLicenseKey = $this->settings['destinationData']['license'];
+ $this->restType = $this->settings['destinationData']['restType'];
+ $this->restLimit = $this->settings['destinationData']['restLimit'];
+ $this->restMode = $this->settings['destinationData']['restMode'];
+ $this->restTemplate = $this->settings['destinationData']['restTemplate'];
+ $this->sysCategoriesPid = $this->settings['destinationData']['categoriesPid'];
+ $this->categoryParentUid = $this->settings['destinationData']['categoryParentUid'];
+ }
+
+ /**
+ * @param $restExperience
+ * @param $storagePid
+ * @param $regionUid
+ * @param $filesFolder
+ */
+ public function import($restExperience, $storagePid, $regionUid, $filesFolder) {
+
+ $this->restExperience = $restExperience;
+ $this->storagePid = $storagePid;
+ $this->regionUid = $regionUid;
+ $this->filesFolder = $filesFolder;
+
+ // Get configuration
+ $frameworkConfiguration = $this->configurationManager->getConfiguration(
+ ConfigurationManagerInterface::CONFIGURATION_TYPE_FRAMEWORK
+ );
+
+ // Set storage pid
+ $persistenceConfiguration = [
+ 'persistence' => [
+ 'storagePid' => $this->storagePid,
+ ],
+ ];
+
+ // Set Configuration
+ $this->configurationManager->setConfiguration(array_merge($frameworkConfiguration, $persistenceConfiguration));
+ $this->logger = GeneralUtility::makeInstance(LogManager::class)->getLogger(__CLASS__);
+
+ $this->logger->info('Starting Destination Data Import Service');
+ $restUrl = $this->restUrl . '?experience=' . $this->restExperience . '&licensekey=' . $this->restLicenseKey . '&type=' . $this->restType . '&mode=' . $this->restMode . '&limit=' . $this->restLimit . '&template=' . $this->restTemplate;
+ $this->logger->info('Try to get data from ' . $restUrl);
+
+ if ($jsonResponse = json_decode(file_get_contents($restUrl),true)) {
+ $this->logger->info('Received data with ' . count($jsonResponse['items']) . ' items');
+ return $this->processData($jsonResponse);
+ } else {
+ $this->logger->error('Could not receive data.');
+ return 1;
+ }
+
+ }
+
+ /**
+ * @param $data
+ * @return int
+ */
+ public function processData($data) {
+
+ $this->logger->info('Processing json ' . count($data['items']));
+
+ // Get selected region
+ $selectedRegion = $this->regionRepository->findByUid($this->regionUid);
+
+ foreach ($data['items'] as $event) {
+
+ $this->logger->info('Processing event ' . substr($event['title'], 0, 20));
+
+ // Event already exists? If not create one!
+ $this->tmpCurrentEvent = $this->getOrCreateEvent($event['global_id'], $event['title']);
+
+ // Set language UID
+ $this->tmpCurrentEvent->setLanguageUid(-1);
+
+ // Set selected Region
+ $this->tmpCurrentEvent->setRegion($selectedRegion);
+
+ // Set Title
+ $this->tmpCurrentEvent->setTitle(substr($event['title'], 0, 254));
+
+ // Set Highlight (Is only set in rest if true)
+ if($event['highlight'])
+ $this->tmpCurrentEvent->setHighlight($event['highlight']);
+
+ // Set Texts
+ if($event['texts'])
+ $this->setTexts($event['texts']);
+
+ // Set address and geo data
+ if($event['name'] || $event['street'] || $event['city'] || $event['zip'] || $event['country'] || $event['web'])
+ $this->setAddress($event);
+
+ // Set LatLng
+ if($event['geo']['main']['latitude'] && $event['geo']['main']['longitude'])
+ $this->setLatLng($event['geo']['main']['latitude'], $event['geo']['main']['longitude']);
+
+ // Set Categories
+ if($event['categories'])
+ $this->setCategories($event['categories']);
+
+ // Set Organizer
+ if($event['addresses'])
+ $this->setOrganizer($event['addresses']);
+
+ // Set Social
+ if($event['media_objects'])
+ $this->setSocial($event['media_objects']);
+
+ // Set Tickets
+ if($event['media_objects'])
+ $this->setTickets($event['media_objects']);
+
+ // Set Dates
+ if($event['timeIntervals'])
+ $this->setDates($event['timeIntervals']);
+
+ // Set Assets
+ if($event['media_objects'])
+ $this->setAssets($event['media_objects']);
+
+ // Update and persist
+ $this->logger->info('Persist database');
+ $this->eventRepository->update($this->tmpCurrentEvent);
+ $this->persistenceManager->persistAll();
+
+ }
+ $this->doSlugUpdate();
+ $this->logger->info('Finished import');
+ return 0;
+ }
+
+ /**
+ *
+ * @param array $categories
+ */
+ protected function setCategories(Array $categories) {
+ $sysParentCategory = $this->sysCategoriesRepository->findByUid($this->categoryParentUid);
+ foreach ($categories as $categoryTitle) {
+ $tmpSysCategory = $this->sysCategoriesRepository->findOneByTitle($categoryTitle);
+ if (!$tmpSysCategory) {
+ $this->logger->info('Creating new category: ' . $categoryTitle);
+ $tmpSysCategory = $this->objectManager->get(\TYPO3\CMS\Extbase\Domain\Model\Category::class);
+ $tmpSysCategory->setTitle($categoryTitle);
+ $tmpSysCategory->setParent($sysParentCategory);
+ $tmpSysCategory->setPid($this->sysCategoriesPid);
+ $this->sysCategoriesRepository->add($tmpSysCategory);
+ $this->tmpCurrentEvent->addCategory($tmpSysCategory);
+ } else {
+ $this->tmpCurrentEvent->addCategory($tmpSysCategory);
+ }
+ }
+ }
+
+ /**
+ * @param array $timeIntervals
+ * @TODO: split into functions
+ */
+ protected function setDates(Array $timeIntervals) {
+
+ // @TODO: does not seem to work -->
+ //$currentEventDates = $this->tmpCurrentEvent->getDates();
+ //$this->tmpCurrentEvent->removeAllDates($currentEventDates);
+ // <--
+
+ // TODO: Workaround delete dates
+ $currentEventDates = $this->tmpCurrentEvent->getDates();
+ $this->logger->info('Found ' . count($currentEventDates) . ' to delete');
+
+ foreach ($currentEventDates as $currentDate) {
+ $this->dateRepository->remove($currentDate);
+ }
+
+ $today = new \DateTime('today');
+ $today = $today->getTimestamp();
+
+ foreach ($timeIntervals as $date) {
+
+ // Check if dates are given as interval or not
+ if (empty($date['interval'])) {
+
+ if (strtotime($date['start']) > $today) {
+ $this->logger->info('Setup single date');
+ $dateObj = $this->objectManager->get(\Wrm\Events\Domain\Model\Date::class);
+ $start = new \DateTime($date['start'], new \DateTimeZone($date['tz']));
+ $end = new \DateTime($date['end'], new \DateTimeZone($date['tz']));
+ $this->logger->info('Start transformed ' . $start->format('Y-m-d H:i'));
+ $this->logger->info('End transformed ' . $end->format('Y-m-d H:i'));
+ // Set language UID
+ $dateObj->setLanguageUid(-1);
+ $dateObj->setStart($start);
+ $dateObj->setEnd($end);
+ $this->tmpCurrentEvent->addDate($dateObj);
+ }
+
+ } else {
+
+ if ($date['freq'] == 'Daily' && empty($date['weekdays']) && !empty($date['repeatUntil'])) {
+
+ $this->logger->info('Setup daily interval dates');
+ $this->logger->info('Start ' . $date['start']);
+ $this->logger->info('End ' . $date['repeatUntil']);
+ $start = new \DateTime($date['start'], new \DateTimeZone($date['tz']));
+ $until = new \DateTime($date['repeatUntil'], new \DateTimeZone($date['tz']));
+
+ for($i = strtotime($start->format('l'), $start->getTimestamp()); $i <= $until->getTimestamp(); $i = strtotime('+1 day', $i)) {
+ if ($i >= $today) {
+ $eventStart = new \DateTime();
+ $eventStart->setTimestamp($i);
+ $eventStart->setTime($start->format('H'), $start->format('i'));
+ $eventEnd = new \DateTime();
+ $eventEnd->setTimestamp($i);
+ $eventEnd->setTime($until->format('H'), $until->format('i'));
+ $dateObj = $this->objectManager->get(\Wrm\Events\Domain\Model\Date::class);
+ $dateObj->setLanguageUid(-1);
+ $dateObj->setStart($eventStart);
+ $dateObj->setEnd($eventEnd);
+ $this->tmpCurrentEvent->addDate($dateObj);
+ }
+ }
+
+ }
+
+ else if ($date['freq'] == 'Weekly' && !empty($date['weekdays']) && !empty($date['repeatUntil'])) {
+ foreach ($date['weekdays'] as $day) {
+ $this->logger->info('Setup weekly interval dates for ' . $day);
+ $this->logger->info('Start ' . $date['start']);
+ $this->logger->info('End ' . $date['repeatUntil']);
+ $start = new \DateTime($date['start'], new \DateTimeZone($date['tz']));
+ $until = new \DateTime($date['repeatUntil'], new \DateTimeZone($date['tz']));
+
+ for($i = strtotime($day, $start->getTimestamp()); $i <= $until->getTimestamp(); $i = strtotime('+1 week', $i)) {
+ if ($i >= $today) {
+ $eventStart = new \DateTime();
+ $eventStart->setTimestamp($i);
+ $eventStart->setTime($start->format('H'), $start->format('i'));
+ $eventEnd = new \DateTime();
+ $eventEnd->setTimestamp($i);
+ $eventEnd->setTime($until->format('H'), $until->format('i'));
+ $dateObj = $this->objectManager->get(\Wrm\Events\Domain\Model\Date::class);
+ $dateObj->setLanguageUid(-1);
+ $dateObj->setStart($eventStart);
+ $dateObj->setEnd($eventEnd);
+ $this->tmpCurrentEvent->addDate($dateObj);
+ }
+ }
+ }
+ }
+ }
+ }
+ $this->logger->info('Finished setup dates');
+ }
+
+ /**
+ * @param array $addresses
+ */
+ protected function setOrganizer(Array $addresses) {
+ foreach ($addresses as $address)
+ {
+ if ($address['rel'] == "organizer") {
+ $tmpOrganizer = $this->organizerRepository->findOneByName($address['name']);
+ if ($tmpOrganizer) {
+ $this->tmpCurrentEvent->setOrganizer($tmpOrganizer);
+ continue;
+ }
+ $tmpOrganizer = $this->objectManager->get(\Wrm\Events\Domain\Model\Organizer::class);
+ $tmpOrganizer->setLanguageUid(-1);
+ $tmpOrganizer->setName($address['name']);
+ $tmpOrganizer->setCity($address['city']);
+ $tmpOrganizer->setZip($address['zip']);
+ $tmpOrganizer->setStreet($address['street']);
+ $tmpOrganizer->setPhone($address['phone']);
+ $tmpOrganizer->setWeb($address['web']);
+ $tmpOrganizer->setEmail($address['email']);
+ $tmpOrganizer->setDistrict($address['district']);
+ $this->organizerRepository->add($tmpOrganizer);
+ $this->tmpCurrentEvent->setOrganizer($tmpOrganizer);
+ }
+ }
+ }
+
+ /**
+ * @param array $event
+ */
+ protected function setAddress(Array $event) {
+ if (!empty($event['name']))
+ $this->tmpCurrentEvent->setName($event['name']);
+ if (!empty($event['street']))
+ $this->tmpCurrentEvent->setStreet($event['street']);
+ if (!empty($event['city']))
+ $this->tmpCurrentEvent->setCity($event['city']);
+ if (!empty($event['zip']))
+ $this->tmpCurrentEvent->setZip($event['zip']);
+ if (!empty($event['country']))
+ $this->tmpCurrentEvent->setCountry($event['country']);
+ if (!empty($event['phone']))
+ $this->tmpCurrentEvent->setPhone($event['phone']);
+ if (!empty($event['web']))
+ $this->tmpCurrentEvent->setWeb($event['web']);
+ }
+
+ /**
+ * @param array $media
+ */
+ protected function setSocial(Array $media) {
+ foreach ($media as $link)
+ {
+ if ($link['rel'] == "socialmedia" && $link['value'] == "Facebook")
+ $this->tmpCurrentEvent->setFacebook($link['url']);
+ if ($link['rel'] == "socialmedia" && $link['value'] == "YouTube")
+ $this->tmpCurrentEvent->setYouTube($link['url']);
+ if ($link['rel'] == "socialmedia" && $link['value'] == "Instagram")
+ $this->tmpCurrentEvent->setInstagram($link['url']);
+ }
+ }
+
+ /**
+ * @param array $media
+ */
+ protected function setTickets(Array $media) {
+ foreach ($media as $link)
+ {
+ if ($link['rel'] == "ticket") {
+ $this->tmpCurrentEvent->setTicket($link['url']);
+ break;
+ } elseif ($link['rel'] == "booking" && !$this->multi_array_key_exists('ticket', $media)) {
+ $this->tmpCurrentEvent->setTicket($link['url']);
+ break;
+ } elseif ($link['rel'] == "PRICE_KARTENLINK" && !$this->multi_array_key_exists('ticket', $media) && !$this->multi_array_key_exists('booking', $media)) {
+ $this->tmpCurrentEvent->setTicket($link['url']);
+ }
+ }
+ }
+
+ /**
+ * @param string $needle
+ * @param array $haystack
+ */
+ protected function multi_array_key_exists( $needle, $haystack ) {
+
+ foreach ( $haystack as $key => $value ) {
+ if ( $needle == $key ) {
+ return true;
+ }
+ if ( is_array( $value ) ) {
+ if ( $this->multi_array_key_exists( $needle, $value ) == true ) {
+ return true;
+ }
+ }
+ }
+ return false;
+ }
+
+ /**
+ * @param string $lat
+ * @param string $lng
+ */
+ protected function setLatLng(String $lat, String $lng) {
+ $this->tmpCurrentEvent->setLatitude($lat);
+ $this->tmpCurrentEvent->setLongitude($lng);
+ }
+
+ /**
+ * Set Texts
+ * @param Array $texts
+ */
+ protected function setTexts(Array $texts) {
+ foreach ($texts as $text)
+ {
+ if ($text['rel'] == "details" && $text['type'] == "text/plain") {
+ $this->tmpCurrentEvent->setDetails(str_replace('\n\n', '\n', $text['value']));
+ }
+ if ($text['rel'] == "teaser" && $text['type'] == "text/plain") {
+ $this->tmpCurrentEvent->setTeaser(str_replace('\n\n', '\n', $text['value']));
+ }
+ if ($text['rel'] == "PRICE_INFO" && $text['type'] == "text/plain") {
+ $this->tmpCurrentEvent->setPriceInfo(str_replace('\n\n', '\n', $text['value']));
+ }
+ }
+ }
+
+ /**
+ * Load File
+ * @param String $globalId
+ * @param String $title
+ */
+ protected function getOrCreateEvent(String $globalId, String $title) {
+
+ $event = $this->eventRepository->findOneByGlobalId($globalId);
+
+ if ($event) {
+ // Global ID is found and events gets updated
+ $event = $this->eventRepository->findOneByGlobalId($globalId);
+ $this->logger->info('Found "' . substr($title, 0, 20) . '..." with global id ' . $globalId . ' in database');
+ return $event;
+ }
+
+ // New event is created
+ $this->logger->info(substr($title, 0, 20) . ' does not exist');
+ $event = $this->objectManager->get(\Wrm\Events\Domain\Model\Event::class);
+ // Create event and persist
+ $event->setGlobalId($globalId);
+ $event->setCategories(new ObjectStorage());
+ $this->eventRepository->add($event);
+ $this->persistenceManager->persistAll();
+ $this->logger->info('Not found "' . substr($title, 0, 20) . '..." with global id ' . $globalId . ' in database. Created new one.');
+ return $event;
+ }
+
+ /**
+ * @param array $assets
+ */
+ protected function setAssets(Array $assets) {
+
+ $this->logger->info("Set assets");
+
+ $error = false;
+
+ foreach ($assets as $media_object)
+ {
+ if($media_object['rel'] == "default" && $media_object['type'] == "image/jpeg") {
+
+ $this->storage = $this->resourceFactory->getDefaultStorage();
+
+ $orgFileUrl = urldecode($media_object['url']);
+ $orgFileNameSanitized = $this->storage->sanitizeFileName(
+ basename(
+ urldecode($media_object['url'])
+ )
+ );
+
+ $this->logger->info('File attached:' . $orgFileUrl);
+ $this->logger->info('File attached sanitized:' . $orgFileNameSanitized);
+ //die();
+
+ if ($this->storage == null) {
+ $this->logger->error('No default storage defined. Cancel import.');
+ die();
+ }
+
+ // Check if file already exists
+ if (file_exists($this->environment->getPublicPath() . '/fileadmin/' . $this->filesFolder . $orgFileNameSanitized)) {
+ $this->logger->info('File already exists');
+ } else {
+ $this->logger->info("File don't exist " . $orgFileNameSanitized);
+ // Load the file
+ if ($file = $this->loadFile($orgFileUrl)) {
+ // Move file to defined folder
+ $this->logger->info('Adding file ' . $file);
+ $this->storage->addFile($this->environment->getPublicPath() . "/uploads/tx_events/" . $file, $this->storage->getFolder($this->filesFolder));
+ } else {
+ $error = true;
+ }
+ }
+
+ if ($error !== true) {
+ if ($this->tmpCurrentEvent->getImages() !== null) {
+ $this->logger->info('Relation found');
+ // TODO: How to delete file references?
+ } else {
+ $this->logger->info('No relation found');
+ $file = $this->storage->getFile($this->filesFolder . $orgFileNameSanitized);
+ $this->metaDataRepository->update($file->getUid(), array('title' => $media_object['value'], 'description' => $media_object['description'], 'alternative' => 'DD Import'));
+ $this->createFileRelations($file->getUid(), 'tx_events_domain_model_event', $this->tmpCurrentEvent->getUid(), 'images', $this->storagePid);
+ }
+ }
+
+ }
+ $error = false;
+ }
+ }
+
+ /**
+ * Load File
+ * @param string $file
+ * @return string
+ */
+ protected function loadFile($file) {
+ $directory = $this->environment->getPublicPath() . "/uploads/tx_events/";
+ $filename = basename($file);
+ $this->logger->info('Getting file ' . $file . ' as ' . $filename);
+ $asset = GeneralUtility::getUrl($file);
+ if ($asset) {
+ file_put_contents($directory . $filename, $asset);
+ return $filename;
+ }
+ $this->logger->error('Cannot load file ' . $file);
+ return false;
+ }
+
+ /**
+ * Build relations for FAL
+ * @param int $uid_local
+ * @param string $tablenames
+ * @param int $uid_foreign
+ * @param string $fieldname
+ * @param string $storagePid
+ * @return bool
+ */
+ protected function createFileRelations($uid_local, $tablenames, $uid_foreign, $fieldname, $storagePid) {
+
+ $newId = 'NEW1234';
+
+ $data = array();
+ $data['sys_file_reference'][$newId] = array(
+ 'table_local' => 'sys_file',
+ 'uid_local' => $uid_local,
+ 'tablenames' => $tablenames,
+ 'uid_foreign' => $uid_foreign,
+ 'fieldname' => $fieldname,
+ 'pid' => $storagePid
+ );
+
+ $data[$tablenames][$uid_foreign] = array(
+ 'pid' => $storagePid,
+ $fieldname => $newId
+ );
+
+ $dataHandler = $this->objectManager->get(\TYPO3\CMS\Core\DataHandling\DataHandler::class);
+ $dataHandler->start($data, array());
+ $dataHandler->process_datamap();
+
+ if (count($dataHandler->errorLog) === 0) {
+ return true;
+ }
+
+ foreach($dataHandler->errorLog as $error) {
+ $this->logger->info($error);
+ }
+ return false;
+ }
+
+ /**
+ * Performs slug update
+ * @return bool
+ */
+ protected function doSlugUpdate()
+ {
+ $this->logger->info('Update slugs');
+
+ $slugHelper = GeneralUtility::makeInstance(
+ SlugHelper::class,
+ 'tx_events_domain_model_event',
+ 'slug',
+ $GLOBALS['TCA']['tx_events_domain_model_event']['columns']['slug']['config']
+ );
+
+ $connection = GeneralUtility::makeInstance(ConnectionPool::class)->getConnectionForTable('tx_events_domain_model_event');
+ $queryBuilder = $connection->createQueryBuilder();
+ $queryBuilder->getRestrictions()->removeAll();
+
+ $statement = $queryBuilder->select('uid', 'global_id')
+ ->from('tx_events_domain_model_event')
+ ->where(
+ $queryBuilder->expr()->orX(
+ $queryBuilder->expr()->eq('slug', $queryBuilder->createNamedParameter('', \PDO::PARAM_STR)),
+ $queryBuilder->expr()->isNull('slug')
+ )
+ )
+ ->execute();
+
+ while ($record = $statement->fetch()) {
+ $queryBuilder = $connection->createQueryBuilder();
+ $queryBuilder->update('tx_events_domain_model_event')
+ ->where(
+ $queryBuilder->expr()->eq(
+ 'uid',
+ $queryBuilder->createNamedParameter($record['uid'], \PDO::PARAM_INT)
+ )
+ )
+ ->set('slug', $slugHelper->sanitize((string)$record['global_id']));
+ $queryBuilder->getSQL();
+ $queryBuilder->execute();
+ }
+
+ return true;
+ }
+}
diff --git a/Classes/ViewHelpers/FormViewHelper.php b/Classes/ViewHelpers/FormViewHelper.php
new file mode 100644
index 0000000..9231214
--- /dev/null
+++ b/Classes/ViewHelpers/FormViewHelper.php
@@ -0,0 +1,9 @@
+ [
+ 'class' => \Wrm\Events\Command\DestinationDataImportCommand::class
+ ],
+ 'events:removeAll' => [
+ 'class' => \Wrm\Events\Command\RemoveAllCommand::class
+ ],
+ 'events:removePast' => [
+ 'class' => \Wrm\Events\Command\RemovePastCommand::class
+ ],
+];
diff --git a/Configuration/ExtensionBuilder/settings.yaml b/Configuration/ExtensionBuilder/settings.yaml
new file mode 100644
index 0000000..3b52d12
--- /dev/null
+++ b/Configuration/ExtensionBuilder/settings.yaml
@@ -0,0 +1,101 @@
+#
+# Extension Builder settings for extension events
+# generated 2019-04-01T14:33:00Z
+#
+# See http://www.yaml.org/spec/1.2/spec.html
+#
+
+---
+
+########### Overwrite settings ###########
+#
+# These settings only apply, if the roundtrip feature of the extension builder
+# is enabled in the extension manager
+#
+# Usage:
+# nesting reflects the file structure
+# a setting applies to a file or recursive to all files and subfolders
+#
+# merge:
+# means for classes: All properties ,methods and method bodies
+# of the existing class will be modified according to the new settings
+# but not overwritten
+#
+# for locallang xlf files: Existing keys and labels are always
+# preserved (renaming a property or DomainObject will result in new keys and new labels)
+#
+# for other files: You will find a Split token at the end of the file
+# see: \EBT\ExtensionBuilder\Service\RoundTrip::SPLIT_TOKEN
+#
+# After this token you can write whatever you want and it will be appended
+# everytime the code is generated
+#
+# keep:
+# files are never overwritten
+# These settings may break the functionality of the extension builder!
+# Handle with care!
+#
+#
+
+############ extension settings ##############
+
+overwriteSettings:
+ Classes:
+ Controller: merge
+ Domain:
+ Model: merge
+ Repository: merge
+
+ Configuration:
+ #TCA merge not possible - use overrides directory
+ #TypoScript: keep
+
+ Resources:
+ Private:
+ #Language: merge
+ #Templates: keep
+
+ user_extension.svg: keep
+
+# ext_localconf.php: merge
+
+# ext_tables.php: merge
+
+# ext_tables.sql: merge
+
+## use static date attribute in xliff files ##
+#staticDateInXliffFiles: 2019-04-01T14:33:00Z
+
+## skip docComment (license header) ##
+#skipDocComment
+
+## list of error codes for warnings that should be ignored ##
+#ignoreWarnings:
+ #503
+
+######### settings for classBuilder #############################
+#
+# here you may define default parent classes for your classes
+# these settings only apply for new generated classes
+# you may also just change the parent class in the generated class file.
+# It will be kept on next code generation, if the overwrite settings
+# are configured to merge it
+#
+#################################################################
+
+classBuilder:
+
+ Controller:
+ parentClass: \TYPO3\CMS\Extbase\Mvc\Controller\ActionController
+
+ Model:
+ AbstractEntity:
+ parentClass: \TYPO3\CMS\Extbase\DomainObject\AbstractEntity
+
+ AbstractValueObject:
+ parentClass: \TYPO3\CMS\Extbase\DomainObject\AbstractValueObject
+
+ Repository:
+ parentClass: \TYPO3\CMS\Extbase\Persistence\Repository
+
+ setDefaultValuesForClassProperties: true
\ No newline at end of file
diff --git a/Configuration/FlexForms/DateList.xml b/Configuration/FlexForms/DateList.xml
new file mode 100644
index 0000000..e971c51
--- /dev/null
+++ b/Configuration/FlexForms/DateList.xml
@@ -0,0 +1,236 @@
+
+
+
+
+
+ Options
+
+ array
+
+
+
+ 1
+ Sort By
+
+ select
+
+
+ Start
+ start
+
+
+ End
+ end
+
+
+
+
+
+
+
+
+ 1
+ Sort Order
+
+ select
+
+
+
+ Ascending
+
+ ASC
+
+
+
+ Descending
+
+ DESC
+
+
+ ASC
+
+
+
+
+
+
+ 1
+ Max Items
+
+ input
+ 10
+ 30
+ trim
+
+
+
+
+
+
+ 1
+ Highlights only
+
+ check
+ 0
+
+
+
+
+
+
+ 1
+ Today only
+
+ check
+ 0
+
+
+
+
+
+
+ 1
+ Show pagination
+
+ check
+ 0
+
+
+
+
+
+
+ 1
+ Detail page
+
+ group
+ db
+ pages
+ 1
+ 1
+ 0
+ 1
+
+
+
+
+
+
+
+
+
+ Template
+
+ array
+
+
+ 1
+ Layout option
+
+ select
+
+
+ Default
+ default
+
+
+ Costum
+ costum
+
+
+ Table
+ table
+
+
+ Grid
+ grid
+
+
+ default
+
+
+
+
+
+
+
+
+ Regions & Categories
+
+ array
+
+
+
+ Region
+
+ select
+ tx_events_domain_model_region
+ AND tx_events_domain_model_region.deleted = 0 AND tx_events_domain_model_region.hidden = 0
+ 3
+ 0
+ 2
+
+
+
+
+
+
+ 1
+ Combination
+
+ select
+
+
+ And
+ 0
+
+
+ Or
+ 1
+
+
+ 0
+
+
+
+
+
+
+ 1
+
+ Category
+
+
+ select
+ 20
+ sys_category
+ AND sys_category.sys_language_uid IN (-1, 0) ORDER BY sys_category.title ASC
+ 1
+ tree
+ 8
+
+
+ 1
+ 1
+
+ parent
+
+
+
+
+
+
+
+ 1
+ Include Subcategories
+
+ check
+ 0
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Configuration/FlexForms/DateSearch.xml b/Configuration/FlexForms/DateSearch.xml
new file mode 100644
index 0000000..ae07a9f
--- /dev/null
+++ b/Configuration/FlexForms/DateSearch.xml
@@ -0,0 +1,39 @@
+
+
+
+
+
+ Options
+
+ array
+
+
+
+ 1
+ Results page
+
+ group
+ db
+ pages
+ 1
+ 1
+ 0
+ 1
+
+
+
+
+
+ 1
+ Show Regions
+
+ check
+ 0
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Configuration/FlexForms/DateShow.xml b/Configuration/FlexForms/DateShow.xml
new file mode 100644
index 0000000..b3eea3d
--- /dev/null
+++ b/Configuration/FlexForms/DateShow.xml
@@ -0,0 +1,57 @@
+
+
+
+
+
+ Options
+
+ array
+
+
+
+ 1
+ Back page
+
+ group
+ db
+ pages
+ 1
+ 1
+ 0
+ 1
+
+
+
+
+
+
+
+
+
+ Template
+
+ array
+
+
+ 1
+ Layout option
+
+ select
+
+
+ Default
+ default
+
+
+ Costum
+ costum
+
+
+ default
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Configuration/FlexForms/Pi1.xml b/Configuration/FlexForms/Pi1.xml
new file mode 100644
index 0000000..2b7084d
--- /dev/null
+++ b/Configuration/FlexForms/Pi1.xml
@@ -0,0 +1,402 @@
+
+
+
+
+
+ Options
+
+ array
+
+
+
+ Controller action
+ reload
+
+ select
+
+
+ Event List
+ Event->list
+
+
+ Event Teaser
+ Event->teaser
+
+
+ Event Show
+ Event->show
+
+
+ Date List
+ Date->list
+
+
+
+ Date Show
+ Date->show
+
+
+
+ Event Search
+ Event->search
+
+
+
+ Date Search
+ Date->search
+
+
+
+
+
+
+
+
+
+ 1
+ Sort By
+ FIELD:switchableControllerActions:=:Event->list
+
+ select
+
+
+ Title
+ title
+
+
+ Region
+ region
+
+
+
+
+
+
+
+
+ 1
+ Sort By
+
+
+ FIELD:switchableControllerActions:=:Date->list
+ FIELD:switchableControllerActions:=:Date->search
+
+
+
+ select
+
+
+ Start
+ start
+
+
+ End
+ end
+
+
+
+
+
+
+
+
+ 1
+ Sort Order
+
+
+ FIELD:switchableControllerActions:=:Event->list
+ FIELD:switchableControllerActions:=:Date->list
+ FIELD:switchableControllerActions:=:Date->search
+
+
+
+ select
+
+
+
+ Ascending
+
+ ASC
+
+
+
+ Descending
+
+ DESC
+
+
+ ASC
+
+
+
+
+
+
+ 1
+ Max Items
+
+
+ FIELD:switchableControllerActions:=:Event->list
+ FIELD:switchableControllerActions:=:Date->list
+ FIELD:switchableControllerActions:=:Date->search
+
+
+
+ input
+ 10
+ 30
+ trim
+
+
+
+
+
+
+ 1
+ Highlights only
+
+
+ FIELD:switchableControllerActions:=:Event->list
+ FIELD:switchableControllerActions:=:Date->list
+
+
+
+ check
+ 0
+
+
+
+
+
+
+ 1
+ Today only
+
+
+ FIELD:switchableControllerActions:=:Event->list
+ FIELD:switchableControllerActions:=:Date->list
+
+
+
+ check
+ 0
+
+
+
+
+
+
+ 1
+ Show pagination
+
+
+ FIELD:switchableControllerActions:=:Event->list
+ FIELD:switchableControllerActions:=:Date->list
+
+
+
+ check
+ 0
+
+
+
+
+
+
+ 1
+ Detail page
+
+
+ FIELD:switchableControllerActions:=:Event->list
+ FIELD:switchableControllerActions:=:Event->teaser
+ FIELD:switchableControllerActions:=:Event->search
+ FIELD:switchableControllerActions:=:Date->list
+ FIELD:switchableControllerActions:=:Date->teaser
+ FIELD:switchableControllerActions:=:Date->search
+
+
+
+ group
+ db
+ pages
+ 1
+ 1
+ 0
+ 1
+
+
+
+
+
+
+
+ Event
+
+
+
+ FIELD:switchableControllerActions:=:Event->teaser
+ FIELD:switchableControllerActions:=:Date->teaser
+
+
+
+ select
+ tx_events_domain_model_event
+ AND tx_events_domain_model_event.deleted = 0 AND tx_events_domain_model_event.hidden = 0
+ 3
+ 1
+ 0
+ 99
+
+
+
+
+
+
+
+
+
+ Template
+
+ array
+
+
+ 1
+ Layout option
+
+
+ FIELD:sDEF.switchableControllerActions:=:Event->list
+ FIELD:sDEF.switchableControllerActions:=:Date->list
+
+
+
+ select
+
+
+ Default
+ default
+
+
+ Costum
+ costum
+
+
+ Table
+ table
+
+
+ Grid
+ grid
+
+
+ default
+
+
+
+
+
+
+
+
+ Regions & Categories
+
+ array
+
+
+
+ Region
+
+
+ FIELD:sDEF.switchableControllerActions:=:Event->list
+ FIELD:sDEF.switchableControllerActions:=:Date->list
+
+
+
+ select
+ tx_events_domain_model_region
+ AND tx_events_domain_model_region.deleted = 0 AND tx_events_domain_model_region.hidden = 0
+ 3
+ 0
+ 2
+
+
+
+
+
+
+ 1
+ Combination
+
+
+ FIELD:sDEF.switchableControllerActions:=:Event->list
+ FIELD:sDEF.switchableControllerActions:=:Date->list
+
+
+
+ select
+
+
+ And
+ 0
+
+
+ Or
+ 1
+
+
+ 0
+
+
+
+
+
+
+ 1
+
+ Category
+
+
+
+ FIELD:sDEF.switchableControllerActions:=:Event->list
+ FIELD:sDEF.switchableControllerActions:=:Date->list
+
+
+
+ select
+ 20
+ sys_category
+ AND sys_category.sys_language_uid IN (-1, 0) ORDER BY sys_category.title ASC
+ 1
+ tree
+ 8
+
+
+ 1
+ 1
+
+ parent
+
+
+
+
+
+
+
+ 1
+ Include Subcategories
+ FIELD:sDEF.switchableControllerActions:=:Event->list
+
+ check
+ 0
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Configuration/TCA/Overrides/tt_content.php b/Configuration/TCA/Overrides/tt_content.php
new file mode 100644
index 0000000..ab4974d
--- /dev/null
+++ b/Configuration/TCA/Overrides/tt_content.php
@@ -0,0 +1,72 @@
+ 'Categories',
+ 'fieldConfiguration' => [
+ 'minitems' => 0,
+ 'maxitems' => 3,
+ 'multiple' => true,
+ ]
+ ]
+);
\ No newline at end of file
diff --git a/Configuration/TCA/tx_events_domain_model_date.php b/Configuration/TCA/tx_events_domain_model_date.php
new file mode 100644
index 0000000..16d7b1e
--- /dev/null
+++ b/Configuration/TCA/tx_events_domain_model_date.php
@@ -0,0 +1,158 @@
+ [
+ 'title' => 'LLL:EXT:events/Resources/Private/Language/locallang_csh_date.xlf:tx_events_domain_model_date',
+ 'label' => 'start',
+ 'tstamp' => 'tstamp',
+ 'crdate' => 'crdate',
+ 'cruser_id' => 'cruser_id',
+ 'versioningWS' => true,
+ 'languageField' => 'sys_language_uid',
+ 'transOrigPointerField' => 'l10n_parent',
+ 'transOrigDiffSourceField' => 'l10n_diffsource',
+ //'delete' => 'deleted',
+ 'enablecolumns' => [
+ 'disabled' => 'hidden',
+ 'starttime' => 'starttime',
+ 'endtime' => 'endtime',
+ ],
+ 'searchFields' => '',
+ 'iconfile' => 'EXT:events/Resources/Public/Icons/tx_events_domain_model_date.gif'
+ ],
+ 'interface' => [
+ 'showRecordFieldList' => 'sys_language_uid, l10n_parent, l10n_diffsource, hidden, start, end',
+ ],
+ 'types' => [
+ '1' => ['showitem' => 'sys_language_uid, l10n_parent, l10n_diffsource, hidden, start, end, event, --div--;LLL:EXT:frontend/Resources/Private/Language/locallang_ttc.xlf:tabs.access, starttime, endtime'],
+ ],
+ 'columns' => [
+ 'sys_language_uid' => [
+ 'exclude' => true,
+ 'label' => 'LLL:EXT:core/Resources/Private/Language/locallang_general.xlf:LGL.language',
+ 'config' => [
+ 'type' => 'select',
+ 'renderType' => 'selectSingle',
+ 'special' => 'languages',
+ 'items' => [
+ [
+ 'LLL:EXT:core/Resources/Private/Language/locallang_general.xlf:LGL.allLanguages',
+ -1,
+ 'flags-multiple'
+ ]
+ ],
+ 'default' => 0,
+ ],
+ ],
+ 'l10n_parent' => [
+ 'displayCond' => 'FIELD:sys_language_uid:>:0',
+ 'exclude' => true,
+ 'label' => 'LLL:EXT:core/Resources/Private/Language/locallang_general.xlf:LGL.l18n_parent',
+ 'config' => [
+ 'type' => 'select',
+ 'renderType' => 'selectSingle',
+ 'default' => 0,
+ 'items' => [
+ ['', 0],
+ ],
+ 'foreign_table' => 'tx_events_domain_model_date',
+ 'foreign_table_where' => 'AND {#tx_events_domain_model_date}.{#pid}=###CURRENT_PID### AND {#tx_events_domain_model_date}.{#sys_language_uid} IN (-1,0)',
+ ],
+ ],
+ 'l10n_diffsource' => [
+ 'config' => [
+ 'type' => 'passthrough',
+ ],
+ ],
+ 't3ver_label' => [
+ 'label' => 'LLL:EXT:core/Resources/Private/Language/locallang_general.xlf:LGL.versionLabel',
+ 'config' => [
+ 'type' => 'input',
+ 'size' => 30,
+ 'max' => 255,
+ ],
+ ],
+ 'hidden' => [
+ 'exclude' => true,
+ 'label' => 'LLL:EXT:core/Resources/Private/Language/locallang_general.xlf:LGL.visible',
+ 'config' => [
+ 'type' => 'check',
+ 'renderType' => 'checkboxToggle',
+ 'items' => [
+ [
+ 0 => '',
+ 1 => '',
+ 'invertStateDisplay' => true
+ ]
+ ],
+ ],
+ ],
+ 'starttime' => [
+ 'exclude' => true,
+ 'label' => 'LLL:EXT:core/Resources/Private/Language/locallang_general.xlf:LGL.starttime',
+ 'config' => [
+ 'type' => 'input',
+ 'renderType' => 'inputDateTime',
+ 'eval' => 'datetime,int',
+ 'default' => 0,
+ 'behaviour' => [
+ 'allowLanguageSynchronization' => true
+ ]
+ ],
+ ],
+ 'endtime' => [
+ 'exclude' => true,
+ 'label' => 'LLL:EXT:core/Resources/Private/Language/locallang_general.xlf:LGL.endtime',
+ 'config' => [
+ 'type' => 'input',
+ 'renderType' => 'inputDateTime',
+ 'eval' => 'datetime,int',
+ 'default' => 0,
+ 'range' => [
+ 'upper' => mktime(0, 0, 0, 1, 1, 2038)
+ ],
+ 'behaviour' => [
+ 'allowLanguageSynchronization' => true
+ ]
+ ],
+ ],
+
+ 'start' => [
+ 'exclude' => true,
+ 'label' => 'LLL:EXT:events/Resources/Private/Language/locallang_csh_date.xlf:tx_events_domain_model_date.start',
+ 'config' => [
+ //'dbType' => 'datetime',
+ 'type' => 'input',
+ 'renderType' => 'inputDateTime',
+ 'size' => 12,
+ 'eval' => 'datetime',
+ 'default' => null,
+ ],
+ ],
+ 'end' => [
+ 'exclude' => true,
+ 'label' => 'LLL:EXT:events/Resources/Private/Language/locallang_csh_date.xlf:tx_events_domain_model_date.end',
+ 'config' => [
+ //'dbType' => 'datetime',
+ 'type' => 'input',
+ 'renderType' => 'inputDateTime',
+ 'size' => 12,
+ 'eval' => 'datetime',
+ 'default' => null,
+ ],
+ ],
+
+ 'event' => array(
+ 'exclude' => 1,
+ 'label' => 'LLL:EXT:events/Resources/Private/Language/locallang_csh_date.xlf:tx_events_domain_model_date.event',
+ 'config' => array(
+ 'type' => 'select',
+ 'renderType' => 'selectSingle',
+ 'foreign_table' => 'tx_events_domain_model_event',
+ 'size' => 1,
+ 'minitems' => 0,
+ 'maxitems' => 1,
+ 'readOnly' =>1,
+ )
+ )
+ ],
+];
diff --git a/Configuration/TCA/tx_events_domain_model_event.php b/Configuration/TCA/tx_events_domain_model_event.php
new file mode 100644
index 0000000..c354a0e
--- /dev/null
+++ b/Configuration/TCA/tx_events_domain_model_event.php
@@ -0,0 +1,452 @@
+ [
+ 'title' => 'LLL:EXT:events/Resources/Private/Language/locallang_csh_event.xlf:tx_events_domain_model_event',
+ 'label' => 'title',
+ 'tstamp' => 'tstamp',
+ 'crdate' => 'crdate',
+ 'cruser_id' => 'cruser_id',
+ 'versioningWS' => true,
+ 'languageField' => 'sys_language_uid',
+ 'transOrigPointerField' => 'l10n_parent',
+ 'transOrigDiffSourceField' => 'l10n_diffsource',
+ 'delete' => 'deleted',
+ 'enablecolumns' => [
+ 'disabled' => 'hidden',
+ 'starttime' => 'starttime',
+ 'endtime' => 'endtime',
+ ],
+ 'searchFields' => 'title,global_id,slug,teaser,details,price_info,street,district,city,zip,country,web,booking,ticket,facebook,youtube,latitude,longitude',
+ 'iconfile' => 'EXT:events/Resources/Public/Icons/tx_events_domain_model_event.gif'
+ ],
+ 'interface' => [
+ 'showRecordFieldList' => 'sys_language_uid, l10n_parent, l10n_diffsource, hidden, title, global_id, slug, highlight, teaser, details, price_info, name, street, district, city, zip, country, phone, web, ticket, facebook, youtube, instagram, latitude, longitude, images, categories, dates, organizer, region',
+ ],
+ 'types' => [
+ '1' => ['showitem' => 'sys_language_uid, l10n_parent, l10n_diffsource, hidden, title, global_id, slug, highlight, teaser, details, price_info, name, street, district, city, zip, country, phone, web, ticket, facebook, youtube, instagram, latitude, longitude, images, categories, dates, organizer, region, --div--;LLL:EXT:frontend/Resources/Private/Language/locallang_ttc.xlf:tabs.access, starttime, endtime'],
+ ],
+ 'columns' => [
+ 'sys_language_uid' => [
+ 'exclude' => true,
+ 'label' => 'LLL:EXT:core/Resources/Private/Language/locallang_general.xlf:LGL.language',
+ 'config' => [
+ 'type' => 'select',
+ 'renderType' => 'selectSingle',
+ 'special' => 'languages',
+ 'items' => [
+ [
+ 'LLL:EXT:core/Resources/Private/Language/locallang_general.xlf:LGL.allLanguages',
+ -1,
+ 'flags-multiple'
+ ]
+ ],
+ 'default' => 0,
+ ],
+ ],
+ 'l10n_parent' => [
+ 'displayCond' => 'FIELD:sys_language_uid:>:0',
+ 'exclude' => true,
+ 'label' => 'LLL:EXT:core/Resources/Private/Language/locallang_general.xlf:LGL.l18n_parent',
+ 'config' => [
+ 'type' => 'select',
+ 'renderType' => 'selectSingle',
+ 'default' => 0,
+ 'items' => [
+ ['', 0],
+ ],
+ 'foreign_table' => 'tx_events_domain_model_event',
+ 'foreign_table_where' => 'AND {#tx_events_domain_model_event}.{#pid}=###CURRENT_PID### AND {#tx_events_domain_model_event}.{#sys_language_uid} IN (-1,0)',
+ ],
+ ],
+ 'l10n_diffsource' => [
+ 'config' => [
+ 'type' => 'passthrough',
+ ],
+ ],
+ 't3ver_label' => [
+ 'label' => 'LLL:EXT:core/Resources/Private/Language/locallang_general.xlf:LGL.versionLabel',
+ 'config' => [
+ 'type' => 'input',
+ 'size' => 30,
+ 'max' => 255,
+ ],
+ ],
+ 'hidden' => [
+ 'exclude' => true,
+ 'label' => 'LLL:EXT:core/Resources/Private/Language/locallang_general.xlf:LGL.visible',
+ 'config' => [
+ 'type' => 'check',
+ 'renderType' => 'checkboxToggle',
+ 'items' => [
+ [
+ 0 => '',
+ 1 => '',
+ 'invertStateDisplay' => true
+ ]
+ ],
+ ],
+ ],
+ 'starttime' => [
+ 'exclude' => true,
+ 'label' => 'LLL:EXT:core/Resources/Private/Language/locallang_general.xlf:LGL.starttime',
+ 'config' => [
+ 'type' => 'input',
+ 'renderType' => 'inputDateTime',
+ 'eval' => 'datetime,int',
+ 'default' => 0,
+ 'behaviour' => [
+ 'allowLanguageSynchronization' => true
+ ]
+ ],
+ ],
+ 'endtime' => [
+ 'exclude' => true,
+ 'label' => 'LLL:EXT:core/Resources/Private/Language/locallang_general.xlf:LGL.endtime',
+ 'config' => [
+ 'type' => 'input',
+ 'renderType' => 'inputDateTime',
+ 'eval' => 'datetime,int',
+ 'default' => 0,
+ 'range' => [
+ 'upper' => mktime(0, 0, 0, 1, 1, 2038)
+ ],
+ 'behaviour' => [
+ 'allowLanguageSynchronization' => true
+ ]
+ ],
+ ],
+
+ 'title' => [
+ 'exclude' => true,
+ 'label' => 'LLL:EXT:events/Resources/Private/Language/locallang_csh_event.xlf:tx_events_domain_model_event.title',
+ 'config' => [
+ 'type' => 'input',
+ 'size' => 30,
+ 'eval' => 'trim'
+ ]
+ ],
+ 'global_id' => [
+ 'exclude' => true,
+ 'label' => 'LLL:EXT:events/Resources/Private/Language/locallang_csh_event.xlf:tx_events_domain_model_event.global_id',
+ 'config' => [
+ 'type' => 'input',
+ 'size' => 30,
+ 'eval' => 'trim'
+ ],
+ ],
+ 'slug' => [
+ 'exclude' => true,
+ 'label' => 'LLL:EXT:events/Resources/Private/Language/locallang_csh_event.xlf:tx_events_domain_model_event.slug',
+ 'config' => [
+ 'type' => 'slug',
+ 'size' => 50,
+ 'generatorOptions' => [
+ 'fields' => ['title'],
+ 'fieldSeparator' => '/',
+ 'prefixParentPageSlug' => false,
+ ],
+ 'fallbackCharacter' => '-',
+ 'eval' => 'uniqueInSite',
+ 'default' => '',
+ ],
+ ],
+ 'highlight' => [
+ 'exclude' => true,
+ 'label' => 'LLL:EXT:events/Resources/Private/Language/locallang_csh_event.xlf:tx_events_domain_model_event.highlight',
+ 'config' => [
+ 'type' => 'check',
+ 'items' => [
+ '1' => [
+ '0' => 'LLL:EXT:lang/locallang_core.xlf:labels.enabled'
+ ]
+ ],
+ 'default' => 0,
+ ]
+ ],
+ 'teaser' => [
+ 'exclude' => true,
+ 'label' => 'LLL:EXT:events/Resources/Private/Language/locallang_csh_event.xlf:tx_events_domain_model_event.teaser',
+ 'config' => [
+ 'type' => 'text',
+ 'cols' => 40,
+ 'rows' => 15,
+ 'eval' => 'trim'
+ ]
+ ],
+ 'details' => [
+ 'exclude' => true,
+ 'label' => 'LLL:EXT:events/Resources/Private/Language/locallang_csh_event.xlf:tx_events_domain_model_event.details',
+ 'config' => [
+ 'type' => 'text',
+ 'enableRichtext' => true,
+ 'richtextConfiguration' => 'default',
+ 'fieldControl' => [
+ 'fullScreenRichtext' => [
+ 'disabled' => false,
+ ],
+ ],
+ 'cols' => 40,
+ 'rows' => 15,
+ 'eval' => 'trim',
+ ],
+
+ ],
+ 'price_info' => [
+ 'exclude' => true,
+ 'label' => 'LLL:EXT:events/Resources/Private/Language/locallang_csh_event.xlf:tx_events_domain_model_event.price_info',
+ 'config' => [
+ 'type' => 'text',
+ 'cols' => 40,
+ 'rows' => 15,
+ 'eval' => 'trim'
+ ]
+ ],
+ 'name' => [
+ 'exclude' => true,
+ 'label' => 'LLL:EXT:events/Resources/Private/Language/locallang_csh_event.xlf:tx_events_domain_model_event.name',
+ 'config' => [
+ 'type' => 'input',
+ 'size' => 30,
+ 'eval' => 'trim'
+ ],
+ ],
+ 'street' => [
+ 'exclude' => true,
+ 'label' => 'LLL:EXT:events/Resources/Private/Language/locallang_csh_event.xlf:tx_events_domain_model_event.street',
+ 'config' => [
+ 'type' => 'input',
+ 'size' => 30,
+ 'eval' => 'trim'
+ ],
+ ],
+ 'district' => [
+ 'exclude' => true,
+ 'label' => 'LLL:EXT:events/Resources/Private/Language/locallang_csh_event.xlf:tx_events_domain_model_event.district',
+ 'config' => [
+ 'type' => 'input',
+ 'size' => 30,
+ 'eval' => 'trim'
+ ],
+ ],
+ 'city' => [
+ 'exclude' => true,
+ 'label' => 'LLL:EXT:events/Resources/Private/Language/locallang_csh_event.xlf:tx_events_domain_model_event.city',
+ 'config' => [
+ 'type' => 'input',
+ 'size' => 30,
+ 'eval' => 'trim'
+ ],
+ ],
+ 'zip' => [
+ 'exclude' => true,
+ 'label' => 'LLL:EXT:events/Resources/Private/Language/locallang_csh_event.xlf:tx_events_domain_model_event.zip',
+ 'config' => [
+ 'type' => 'input',
+ 'size' => 30,
+ 'eval' => 'trim'
+ ],
+ ],
+ 'country' => [
+ 'exclude' => true,
+ 'label' => 'LLL:EXT:events/Resources/Private/Language/locallang_csh_event.xlf:tx_events_domain_model_event.country',
+ 'config' => [
+ 'type' => 'input',
+ 'size' => 30,
+ 'eval' => 'trim'
+ ],
+ ],
+ 'phone' => [
+ 'exclude' => true,
+ 'label' => 'LLL:EXT:events/Resources/Private/Language/locallang_csh_event.xlf:tx_events_domain_model_event.phone',
+ 'config' => [
+ 'type' => 'input',
+ 'size' => 30,
+ 'eval' => 'trim'
+ ],
+ ],
+ 'web' => [
+ 'exclude' => true,
+ 'label' => 'LLL:EXT:events/Resources/Private/Language/locallang_csh_event.xlf:tx_events_domain_model_event.web',
+ 'config' => [
+ 'type' => 'input',
+ 'size' => 30,
+ 'eval' => 'trim'
+ ],
+ ],
+ 'ticket' => [
+ 'exclude' => true,
+ 'label' => 'LLL:EXT:events/Resources/Private/Language/locallang_csh_event.xlf:tx_events_domain_model_event.ticket',
+ 'config' => [
+ 'type' => 'input',
+ 'size' => 30,
+ 'eval' => 'trim'
+ ],
+ ],
+ 'facebook' => [
+ 'exclude' => true,
+ 'label' => 'LLL:EXT:events/Resources/Private/Language/locallang_csh_event.xlf:tx_events_domain_model_event.facebook',
+ 'config' => [
+ 'type' => 'input',
+ 'size' => 30,
+ 'eval' => 'trim'
+ ],
+ ],
+ 'youtube' => [
+ 'exclude' => true,
+ 'label' => 'LLL:EXT:events/Resources/Private/Language/locallang_csh_event.xlf:tx_events_domain_model_event.youtube',
+ 'config' => [
+ 'type' => 'input',
+ 'size' => 30,
+ 'eval' => 'trim'
+ ],
+ ],
+ 'instagram' => [
+ 'exclude' => true,
+ 'label' => 'LLL:EXT:events/Resources/Private/Language/locallang_csh_event.xlf:tx_events_domain_model_event.instagram',
+ 'config' => [
+ 'type' => 'input',
+ 'size' => 30,
+ 'eval' => 'trim'
+ ],
+ ],
+ 'latitude' => [
+ 'exclude' => true,
+ 'label' => 'LLL:EXT:events/Resources/Private/Language/locallang_csh_event.xlf:tx_events_domain_model_event.latitude',
+ 'config' => [
+ 'type' => 'input',
+ 'size' => 30,
+ 'eval' => 'trim'
+ ],
+ ],
+ 'longitude' => [
+ 'exclude' => true,
+ 'label' => 'LLL:EXT:events/Resources/Private/Language/locallang_csh_event.xlf:tx_events_domain_model_event.longitude',
+ 'config' => [
+ 'type' => 'input',
+ 'size' => 30,
+ 'eval' => 'trim'
+ ],
+ ],
+ 'images' => [
+ 'exclude' => true,
+ 'label' => 'LLL:EXT:events/Resources/Private/Language/locallang_csh_event.xlf:tx_events_domain_model_event.images',
+ 'config' => \TYPO3\CMS\Core\Utility\ExtensionManagementUtility::getFileFieldTCAConfig(
+ 'images',
+ [
+ 'appearance' => [
+ 'createNewRelationLinkTitle' => 'LLL:EXT:frontend/Resources/Private/Language/locallang_ttc.xlf:images.addFileReference',
+ 'showPossibleLocalizationRecords' => true,
+ 'showRemovedLocalizationRecords' => true,
+ 'showAllLocalizationLink' => true,
+ 'showSynchronizationLink' => true,
+ ],
+ 'foreign_match_fields' => [
+ 'fieldname' => 'images',
+ 'tablenames' => 'tx_events_domain_model_event',
+ 'table_local' => 'sys_file',
+ ],
+ 'foreign_types' => [
+ '0' => [
+ 'showitem' => '
+ --palette--;LLL:EXT:lang/locallang_tca.xlf:sys_file_reference.imageoverlayPalette;imageoverlayPalette,
+ --palette--;;filePalette'
+ ],
+ \TYPO3\CMS\Core\Resource\File::FILETYPE_TEXT => [
+ 'showitem' => '
+ --palette--;LLL:EXT:lang/locallang_tca.xlf:sys_file_reference.imageoverlayPalette;imageoverlayPalette,
+ --palette--;;filePalette'
+ ],
+ \TYPO3\CMS\Core\Resource\File::FILETYPE_IMAGE => [
+ 'showitem' => '
+ --palette--;LLL:EXT:lang/locallang_tca.xlf:sys_file_reference.imageoverlayPalette;imageoverlayPalette,
+ --palette--;;filePalette'
+ ],
+ \TYPO3\CMS\Core\Resource\File::FILETYPE_AUDIO => [
+ 'showitem' => '
+ --palette--;LLL:EXT:lang/locallang_tca.xlf:sys_file_reference.imageoverlayPalette;imageoverlayPalette,
+ --palette--;;filePalette'
+ ],
+ \TYPO3\CMS\Core\Resource\File::FILETYPE_VIDEO => [
+ 'showitem' => '
+ --palette--;LLL:EXT:lang/locallang_tca.xlf:sys_file_reference.imageoverlayPalette;imageoverlayPalette,
+ --palette--;;filePalette'
+ ],
+ \TYPO3\CMS\Core\Resource\File::FILETYPE_APPLICATION => [
+ 'showitem' => '
+ --palette--;LLL:EXT:lang/locallang_tca.xlf:sys_file_reference.imageoverlayPalette;imageoverlayPalette,
+ --palette--;;filePalette'
+ ]
+ ],
+ 'maxitems' => 1
+ ],
+ $GLOBALS['TYPO3_CONF_VARS']['GFX']['imagefile_ext']
+ ),
+ ],
+
+ 'categories' => [
+ 'exclude' => true,
+ 'label' => 'LLL:EXT:events/Resources/Private/Language/locallang_csh_event.xlf:tx_events_domain_model_event.categories',
+ 'config' => [
+ 'type' => 'input',
+ 'size' => 4,
+ 'eval' => 'int'
+ ]
+ ],
+
+ 'dates' => [
+ 'exclude' => true,
+ 'label' => 'LLL:EXT:events/Resources/Private/Language/locallang_csh_event.xlf:tx_events_domain_model_event.dates',
+ 'config' => [
+ 'type' => 'inline',
+ 'foreign_table' => 'tx_events_domain_model_date',
+ 'foreign_field' => 'event',
+ 'maxitems' => 9999,
+ 'appearance' => [
+ 'collapseAll' => 1,
+ 'useSortable' => 0,
+ 'expandSingle' => 1,
+ 'enabledControls' => array(
+ 'info' => false,
+ 'new' => false,
+ 'dragdrop' => false,
+ 'sort' => false,
+ 'hide' => false,
+ 'delete' => false,
+ 'localize' => false,
+ ),
+ 'levelLinksPosition' => 'top',
+ 'showPossibleLocalizationRecords' => false,
+ 'showRemovedLocalizationRecords' => false,
+ 'showSynchronizationLink' => false,
+ 'showAllLocalizationLink' => false,
+ ],
+
+ ],
+
+ ],
+
+ 'organizer' => [
+ 'exclude' => true,
+ 'label' => 'LLL:EXT:events/Resources/Private/Language/locallang_csh_event.xlf:tx_events_domain_model_event.organizer',
+ 'config' => [
+ 'type' => 'select',
+ 'renderType' => 'selectSingle',
+ 'foreign_table' => 'tx_events_domain_model_organizer',
+ 'minitems' => 0,
+ 'maxitems' => 1,
+ ],
+ ],
+ 'region' => [
+ 'exclude' => true,
+ 'label' => 'LLL:EXT:events/Resources/Private/Language/locallang_csh_event.xlf:tx_events_domain_model_event.region',
+ 'config' => [
+ 'type' => 'select',
+ 'renderType' => 'selectSingle',
+ 'foreign_table' => 'tx_events_domain_model_region',
+ 'minitems' => 0,
+ 'maxitems' => 1,
+ ],
+ ],
+
+ ],
+];
diff --git a/Configuration/TCA/tx_events_domain_model_organizer.php b/Configuration/TCA/tx_events_domain_model_organizer.php
new file mode 100644
index 0000000..4cf94db
--- /dev/null
+++ b/Configuration/TCA/tx_events_domain_model_organizer.php
@@ -0,0 +1,193 @@
+ [
+ 'title' => 'LLL:EXT:events/Resources/Private/Language/locallang_csh_organizer.xlf:tx_events_domain_model_organizer',
+ 'label' => 'name',
+ 'tstamp' => 'tstamp',
+ 'crdate' => 'crdate',
+ 'cruser_id' => 'cruser_id',
+ 'versioningWS' => true,
+ 'languageField' => 'sys_language_uid',
+ 'transOrigPointerField' => 'l10n_parent',
+ 'transOrigDiffSourceField' => 'l10n_diffsource',
+ 'delete' => 'deleted',
+ 'enablecolumns' => [
+ 'disabled' => 'hidden',
+ 'starttime' => 'starttime',
+ 'endtime' => 'endtime',
+ ],
+ 'searchFields' => 'name,street,district,city,zip,phone,web,email',
+ 'iconfile' => 'EXT:events/Resources/Public/Icons/tx_events_domain_model_organizer.gif'
+ ],
+ 'interface' => [
+ 'showRecordFieldList' => 'sys_language_uid, l10n_parent, l10n_diffsource, hidden, name, street, district, city, zip, phone, web, email',
+ ],
+ 'types' => [
+ '1' => ['showitem' => 'sys_language_uid, l10n_parent, l10n_diffsource, hidden, name, street, district, city, zip, phone, web, email, --div--;LLL:EXT:frontend/Resources/Private/Language/locallang_ttc.xlf:tabs.access, starttime, endtime'],
+ ],
+ 'columns' => [
+ 'sys_language_uid' => [
+ 'exclude' => true,
+ 'label' => 'LLL:EXT:core/Resources/Private/Language/locallang_general.xlf:LGL.language',
+ 'config' => [
+ 'type' => 'select',
+ 'renderType' => 'selectSingle',
+ 'special' => 'languages',
+ 'items' => [
+ [
+ 'LLL:EXT:core/Resources/Private/Language/locallang_general.xlf:LGL.allLanguages',
+ -1,
+ 'flags-multiple'
+ ]
+ ],
+ 'default' => 0,
+ ],
+ ],
+ 'l10n_parent' => [
+ 'displayCond' => 'FIELD:sys_language_uid:>:0',
+ 'exclude' => true,
+ 'label' => 'LLL:EXT:core/Resources/Private/Language/locallang_general.xlf:LGL.l18n_parent',
+ 'config' => [
+ 'type' => 'select',
+ 'renderType' => 'selectSingle',
+ 'default' => 0,
+ 'items' => [
+ ['', 0],
+ ],
+ 'foreign_table' => 'tx_events_domain_model_organizer',
+ 'foreign_table_where' => 'AND {#tx_events_domain_model_organizer}.{#pid}=###CURRENT_PID### AND {#tx_events_domain_model_organizer}.{#sys_language_uid} IN (-1,0)',
+ ],
+ ],
+ 'l10n_diffsource' => [
+ 'config' => [
+ 'type' => 'passthrough',
+ ],
+ ],
+ 't3ver_label' => [
+ 'label' => 'LLL:EXT:core/Resources/Private/Language/locallang_general.xlf:LGL.versionLabel',
+ 'config' => [
+ 'type' => 'input',
+ 'size' => 30,
+ 'max' => 255,
+ ],
+ ],
+ 'hidden' => [
+ 'exclude' => true,
+ 'label' => 'LLL:EXT:core/Resources/Private/Language/locallang_general.xlf:LGL.visible',
+ 'config' => [
+ 'type' => 'check',
+ 'renderType' => 'checkboxToggle',
+ 'items' => [
+ [
+ 0 => '',
+ 1 => '',
+ 'invertStateDisplay' => true
+ ]
+ ],
+ ],
+ ],
+ 'starttime' => [
+ 'exclude' => true,
+ 'label' => 'LLL:EXT:core/Resources/Private/Language/locallang_general.xlf:LGL.starttime',
+ 'config' => [
+ 'type' => 'input',
+ 'renderType' => 'inputDateTime',
+ 'eval' => 'datetime,int',
+ 'default' => 0,
+ 'behaviour' => [
+ 'allowLanguageSynchronization' => true
+ ]
+ ],
+ ],
+ 'endtime' => [
+ 'exclude' => true,
+ 'label' => 'LLL:EXT:core/Resources/Private/Language/locallang_general.xlf:LGL.endtime',
+ 'config' => [
+ 'type' => 'input',
+ 'renderType' => 'inputDateTime',
+ 'eval' => 'datetime,int',
+ 'default' => 0,
+ 'range' => [
+ 'upper' => mktime(0, 0, 0, 1, 1, 2038)
+ ],
+ 'behaviour' => [
+ 'allowLanguageSynchronization' => true
+ ]
+ ],
+ ],
+
+ 'name' => [
+ 'exclude' => true,
+ 'label' => 'LLL:EXT:events/Resources/Private/Language/locallang_csh_organizer.xlf:tx_events_domain_model_organizer.name',
+ 'config' => [
+ 'type' => 'input',
+ 'size' => 30,
+ 'eval' => 'trim'
+ ],
+ ],
+ 'street' => [
+ 'exclude' => true,
+ 'label' => 'LLL:EXT:events/Resources/Private/Language/locallang_csh_organizer.xlf:tx_events_domain_model_organizer.street',
+ 'config' => [
+ 'type' => 'input',
+ 'size' => 30,
+ 'eval' => 'trim'
+ ],
+ ],
+ 'district' => [
+ 'exclude' => true,
+ 'label' => 'LLL:EXT:events/Resources/Private/Language/locallang_csh_organizer.xlf:tx_events_domain_model_organizer.district',
+ 'config' => [
+ 'type' => 'input',
+ 'size' => 30,
+ 'eval' => 'trim'
+ ],
+ ],
+ 'city' => [
+ 'exclude' => true,
+ 'label' => 'LLL:EXT:events/Resources/Private/Language/locallang_csh_organizer.xlf:tx_events_domain_model_organizer.city',
+ 'config' => [
+ 'type' => 'input',
+ 'size' => 30,
+ 'eval' => 'trim'
+ ],
+ ],
+ 'zip' => [
+ 'exclude' => true,
+ 'label' => 'LLL:EXT:events/Resources/Private/Language/locallang_csh_organizer.xlf:tx_events_domain_model_organizer.zip',
+ 'config' => [
+ 'type' => 'input',
+ 'size' => 30,
+ 'eval' => 'trim'
+ ],
+ ],
+ 'phone' => [
+ 'exclude' => true,
+ 'label' => 'LLL:EXT:events/Resources/Private/Language/locallang_csh_organizer.xlf:tx_events_domain_model_organizer.phone',
+ 'config' => [
+ 'type' => 'input',
+ 'size' => 30,
+ 'eval' => 'trim'
+ ],
+ ],
+ 'web' => [
+ 'exclude' => true,
+ 'label' => 'LLL:EXT:events/Resources/Private/Language/locallang_csh_organizer.xlf:tx_events_domain_model_organizer.web',
+ 'config' => [
+ 'type' => 'input',
+ 'size' => 30,
+ 'eval' => 'trim'
+ ],
+ ],
+ 'email' => [
+ 'exclude' => true,
+ 'label' => 'LLL:EXT:events/Resources/Private/Language/locallang_csh_organizer.xlf:tx_events_domain_model_organizer.email',
+ 'config' => [
+ 'type' => 'input',
+ 'size' => 30,
+ 'eval' => 'trim'
+ ],
+ ],
+
+ ],
+];
diff --git a/Configuration/TCA/tx_events_domain_model_region.php b/Configuration/TCA/tx_events_domain_model_region.php
new file mode 100644
index 0000000..b2cbaf8
--- /dev/null
+++ b/Configuration/TCA/tx_events_domain_model_region.php
@@ -0,0 +1,130 @@
+ [
+ 'title' => 'LLL:EXT:events/Resources/Private/Language/locallang_csh_region.xlf:tx_events_domain_model_region',
+ 'label' => 'title',
+ 'tstamp' => 'tstamp',
+ 'crdate' => 'crdate',
+ 'cruser_id' => 'cruser_id',
+ 'versioningWS' => true,
+ 'languageField' => 'sys_language_uid',
+ 'transOrigPointerField' => 'l10n_parent',
+ 'transOrigDiffSourceField' => 'l10n_diffsource',
+ 'delete' => 'deleted',
+ 'enablecolumns' => [
+ 'disabled' => 'hidden',
+ 'starttime' => 'starttime',
+ 'endtime' => 'endtime',
+ ],
+ 'searchFields' => 'title',
+ 'iconfile' => 'EXT:events/Resources/Public/Icons/tx_events_domain_model_region.gif'
+ ],
+ 'interface' => [
+ 'showRecordFieldList' => 'sys_language_uid, l10n_parent, l10n_diffsource, hidden, title',
+ ],
+ 'types' => [
+ '1' => ['showitem' => 'sys_language_uid, l10n_parent, l10n_diffsource, hidden, title, --div--;LLL:EXT:frontend/Resources/Private/Language/locallang_ttc.xlf:tabs.access, starttime, endtime'],
+ ],
+ 'columns' => [
+ 'sys_language_uid' => [
+ 'exclude' => true,
+ 'label' => 'LLL:EXT:core/Resources/Private/Language/locallang_general.xlf:LGL.language',
+ 'config' => [
+ 'type' => 'select',
+ 'renderType' => 'selectSingle',
+ 'special' => 'languages',
+ 'items' => [
+ [
+ 'LLL:EXT:core/Resources/Private/Language/locallang_general.xlf:LGL.allLanguages',
+ -1,
+ 'flags-multiple'
+ ]
+ ],
+ 'default' => 0,
+ ],
+ ],
+ 'l10n_parent' => [
+ 'displayCond' => 'FIELD:sys_language_uid:>:0',
+ 'exclude' => true,
+ 'label' => 'LLL:EXT:core/Resources/Private/Language/locallang_general.xlf:LGL.l18n_parent',
+ 'config' => [
+ 'type' => 'select',
+ 'renderType' => 'selectSingle',
+ 'default' => 0,
+ 'items' => [
+ ['', 0],
+ ],
+ 'foreign_table' => 'tx_events_domain_model_region',
+ 'foreign_table_where' => 'AND {#tx_events_domain_model_region}.{#pid}=###CURRENT_PID### AND {#tx_events_domain_model_region}.{#sys_language_uid} IN (-1,0)',
+ ],
+ ],
+ 'l10n_diffsource' => [
+ 'config' => [
+ 'type' => 'passthrough',
+ ],
+ ],
+ 't3ver_label' => [
+ 'label' => 'LLL:EXT:core/Resources/Private/Language/locallang_general.xlf:LGL.versionLabel',
+ 'config' => [
+ 'type' => 'input',
+ 'size' => 30,
+ 'max' => 255,
+ ],
+ ],
+ 'hidden' => [
+ 'exclude' => true,
+ 'label' => 'LLL:EXT:core/Resources/Private/Language/locallang_general.xlf:LGL.visible',
+ 'config' => [
+ 'type' => 'check',
+ 'renderType' => 'checkboxToggle',
+ 'items' => [
+ [
+ 0 => '',
+ 1 => '',
+ 'invertStateDisplay' => true
+ ]
+ ],
+ ],
+ ],
+ 'starttime' => [
+ 'exclude' => true,
+ 'label' => 'LLL:EXT:core/Resources/Private/Language/locallang_general.xlf:LGL.starttime',
+ 'config' => [
+ 'type' => 'input',
+ 'renderType' => 'inputDateTime',
+ 'eval' => 'datetime,int',
+ 'default' => 0,
+ 'behaviour' => [
+ 'allowLanguageSynchronization' => true
+ ]
+ ],
+ ],
+ 'endtime' => [
+ 'exclude' => true,
+ 'label' => 'LLL:EXT:core/Resources/Private/Language/locallang_general.xlf:LGL.endtime',
+ 'config' => [
+ 'type' => 'input',
+ 'renderType' => 'inputDateTime',
+ 'eval' => 'datetime,int',
+ 'default' => 0,
+ 'range' => [
+ 'upper' => mktime(0, 0, 0, 1, 1, 2038)
+ ],
+ 'behaviour' => [
+ 'allowLanguageSynchronization' => true
+ ]
+ ],
+ ],
+
+ 'title' => [
+ 'exclude' => true,
+ 'label' => 'LLL:EXT:events/Resources/Private/Language/locallang_csh_region.xlf:tx_events_domain_model_region.title',
+ 'config' => [
+ 'type' => 'input',
+ 'size' => 30,
+ 'eval' => 'trim'
+ ],
+ ],
+
+ ],
+];
diff --git a/Configuration/TypoScript/constants.typoscript b/Configuration/TypoScript/constants.typoscript
new file mode 100644
index 0000000..5ab60de
--- /dev/null
+++ b/Configuration/TypoScript/constants.typoscript
@@ -0,0 +1,37 @@
+
+plugin.tx_events {
+ view {
+ # cat=plugin.tx_events/file; type=string; label=Path to template root (FE)
+ templateRootPath = EXT:events/Resources/Private/Templates/
+ # cat=plugin.tx_events/file; type=string; label=Path to template partials (FE)
+ partialRootPath = EXT:events/Resources/Private/Partials/
+ # cat=plugin.tx_events/file; type=string; label=Path to template layouts (FE)
+ layoutRootPath = EXT:events/Resources/Private/Layouts/
+ }
+ persistence {
+ # cat=plugin.tx_events//a; type=string; label=Default storage PID
+ storagePid =
+ }
+ settings {
+ # cat=plugin.tx_events//a; type=string; label=Default Image
+ defaultImagePath = typo3conf/ext/events/Resources/Public/Images/default.jpg
+ destinationData {
+ # cat=plugin.tx_events//a; type=string; label=Rest Url
+ restUrl = http://meta.et4.de/rest.ashx/search/
+ # cat=plugin.tx_events//a; type=string; label=License
+ license = ***REMOVED***
+ # cat=plugin.tx_events//a; type=string; label=Data Type
+ restType = Event
+ # cat=plugin.tx_events//a; type=string; label=Data Limit
+ restLimit = 500
+ # cat=plugin.tx_events//a; type=string; label=Mode
+ restMode = next_months,12
+ # cat=plugin.tx_events//a; type=string; label=Data Template
+ restTemplate = ET2014A.json
+ # cat=plugin.tx_events//a; type=string; Label=Category Storage
+ categoriesPid = 54
+ # cat=plugin.tx_events//a; type=string; Label=Category Parent ID
+ categoryParentUid = 6
+ }
+ }
+}
diff --git a/Configuration/TypoScript/setup.typoscript b/Configuration/TypoScript/setup.typoscript
new file mode 100644
index 0000000..46197a6
--- /dev/null
+++ b/Configuration/TypoScript/setup.typoscript
@@ -0,0 +1,62 @@
+plugin.tx_events {
+ view {
+ templateRootPaths {
+ 0 = EXT:events/Resources/Private/Templates/
+ 1 = {$plugin.tx_events.view.templateRootPath}
+ }
+ partialRootPaths {
+ 0 = EXT:events/Resources/Private/Partials/
+ 1 = {$plugin.tx_events.view.partialRootPath}
+ }
+ layoutRootPaths {
+ 0 = EXT:events/Resources/Private/Layouts/
+ 1 = {$plugin.tx_events.view.layoutRootPath}
+ }
+ widget {
+ TYPO3\CMS\Fluid\ViewHelpers\Widget\PaginateViewHelper {
+ templateRootPath = {$plugin.tx_events.view.templateRootPath}
+ }
+ }
+ }
+ persistence {
+ storagePid = {$plugin.tx_events.persistence.storagePid}
+ recursive = 1
+ }
+ features {
+ #skipDefaultArguments = 1
+ # if set to 1, the enable fields are ignored in BE context
+ ignoreAllEnableFieldsInBe = 0
+ # Should be on by default, but can be disabled if all action in the plugin are uncached
+ requireCHashArgumentForActionArguments = 0
+ }
+ mvc {
+ #callDefaultActionIfActionCantBeResolved = 1
+ }
+ settings {
+
+ defaulDetailEventsPid =
+ defaultDetailDatesPid =
+ defaultImagePath = {$plugin.tx_events.settings.defaultImagePath}
+
+ paginate {
+ # can be overriden by plugin
+ itemsPerPage = 10
+ insertAbove = 0
+ insertBelow = 1
+ maximumNumberOfLinks = 10
+ }
+
+ destinationData {
+ restUrl = {$plugin.tx_events.settings.destinationData.restUrl}
+ license = {$plugin.tx_events.settings.destinationData.license}
+ restType = {$plugin.tx_events.settings.destinationData.restType}
+ restLimit = {$plugin.tx_events.settings.destinationData.restLimit}
+ restMode = {$plugin.tx_events.settings.destinationData.restMode}
+ restTemplate = {$plugin.tx_events.settings.destinationData.restTemplate}
+ categoriesPid = {$plugin.tx_events.settings.destinationData.categoriesPid}
+ categoryParentUid = {$plugin.tx_events.settings.destinationData.categoryParentUid}
+ }
+ }
+}
+
+module.tx_events < plugin.tx_events
diff --git a/Documentation/Administrator/Index.rst b/Documentation/Administrator/Index.rst
new file mode 100644
index 0000000..10bc545
--- /dev/null
+++ b/Documentation/Administrator/Index.rst
@@ -0,0 +1,82 @@
+.. ==================================================
+.. FOR YOUR INFORMATION
+.. --------------------------------------------------
+.. -*- coding: utf-8 -*- with BOM.
+
+.. include:: ../Includes.txt
+
+
+.. _admin-manual:
+
+Administrator Manual
+====================
+
+Target group: **Administrators**
+
+Describes how to manage the extension from an administrator point of view.
+That relates to Page/User TSconfig, permissions, configuration etc.,
+which administrator level users have access to.
+
+Language should be non / semi-technical, explaining, using small examples.
+
+
+.. _admin-installation:
+
+Installation
+------------
+
+- How should the extension be installed?
+- Are they dependencies to resolve?
+- Is it a static template file to be included?
+
+To install the extension, perform the following steps:
+
+#. Go to the Extension Manager
+#. Install the extension
+#. Load the static template
+#. ...
+
+For a list of configuration options, using a definition list is recommended:
+
+Some Configuration
+ This option enables...
+
+Other configuration
+ This other option is for all the rest...
+
+
+.. figure:: ../Images/AdministratorManual/ExtensionManager.png
+ :alt: Extension Manager
+
+ Extension Manager (caption of the image)
+
+ List of extensions within the Extension Manager also shorten with "EM" (legend of the image)
+
+
+.. _admin-configuration:
+
+Configuration
+-------------
+
+* Where and how the extension should be configured? TypoScript? PHP?
+
+* Are there other prerequisite to full fill beforehand?
+ For example, configure a setting in a special way somewhere.
+
+
+.. _admin-faq:
+
+FAQ
+---
+
+Possible subsection: FAQ
+
+Subsection
+^^^^^^^^^^
+
+Some subsection
+
+Sub-subsection
+""""""""""""""
+
+Deeper into the structure...
diff --git a/Documentation/ChangeLog/Index.rst b/Documentation/ChangeLog/Index.rst
new file mode 100644
index 0000000..4972785
--- /dev/null
+++ b/Documentation/ChangeLog/Index.rst
@@ -0,0 +1,16 @@
+.. ==================================================
+.. FOR YOUR INFORMATION
+.. --------------------------------------------------
+.. -*- coding: utf-8 -*- with BOM.
+
+.. include:: ../Includes.txt
+
+
+.. _changelog:
+
+ChangeLog
+=========
+
+Providing a change log chapter is optional. You can also refer
+users to the ChangeLog file inside the extension or to some repository's
+commit listing.
diff --git a/Documentation/Configuration/Index.rst b/Documentation/Configuration/Index.rst
new file mode 100644
index 0000000..0dac787
--- /dev/null
+++ b/Documentation/Configuration/Index.rst
@@ -0,0 +1,106 @@
+.. ==================================================
+.. FOR YOUR INFORMATION
+.. --------------------------------------------------
+.. -*- coding: utf-8 -*- with BOM.
+
+.. include:: ../Includes.txt
+
+
+.. _configuration:
+
+Configuration Reference
+=======================
+
+Technical information: Installation, Reference of TypoScript options,
+configuration options on system level, how to extend it, the technical
+details, how to debug it and so on.
+
+Language should be technical, assuming developer knowledge of TYPO3.
+Small examples/visuals are always encouraged.
+
+Target group: **Developers**
+
+
+.. _configuration-typoscript:
+
+TypoScript Reference
+--------------------
+
+Possible subsections: Reference of TypoScript options.
+The construct below show the recommended structure for
+TypoScript properties listing and description.
+
+Properties should be listed in the order in which they
+are executed by your extension, but the first should be
+alphabetical for easier access.
+
+When detailing data types or standard TypoScript
+features, don't hesitate to cross-link to the TypoScript
+Reference as shown below. See the :file:`Settings.yml`
+file for the declaration of cross-linking keys.
+
+
+Properties
+^^^^^^^^^^
+
+.. container:: ts-properties
+
+ =========================== ===================================== ======================= ====================
+ Property Data type :ref:`t3tsref:stdwrap` Default
+ =========================== ===================================== ======================= ====================
+ allWrap_ :ref:`t3tsref:data-type-wrap` yes :code:`
|
`
+ `subst\_elementUid`_ :ref:`t3tsref:data-type-boolean` no 0
+ wrapItemAndSub_ :ref:`t3tsref:data-type-wrap`
+ =========================== ===================================== ======================= ====================
+
+
+Property details
+^^^^^^^^^^^^^^^^
+
+.. only:: html
+
+ .. contents::
+ :local:
+ :depth: 1
+
+
+.. _ts-plugin-tx-extensionkey-stdwrap:
+
+allWrap
+"""""""
+
+:typoscript:`plugin.tx_extensionkey.allWrap =` :ref:`t3tsref:data-type-wrap`
+
+Wraps the whole item.
+
+
+.. _ts-plugin-tx-extensionkey-wrapitemandsub:
+
+wrapItemAndSub
+""""""""""""""
+
+:typoscript:`plugin.tx_extensionkey.wrapItemAndSub =` :ref:`t3tsref:data-type-wrap`
+
+Wraps the whole item and any submenu concatenated to it.
+
+
+.. _ts-plugin-tx-extensionkey-substelementUid:
+
+subst_elementUid
+""""""""""""""""
+
+:typoscript:`plugin.tx_extensionkey.subst_elementUid =` :ref:`t3tsref:data-type-boolean`
+
+If set, all appearances of the string ``{elementUid}`` in the total
+element html-code (after wrapped in allWrap_) are substituted with the
+uid number of the menu item. This is useful if you want to insert an
+identification code in the HTML in order to manipulate properties with
+JavaScript.
+
+
+.. _configuration-faq:
+
+FAQ
+---
+
+Possible subsection: FAQ
diff --git a/Documentation/Developer/Index.rst b/Documentation/Developer/Index.rst
new file mode 100644
index 0000000..57d4447
--- /dev/null
+++ b/Documentation/Developer/Index.rst
@@ -0,0 +1,60 @@
+.. ==================================================
+.. FOR YOUR INFORMATION
+.. --------------------------------------------------
+.. -*- coding: utf-8 -*- with BOM.
+
+.. include:: ../Includes.txt
+
+
+.. _developer:
+
+Developer Corner
+================
+
+Target group: **Developers**
+
+Use this section for *providing code examples* or any **useful** information code wise.
+
+
+.. _developer-hooks:
+
+Hooks
+-----
+
+Possible hook examples. Input parameters are:
+
++----------------+---------------+---------------------------------+
+| Parameter | Data type | Description |
++================+===============+=================================+
+| $table | string | Name of the table |
++----------------+---------------+---------------------------------+
+| $field | string | Name of the field |
++----------------+---------------+---------------------------------+
+
+Use parameter :code:`$table` to retrieve the table name...
+
+.. _developer-api:
+
+API
+---
+
+How to use the API...
+
+.. code-block:: php
+
+ $stuff = \TYPO3\CMS\Core\Utility\GeneralUtility::makeInstance(
+ '\\Foo\\Bar\\Utility\\Stuff'
+ );
+ $stuff->do();
+
+or some other language:
+
+.. code-block:: javascript
+ :linenos:
+ :emphasize-lines: 2-4
+
+ $(document).ready(
+ function () {
+ doStuff();
+ }
+ );
diff --git a/Documentation/Images/AdministratorManual/ExtensionManager.png b/Documentation/Images/AdministratorManual/ExtensionManager.png
new file mode 100644
index 0000000..67ea693
Binary files /dev/null and b/Documentation/Images/AdministratorManual/ExtensionManager.png differ
diff --git a/Documentation/Images/IntroductionPackage.png b/Documentation/Images/IntroductionPackage.png
new file mode 100644
index 0000000..1de0f00
Binary files /dev/null and b/Documentation/Images/IntroductionPackage.png differ
diff --git a/Documentation/Images/UserManual/BackendView.png b/Documentation/Images/UserManual/BackendView.png
new file mode 100644
index 0000000..46f90a8
Binary files /dev/null and b/Documentation/Images/UserManual/BackendView.png differ
diff --git a/Documentation/Includes.txt b/Documentation/Includes.txt
new file mode 100644
index 0000000..a111144
--- /dev/null
+++ b/Documentation/Includes.txt
@@ -0,0 +1,21 @@
+.. ==================================================
+.. FOR YOUR INFORMATION
+.. --------------------------------------------------
+.. -*- coding: utf-8 -*- with BOM.
+
+.. This is 'Includes.txt'. It is included at the very top of each and
+ every ReST source file in this documentation project (= manual).
+
+
+.. ==================================================
+.. DEFINE SOME TEXT ROLES
+.. --------------------------------------------------
+
+.. role:: typoscript(code)
+
+.. role:: ts(typoscript)
+ :class: typoscript
+
+.. role:: php(code)
+
+.. highlight:: php
diff --git a/Documentation/Index.rst b/Documentation/Index.rst
new file mode 100644
index 0000000..178e8db
--- /dev/null
+++ b/Documentation/Index.rst
@@ -0,0 +1,64 @@
+.. ==================================================
+.. FOR YOUR INFORMATION
+.. --------------------------------------------------
+.. -*- coding: utf-8 -*- with BOM.
+
+.. include:: Includes.txt
+
+.. _start:
+
+=============================================================
+DD Events
+=============================================================
+
+.. only:: html
+
+ :Classification:
+ dd_events
+
+ :Version:
+ |release|
+
+ :Language:
+ en
+
+ :Description:
+ Extension to manage Destination Data managed events
+
+ :Keywords:
+ comma,separated,list,of,keywords
+
+ :Copyright:
+ 2019
+
+ :Author:
+ Dirk Koritnik
+
+ :Email:
+ koritnik@werkraum-media.de
+
+ :License:
+ This document is published under the Open Content License
+ available from http://www.opencontent.org/opl.shtml
+
+ :Rendered:
+ |today|
+
+ The content of this document is related to TYPO3,
+ a GNU/GPL CMS/Framework available from `www.typo3.org `_.
+
+ **Table of Contents**
+
+.. toctree::
+ :maxdepth: 3
+ :titlesonly:
+
+ Introduction/Index
+ User/Index
+ Administrator/Index
+ Configuration/Index
+ Developer/Index
+ KnownProblems/Index
+ ToDoList/Index
+ ChangeLog/Index
+ Links
diff --git a/Documentation/Introduction/Index.rst b/Documentation/Introduction/Index.rst
new file mode 100644
index 0000000..9044832
--- /dev/null
+++ b/Documentation/Introduction/Index.rst
@@ -0,0 +1,46 @@
+.. ==================================================
+.. FOR YOUR INFORMATION
+.. --------------------------------------------------
+.. -*- coding: utf-8 -*- with BOM.
+
+.. include:: ../Includes.txt
+
+
+.. _introduction:
+
+Introduction
+============
+
+
+.. _what-it-does:
+
+What does it do?
+----------------
+
+This chapter should give a brief overview of the extension. What does it do? What problems does it solve?
+Who is interested in this? Basically, this section includes everything people need to know to decide whether they
+should go on with this extension or not.
+
+.. important::
+
+ Please don't forget to repeat your extension's version number in the
+ :file:`Settings.yml` file, in the :code:`release` property. It will be
+ automatically picked up on the cover page by the :code:`|release|`
+ substitution.
+
+
+.. _screenshots:
+
+Screenshots
+-----------
+
+This chapter should help people figure how the extension works. Remove it
+if not relevant.
+
+.. figure:: ../Images/IntroductionPackage.png
+ :width: 500px
+ :alt: Introduction Package
+
+ Introduction Package just after installation (caption of the image)
+
+ How the Frontend of the Introduction Package looks like just after installation (legend of the image)
diff --git a/Documentation/KnownProblems/Index.rst b/Documentation/KnownProblems/Index.rst
new file mode 100644
index 0000000..dcb52d7
--- /dev/null
+++ b/Documentation/KnownProblems/Index.rst
@@ -0,0 +1,17 @@
+.. ==================================================
+.. FOR YOUR INFORMATION
+.. --------------------------------------------------
+.. -*- coding: utf-8 -*- with BOM.
+
+.. include:: ../Includes.txt
+
+
+.. _known-problems:
+
+Known Problems
+==============
+
+Say where bugs can be reported / followed up. Is it a
+`bug tracker `_?
+Use this section for informing about any type of of problem
+that are not necessarily named in the bug tracker such as performance issues, ...
diff --git a/Documentation/Links.rst b/Documentation/Links.rst
new file mode 100644
index 0000000..93b13e3
--- /dev/null
+++ b/Documentation/Links.rst
@@ -0,0 +1,24 @@
+.. ==================================================
+.. FOR YOUR INFORMATION
+.. --------------------------------------------------
+.. -*- coding: utf-8 -*- with BOM.
+
+.. include:: Includes.txt
+
+
+.. _links:
+
+Links
+-----
+
+:TER:
+ https://typo3.org/extensions/repository/view/
+
+:Bug Tracker:
+ https://forge.typo3.org/projects/extension-/issues
+
+:Git Repository:
+ https://github.com//
+
+:Contact:
+ `@ `__
diff --git a/Documentation/Localization.de_DE.tmpl/Index.rst b/Documentation/Localization.de_DE.tmpl/Index.rst
new file mode 100644
index 0000000..50921e0
--- /dev/null
+++ b/Documentation/Localization.de_DE.tmpl/Index.rst
@@ -0,0 +1,65 @@
+.. ==================================================
+.. FOR YOUR INFORMATION
+.. --------------------------------------------------
+.. -*- coding: utf-8 -*- with BOM.
+
+.. include:: ../Includes.txt
+
+
+.. _start:
+
+=============================================================
+###PROJECT_NAME### (Deutsch)
+=============================================================
+
+.. only:: html
+
+ :Klassifikation:
+ extension_key
+
+ :Version:
+ |release|
+
+ :Sprache:
+ de
+
+ :Beschreibung:
+ Geben Sie eine Beschreibung ein.
+
+ :Schlüsselwörter:
+ komma-getrennte,Liste,von,Schlüsselwörtern
+
+ :Copyright:
+ ###YEAR###
+
+ :Autor:
+ ###AUTHOR###
+
+ :E-Mail:
+ author@example.com
+
+ :Lizenz:
+ Dieses Dokument wird unter der Open Publication License, siehe
+ http://www.opencontent.org/openpub/ veröffentlicht.
+
+ :Gerendert:
+ |today|
+
+ Der Inhalt dieses Dokuments bezieht sich auf TYPO3,
+ ein GNU/GPL CMS-Framework auf `www.typo3.org `__.
+
+
+ **Inhaltsverzeichnis**
+
+.. toctree::
+ :maxdepth: 3
+ :titlesonly:
+
+.. Introduction/Index
+.. UserManual/Index
+.. AdministratorManual/Index
+.. Configuration/Index
+.. DeveloperCorner/Index
+.. KnownProblems/Index
+.. ToDoList/Index
+.. ChangeLog/Index
diff --git a/Documentation/Localization.de_DE.tmpl/README b/Documentation/Localization.de_DE.tmpl/README
new file mode 100644
index 0000000..c1517e6
--- /dev/null
+++ b/Documentation/Localization.de_DE.tmpl/README
@@ -0,0 +1,24 @@
+How to translate
+================
+
+This directory contains the German translation of your documentation.
+This is a complete Sphinx project but you may reuse assets from the
+main documentation under Documentation/.
+
+If you plan to translate your documentation to German, you should
+rename this directory and remove the suffix ".tmpl":
+
+Localization.de_DE.tmpl -> Localization.de_DE
+
+As this file is not needed either, feel free to delete it as well.
+
+
+Supported languages
+===================
+
+Please visit http://sphinx-doc.org/latest/config.html#intl-options for a
+list of languages supported by Sphinx.
+
+Please note however that TYPO3 is using locales so you may need to
+extend the language code from Sphinx into a proper locale to be used
+by TYPO3.
diff --git a/Documentation/Localization.de_DE.tmpl/Settings.yml b/Documentation/Localization.de_DE.tmpl/Settings.yml
new file mode 100644
index 0000000..fefd340
--- /dev/null
+++ b/Documentation/Localization.de_DE.tmpl/Settings.yml
@@ -0,0 +1,29 @@
+# This is the project specific Settings.yml file.
+# Place Sphinx specific build information here.
+# Settings given here will replace the settings of 'conf.py'.
+
+# Below is an example of intersphinx mapping declaration
+# Add more mappings depending on what manual you want to link to
+# Remove entirely if you don't need cross-linking
+
+---
+conf.py:
+ copyright: 2012-2015
+ project: Extension Name (Deutsch)
+ version: x.y
+ release: x.y.z
+ intersphinx_mapping:
+ t3tsref:
+ - https://docs.typo3.org/typo3cms/TyposcriptReference/
+ - null
+ latex_documents:
+ - - Index
+ - .tex
+ - Extension Name (Français)
+ - Your Name
+ - manual
+ latex_elements:
+ papersize: a4paper
+ pointsize: 10pt
+ preamble: \usepackage{typo3}
+...
diff --git a/Documentation/Localization.fr_FR.tmpl/Index.rst b/Documentation/Localization.fr_FR.tmpl/Index.rst
new file mode 100644
index 0000000..c0071e6
--- /dev/null
+++ b/Documentation/Localization.fr_FR.tmpl/Index.rst
@@ -0,0 +1,65 @@
+.. ==================================================
+.. FOR YOUR INFORMATION
+.. --------------------------------------------------
+.. -*- coding: utf-8 -*- with BOM.
+
+.. include:: ../Includes.txt
+
+
+.. _start:
+
+=============================================================
+###PROJECT_NAME### (Français)
+=============================================================
+
+.. only:: html
+
+ :Classification:
+ extension_key
+
+ :Version:
+ |release|
+
+ :Langue:
+ fr
+
+ :Description:
+ entrez une description.
+
+ :Mots-clés:
+ list,mots-clés,séparés,par,virgules
+
+ :Copyright:
+ ###YEAR###
+
+ :Auteur:
+ ###AUTHOR###
+
+ :E-mail:
+ author@example.com
+
+ :Licence:
+ Ce document est publié sous la licence de publication libre
+ disponible sur http://www.opencontent.org/openpub/
+
+ :Généré:
+ |today|
+
+ Le contenu de ce document est en relation avec TYPO3,
+ un CMS/Framework GNU/GPL disponible sur `www.typo3.org `__.
+
+
+ **Sommaire**
+
+.. toctree::
+ :maxdepth: 3
+ :titlesonly:
+
+.. Introduction/Index
+.. UserManual/Index
+.. AdministratorManual/Index
+.. Configuration/Index
+.. DeveloperCorner/Index
+.. KnownProblems/Index
+.. ToDoList/Index
+.. ChangeLog/Index
diff --git a/Documentation/Localization.fr_FR.tmpl/README b/Documentation/Localization.fr_FR.tmpl/README
new file mode 100644
index 0000000..8436ec0
--- /dev/null
+++ b/Documentation/Localization.fr_FR.tmpl/README
@@ -0,0 +1,24 @@
+How to translate
+================
+
+This directory contains the French translation of your documentation.
+This is a complete Sphinx project but you may reuse assets from the
+main documentation under Documentation/.
+
+If you plan to translate your documentation to French, you should
+rename this directory and remove the suffix ".tmpl":
+
+Localization.fr_FR.tmpl -> Localization.fr_FR
+
+As this file is not needed either, feel free to delete it as well.
+
+
+Supported languages
+===================
+
+Please visit http://sphinx-doc.org/latest/config.html#intl-options for a
+list of languages supported by Sphinx.
+
+Please note however that TYPO3 is using locales so you may need to
+extend the language code from Sphinx into a proper locale to be used
+by TYPO3.
diff --git a/Documentation/Localization.fr_FR.tmpl/Settings.yml b/Documentation/Localization.fr_FR.tmpl/Settings.yml
new file mode 100644
index 0000000..0bf2b9d
--- /dev/null
+++ b/Documentation/Localization.fr_FR.tmpl/Settings.yml
@@ -0,0 +1,29 @@
+# This is the project specific Settings.yml file.
+# Place Sphinx specific build information here.
+# Settings given here will replace the settings of 'conf.py'.
+
+# Below is an example of intersphinx mapping declaration
+# Add more mappings depending on what manual you want to link to
+# Remove entirely if you don't need cross-linking
+
+---
+conf.py:
+ copyright: 2012-2015
+ project: Extension Name (Français)
+ version: x.y
+ release: x.y.z
+ intersphinx_mapping:
+ t3tsref:
+ - https://docs.typo3.org/typo3cms/TyposcriptReference/
+ - null
+ latex_documents:
+ - - Index
+ - .tex
+ - Extension Name (Français)
+ - Your Name
+ - manual
+ latex_elements:
+ papersize: a4paper
+ pointsize: 10pt
+ preamble: \usepackage{typo3}
+...
diff --git a/Documentation/Settings.yml b/Documentation/Settings.yml
new file mode 100644
index 0000000..5fd04df
--- /dev/null
+++ b/Documentation/Settings.yml
@@ -0,0 +1,32 @@
+# This is the project specific Settings.yml file.
+# Place Sphinx specific build information here.
+# Settings given here will replace the settings of 'conf.py'.
+
+# Below is an example of intersphinx mapping declaration
+# Add more mappings depending on what manual you want to link to
+# Remove entirely if you don't need cross-linking
+
+---
+conf.py:
+ copyright: 2019
+ project: DD Events
+ version: 1.0.0
+ release: 1.0.0
+ intersphinx_mapping:
+ t3tsref:
+ - http://docs.typo3.org/typo3cms/TyposcriptReference/
+ - null
+ latex_documents:
+ - - Index
+ - dd_events.tex
+ - DD Events
+ - Dirk Koritnik
+ - manual
+ latex_elements:
+ papersize: a4paper
+ pointsize: 10pt
+ preamble: \usepackage
+ html_theme_options:
+ github_repository: TYPO3-Documentation/TYPO3CMS-Example-ExtensionManual
+ github_branch: latest
+...
diff --git a/Documentation/ToDoList/Index.rst b/Documentation/ToDoList/Index.rst
new file mode 100644
index 0000000..5cc010c
--- /dev/null
+++ b/Documentation/ToDoList/Index.rst
@@ -0,0 +1,16 @@
+.. ==================================================
+.. FOR YOUR INFORMATION
+.. --------------------------------------------------
+.. -*- coding: utf-8 -*- with BOM.
+
+.. include:: ../Includes.txt
+
+
+.. _todo:
+
+To-Do list
+==========
+
+Give a link pointing to a `roadmap `_.
+Alternatively, you can dress up a list of things you want to add or fix in this chapter
+or give a vision about where the extension is heading.
diff --git a/Documentation/User/Index.rst b/Documentation/User/Index.rst
new file mode 100644
index 0000000..036869b
--- /dev/null
+++ b/Documentation/User/Index.rst
@@ -0,0 +1,67 @@
+.. ==================================================
+.. FOR YOUR INFORMATION
+.. --------------------------------------------------
+.. -*- coding: utf-8 -*- with BOM.
+
+.. include:: ../Includes.txt
+
+
+.. _user-manual:
+
+Users Manual
+============
+
+Target group: **Editors**
+
+Here should be described how to use the extension from the editor perspective.
+
+- How does it work?
+
+ - works well when doing this.
+
+ - does not work so well when doing that
+ but we can live with it.
+
+ - **mind indentation when nesting lists**.
+
+- How to install the plugin on a web page?
+
+- What options are available?
+
+Language should be non-technical, explaining, using small examples.
+Don't use to many acronyms unless they have been explained.
+Don't be confusing by putting information targeting administrators.
+
+.. tip::
+
+ Take a break from time to time.
+
+Admonitions should be used to warn the users about potential
+pitfalls, attract their attention to important elements
+or just add some notes for for information (further reading,
+for example).
+
+.. important::
+
+ Remember to always say "please" when asking your software to
+ do something.
+
+Provide screenshots as needed for making things clear. When creating
+screenshots, try using the `Introduction Package `_
+as a neutral TYPO3 CMS instance.
+
+.. figure:: ../Images/UserManual/BackendView.png
+ :width: 500px
+ :alt: Backend view
+
+ Default Backend view (caption of the image)
+
+ The Backend view of TYPO3 after the user has clicked on module "Page". (legend of the image)
+
+
+.. _user-faq:
+
+FAQ
+---
+
+Possible subsection: FAQ
diff --git a/ExtensionBuilder.json b/ExtensionBuilder.json
new file mode 100644
index 0000000..173b6eb
--- /dev/null
+++ b/ExtensionBuilder.json
@@ -0,0 +1,638 @@
+{
+ "modules": [
+ {
+ "config": {
+ "position": [
+ 830,
+ 5
+ ]
+ },
+ "name": "New Model Object",
+ "value": {
+ "actionGroup": {
+ "_default0_list": true,
+ "_default1_show": true,
+ "_default2_new_create": false,
+ "_default3_edit_update": false,
+ "_default4_delete": false,
+ "customActions": [
+ "teaser"
+ ]
+ },
+ "name": "Event",
+ "objectsettings": {
+ "addDeletedField": true,
+ "addHiddenField": true,
+ "addStarttimeEndtimeFields": true,
+ "aggregateRoot": false,
+ "categorizable": false,
+ "description": "",
+ "mapToTable": "",
+ "parentClass": "",
+ "sorting": false,
+ "type": "Entity",
+ "uid": "109921408756"
+ },
+ "propertyGroup": {
+ "properties": [
+ {
+ "allowedFileTypes": "",
+ "maxItems": "1",
+ "propertyDescription": "",
+ "propertyIsExcludeField": true,
+ "propertyIsL10nModeExclude": false,
+ "propertyIsRequired": false,
+ "propertyName": "title",
+ "propertyType": "Text",
+ "uid": "102409777447"
+ },
+ {
+ "allowedFileTypes": "",
+ "maxItems": "1",
+ "propertyDescription": "",
+ "propertyIsExcludeField": true,
+ "propertyIsL10nModeExclude": false,
+ "propertyIsRequired": false,
+ "propertyName": "globalId",
+ "propertyType": "String",
+ "uid": "1312474499176"
+ },
+ {
+ "allowedFileTypes": "",
+ "maxItems": "1",
+ "propertyDescription": "",
+ "propertyIsExcludeField": true,
+ "propertyIsL10nModeExclude": false,
+ "propertyIsRequired": false,
+ "propertyName": "slug",
+ "propertyType": "String",
+ "uid": "1365923328864"
+ },
+ {
+ "allowedFileTypes": "",
+ "maxItems": "1",
+ "propertyDescription": "",
+ "propertyIsExcludeField": true,
+ "propertyIsL10nModeExclude": false,
+ "propertyIsRequired": false,
+ "propertyName": "highlight",
+ "propertyType": "Boolean",
+ "uid": "702208098957"
+ },
+ {
+ "allowedFileTypes": "",
+ "maxItems": "1",
+ "propertyDescription": "",
+ "propertyIsExcludeField": true,
+ "propertyIsL10nModeExclude": false,
+ "propertyIsRequired": false,
+ "propertyName": "teaser",
+ "propertyType": "Text",
+ "uid": "1507172184308"
+ },
+ {
+ "allowedFileTypes": "",
+ "maxItems": "1",
+ "propertyDescription": "",
+ "propertyIsExcludeField": true,
+ "propertyIsL10nModeExclude": false,
+ "propertyIsRequired": false,
+ "propertyName": "details",
+ "propertyType": "RichText",
+ "uid": "314424153167"
+ },
+ {
+ "allowedFileTypes": "",
+ "maxItems": "1",
+ "propertyDescription": "",
+ "propertyIsExcludeField": true,
+ "propertyIsL10nModeExclude": false,
+ "propertyIsRequired": false,
+ "propertyName": "priceInfo",
+ "propertyType": "Text",
+ "uid": "448596702496"
+ },
+ {
+ "allowedFileTypes": "",
+ "maxItems": "1",
+ "propertyDescription": "",
+ "propertyIsExcludeField": true,
+ "propertyIsL10nModeExclude": false,
+ "propertyIsRequired": false,
+ "propertyName": "street",
+ "propertyType": "String",
+ "uid": "517245651530"
+ },
+ {
+ "allowedFileTypes": "",
+ "maxItems": "1",
+ "propertyDescription": "",
+ "propertyIsExcludeField": true,
+ "propertyIsL10nModeExclude": false,
+ "propertyIsRequired": false,
+ "propertyName": "district",
+ "propertyType": "String",
+ "uid": "701548922501"
+ },
+ {
+ "allowedFileTypes": "",
+ "maxItems": "1",
+ "propertyDescription": "",
+ "propertyIsExcludeField": true,
+ "propertyIsL10nModeExclude": false,
+ "propertyIsRequired": false,
+ "propertyName": "city",
+ "propertyType": "String",
+ "uid": "565150091343"
+ },
+ {
+ "allowedFileTypes": "",
+ "maxItems": "1",
+ "propertyDescription": "",
+ "propertyIsExcludeField": true,
+ "propertyIsL10nModeExclude": false,
+ "propertyIsRequired": false,
+ "propertyName": "zip",
+ "propertyType": "String",
+ "uid": "1052357865101"
+ },
+ {
+ "allowedFileTypes": "",
+ "maxItems": "1",
+ "propertyDescription": "",
+ "propertyIsExcludeField": true,
+ "propertyIsL10nModeExclude": false,
+ "propertyIsRequired": false,
+ "propertyName": "country",
+ "propertyType": "String",
+ "uid": "437952486493"
+ },
+ {
+ "allowedFileTypes": "",
+ "maxItems": "1",
+ "propertyDescription": "",
+ "propertyIsExcludeField": true,
+ "propertyIsL10nModeExclude": false,
+ "propertyIsRequired": false,
+ "propertyName": "web",
+ "propertyType": "String",
+ "uid": "886851132875"
+ },
+ {
+ "allowedFileTypes": "",
+ "maxItems": "1",
+ "propertyDescription": "",
+ "propertyIsExcludeField": true,
+ "propertyIsL10nModeExclude": false,
+ "propertyIsRequired": false,
+ "propertyName": "booking",
+ "propertyType": "String",
+ "uid": "1258790658884"
+ },
+ {
+ "allowedFileTypes": "",
+ "maxItems": "1",
+ "propertyDescription": "",
+ "propertyIsExcludeField": true,
+ "propertyIsL10nModeExclude": false,
+ "propertyIsRequired": false,
+ "propertyName": "ticket",
+ "propertyType": "String",
+ "uid": "832122856559"
+ },
+ {
+ "allowedFileTypes": "",
+ "maxItems": "1",
+ "propertyDescription": "",
+ "propertyIsExcludeField": true,
+ "propertyIsL10nModeExclude": false,
+ "propertyIsRequired": false,
+ "propertyName": "facebook",
+ "propertyType": "String",
+ "uid": "1386671701366"
+ },
+ {
+ "allowedFileTypes": "",
+ "maxItems": "1",
+ "propertyDescription": "",
+ "propertyIsExcludeField": true,
+ "propertyIsL10nModeExclude": false,
+ "propertyIsRequired": false,
+ "propertyName": "youtube",
+ "propertyType": "String",
+ "uid": "1246060567520"
+ },
+ {
+ "allowedFileTypes": "",
+ "maxItems": "1",
+ "propertyDescription": "",
+ "propertyIsExcludeField": true,
+ "propertyIsL10nModeExclude": false,
+ "propertyIsRequired": false,
+ "propertyName": "latitude",
+ "propertyType": "String",
+ "uid": "1312904595125"
+ },
+ {
+ "allowedFileTypes": "",
+ "maxItems": "1",
+ "propertyDescription": "",
+ "propertyIsExcludeField": true,
+ "propertyIsL10nModeExclude": false,
+ "propertyIsRequired": false,
+ "propertyName": "longitude",
+ "propertyType": "String",
+ "uid": "671898304575"
+ },
+ {
+ "allowedFileTypes": "",
+ "maxItems": "1",
+ "propertyDescription": "",
+ "propertyIsExcludeField": true,
+ "propertyIsL10nModeExclude": false,
+ "propertyIsRequired": false,
+ "propertyName": "images",
+ "propertyType": "Image",
+ "uid": "259140197650"
+ },
+ {
+ "allowedFileTypes": "",
+ "maxItems": "1",
+ "propertyDescription": "",
+ "propertyIsExcludeField": true,
+ "propertyIsL10nModeExclude": false,
+ "propertyIsRequired": false,
+ "propertyName": "categories",
+ "propertyType": "Integer",
+ "uid": "677483446855"
+ }
+ ]
+ },
+ "relationGroup": {
+ "relations": [
+ {
+ "foreignRelationClass": "",
+ "lazyLoading": false,
+ "propertyIsExcludeField": true,
+ "relationDescription": "",
+ "relationName": "dates",
+ "relationType": "zeroToMany",
+ "relationWire": "[wired]",
+ "renderType": "inline",
+ "uid": "120463841009"
+ },
+ {
+ "foreignRelationClass": "",
+ "lazyLoading": false,
+ "propertyIsExcludeField": true,
+ "relationDescription": "",
+ "relationName": "organizer",
+ "relationType": "manyToOne",
+ "relationWire": "[wired]",
+ "renderType": "selectSingle",
+ "uid": "272437572533"
+ },
+ {
+ "foreignRelationClass": "",
+ "lazyLoading": false,
+ "propertyIsExcludeField": true,
+ "relationDescription": "",
+ "relationName": "region",
+ "relationType": "manyToOne",
+ "relationWire": "[wired]",
+ "renderType": "selectSingle",
+ "uid": "1093126928530"
+ }
+ ]
+ }
+ }
+ },
+ {
+ "config": {
+ "position": [
+ 315,
+ 132
+ ]
+ },
+ "name": "New Model Object",
+ "value": {
+ "actionGroup": {
+ "_default0_list": false,
+ "_default1_show": false,
+ "_default2_new_create": false,
+ "_default3_edit_update": false,
+ "_default4_delete": false,
+ "customActions": []
+ },
+ "name": "Organizer",
+ "objectsettings": {
+ "addDeletedField": true,
+ "addHiddenField": true,
+ "addStarttimeEndtimeFields": true,
+ "aggregateRoot": false,
+ "categorizable": false,
+ "description": "",
+ "mapToTable": "",
+ "parentClass": "",
+ "sorting": false,
+ "type": "Entity",
+ "uid": "853312122030"
+ },
+ "propertyGroup": {
+ "properties": [
+ {
+ "allowedFileTypes": "",
+ "maxItems": "1",
+ "propertyDescription": "",
+ "propertyIsExcludeField": true,
+ "propertyIsL10nModeExclude": false,
+ "propertyIsRequired": false,
+ "propertyName": "name",
+ "propertyType": "String",
+ "uid": "1039029201328"
+ },
+ {
+ "allowedFileTypes": "",
+ "maxItems": "1",
+ "propertyDescription": "",
+ "propertyIsExcludeField": true,
+ "propertyIsL10nModeExclude": false,
+ "propertyIsRequired": false,
+ "propertyName": "street",
+ "propertyType": "String",
+ "uid": "332930486259"
+ },
+ {
+ "allowedFileTypes": "",
+ "maxItems": "1",
+ "propertyDescription": "",
+ "propertyIsExcludeField": true,
+ "propertyIsL10nModeExclude": false,
+ "propertyIsRequired": false,
+ "propertyName": "district",
+ "propertyType": "String",
+ "uid": "1300937445752"
+ },
+ {
+ "allowedFileTypes": "",
+ "maxItems": "1",
+ "propertyDescription": "",
+ "propertyIsExcludeField": true,
+ "propertyIsL10nModeExclude": false,
+ "propertyIsRequired": false,
+ "propertyName": "city",
+ "propertyType": "String",
+ "uid": "114683887277"
+ },
+ {
+ "allowedFileTypes": "",
+ "maxItems": "1",
+ "propertyDescription": "",
+ "propertyIsExcludeField": true,
+ "propertyIsL10nModeExclude": false,
+ "propertyIsRequired": false,
+ "propertyName": "zip",
+ "propertyType": "String",
+ "uid": "390187572664"
+ },
+ {
+ "allowedFileTypes": "",
+ "maxItems": "1",
+ "propertyDescription": "",
+ "propertyIsExcludeField": true,
+ "propertyIsL10nModeExclude": false,
+ "propertyIsRequired": false,
+ "propertyName": "phone",
+ "propertyType": "String",
+ "uid": "16157077259"
+ },
+ {
+ "allowedFileTypes": "",
+ "maxItems": "1",
+ "propertyDescription": "",
+ "propertyIsExcludeField": true,
+ "propertyIsL10nModeExclude": false,
+ "propertyIsRequired": false,
+ "propertyName": "web",
+ "propertyType": "String",
+ "uid": "106668624565"
+ },
+ {
+ "allowedFileTypes": "",
+ "maxItems": "1",
+ "propertyDescription": "",
+ "propertyIsExcludeField": true,
+ "propertyIsL10nModeExclude": false,
+ "propertyIsRequired": false,
+ "propertyName": "email",
+ "propertyType": "String",
+ "uid": "837795943910"
+ }
+ ]
+ },
+ "relationGroup": {
+ "relations": []
+ }
+ }
+ },
+ {
+ "config": {
+ "position": [
+ 318,
+ 376
+ ]
+ },
+ "name": "New Model Object",
+ "value": {
+ "actionGroup": {
+ "_default0_list": true,
+ "_default1_show": true,
+ "_default2_new_create": false,
+ "_default3_edit_update": false,
+ "_default4_delete": false,
+ "customActions": [
+ "teaser"
+ ]
+ },
+ "name": "Date",
+ "objectsettings": {
+ "addDeletedField": true,
+ "addHiddenField": true,
+ "addStarttimeEndtimeFields": true,
+ "aggregateRoot": false,
+ "categorizable": false,
+ "description": "",
+ "mapToTable": "",
+ "parentClass": "",
+ "sorting": false,
+ "type": "Entity",
+ "uid": "19849981223"
+ },
+ "propertyGroup": {
+ "properties": [
+ {
+ "allowedFileTypes": "",
+ "maxItems": "1",
+ "propertyDescription": "",
+ "propertyIsExcludeField": true,
+ "propertyIsL10nModeExclude": false,
+ "propertyIsRequired": false,
+ "propertyName": "start",
+ "propertyType": "NativeDateTime",
+ "uid": "1175274648657"
+ },
+ {
+ "allowedFileTypes": "",
+ "maxItems": "1",
+ "propertyDescription": "",
+ "propertyIsExcludeField": true,
+ "propertyIsL10nModeExclude": false,
+ "propertyIsRequired": false,
+ "propertyName": "end",
+ "propertyType": "NativeDateTime",
+ "uid": "119149519780"
+ }
+ ]
+ },
+ "relationGroup": {
+ "relations": []
+ }
+ }
+ },
+ {
+ "config": {
+ "position": [
+ 315,
+ 613
+ ]
+ },
+ "name": "New Model Object",
+ "value": {
+ "actionGroup": {
+ "_default0_list": false,
+ "_default1_show": false,
+ "_default2_new_create": false,
+ "_default3_edit_update": false,
+ "_default4_delete": false,
+ "customActions": []
+ },
+ "name": "Region",
+ "objectsettings": {
+ "addDeletedField": true,
+ "addHiddenField": true,
+ "addStarttimeEndtimeFields": true,
+ "aggregateRoot": false,
+ "categorizable": false,
+ "description": "",
+ "mapToTable": "",
+ "parentClass": "",
+ "sorting": false,
+ "type": "Entity",
+ "uid": "425722520612"
+ },
+ "propertyGroup": {
+ "properties": [
+ {
+ "allowedFileTypes": "",
+ "maxItems": "1",
+ "propertyDescription": "",
+ "propertyIsExcludeField": true,
+ "propertyIsL10nModeExclude": false,
+ "propertyIsRequired": false,
+ "propertyName": "title",
+ "propertyType": "String",
+ "uid": "1316430837945"
+ }
+ ]
+ },
+ "relationGroup": {
+ "relations": []
+ }
+ }
+ }
+ ],
+ "properties": {
+ "backendModules": [],
+ "description": "Extension to manage Destination Data managed events",
+ "emConf": {
+ "category": "plugin",
+ "custom_category": "",
+ "dependsOn": "typo3 => 9.5.0-9.5.99\n",
+ "disableLocalization": false,
+ "disableVersioning": false,
+ "skipGenerateDocumentationTemplate": false,
+ "sourceLanguage": "en",
+ "state": "alpha",
+ "targetVersion": "9.5.0-9.5.99",
+ "version": "1.0.0"
+ },
+ "extensionKey": "dd_events",
+ "name": "DD Events",
+ "originalExtensionKey": "dd_events",
+ "originalVendorName": "Wrm",
+ "persons": [
+ {
+ "company": "",
+ "email": "koritnik@werkraum-media.de",
+ "name": "Dirk Koritnik",
+ "role": "Developer"
+ }
+ ],
+ "plugins": [
+ {
+ "actions": {
+ "controllerActionCombinations": "Event=>teaser, list, show\nDate=>teaser, list, show",
+ "noncacheableActions": "Event=>teaser, list, show\nDate=>teaser, list, show",
+ "switchableActions": "Display Events\nEvent=>teaser; Event=>list; Event=>show\nDisplay Dates\nDate=>teaser; Date=>list; Date=>show"
+ },
+ "description": "",
+ "key": "ddevents",
+ "name": "DD Events"
+ }
+ ],
+ "vendorName": "Wrm"
+ },
+ "wires": [
+ {
+ "src": {
+ "moduleId": 0,
+ "terminal": "relationWire_0",
+ "uid": "120463841009"
+ },
+ "tgt": {
+ "moduleId": 2,
+ "terminal": "SOURCES",
+ "uid": "19849981223"
+ }
+ },
+ {
+ "src": {
+ "moduleId": 0,
+ "terminal": "relationWire_1",
+ "uid": "272437572533"
+ },
+ "tgt": {
+ "moduleId": 1,
+ "terminal": "SOURCES",
+ "uid": "853312122030"
+ }
+ },
+ {
+ "src": {
+ "moduleId": 0,
+ "terminal": "relationWire_2",
+ "uid": "1093126928530"
+ },
+ "tgt": {
+ "moduleId": 3,
+ "terminal": "SOURCES",
+ "uid": "425722520612"
+ }
+ }
+ ],
+ "log": {
+ "last_modified": "2019-04-03 12:11",
+ "extension_builder_version": "9.10.0",
+ "be_user": "Dirk Koritnik (1)"
+ }
+}
\ No newline at end of file
diff --git a/README.md b/README.md
index 2444140..a299ca5 100644
--- a/README.md
+++ b/README.md
@@ -1,3 +1,19 @@
-# events
+### Destination Data Event Import Extension
-TYPO3 extension to sync and manage events
\ No newline at end of file
+##### Start Symfony Command to import Events local
+
+ TYPO3_CONTEXT=Development php vendor/bin/typo3 events:import
+
+##### Start Symfony Command to import Events on Stage
+
+ TYPO3_CONTEXT=Production/Staging /usr/local/bin/php7.1.6-cli typo3cms/stage.thueringer-staedte.de/current/vendor/bin/typo3 events:import
+
+##### Clean category relations
+
+ TRUNCATE TABLE tx_events_domain_model_event;
+ TRUNCATE TABLE tx_events_domain_model_date;
+ TRUNCATE TABLE tx_events_domain_model_organizer;
+ DELETE FROM sys_category_record_mm WHERE tablenames = 'tx_events_domain_model_event';
+ DELETE FROM sys_file_reference WHERE tablenames = 'tx_events_domain_model_event';
+ DELETE FROM sys_file WHERE identifier LIKE '%/events/%';
+ DELETE FROM sys_file_metadata WHERE alternative = 'DD Import';
\ No newline at end of file
diff --git a/Resources/Private/.htaccess b/Resources/Private/.htaccess
new file mode 100644
index 0000000..96d0729
--- /dev/null
+++ b/Resources/Private/.htaccess
@@ -0,0 +1,11 @@
+# Apache < 2.3
+
+ Order allow,deny
+ Deny from all
+ Satisfy All
+
+
+# Apache >= 2.3
+
+ Require all denied
+
diff --git a/Resources/Private/Language/de.locallang.xlf b/Resources/Private/Language/de.locallang.xlf
new file mode 100644
index 0000000..e07ab4a
--- /dev/null
+++ b/Resources/Private/Language/de.locallang.xlf
@@ -0,0 +1,32 @@
+
+
+
+
+
+
+ Search form
+ Suchformular
+
+
+ Search word
+ Suchwort
+
+
+ Date from
+ Datum von
+
+
+ Date to
+ Date bis
+
+
+ All regions
+ Alle Städte
+
+
+ Search
+ Suchen
+
+
+
+
diff --git a/Resources/Private/Language/de.locallang_csh_date.xlf b/Resources/Private/Language/de.locallang_csh_date.xlf
new file mode 100644
index 0000000..f52c5ef
--- /dev/null
+++ b/Resources/Private/Language/de.locallang_csh_date.xlf
@@ -0,0 +1,24 @@
+
+
+
+
+
+
+ Date
+ Termin
+
+
+ Start
+ Beginn
+
+
+ End
+ Ende
+
+
+ Associated event
+ Verknüpfte Veranstaltungen
+
+
+
+
diff --git a/Resources/Private/Language/de.locallang_csh_event.xlf b/Resources/Private/Language/de.locallang_csh_event.xlf
new file mode 100644
index 0000000..0b8d472
--- /dev/null
+++ b/Resources/Private/Language/de.locallang_csh_event.xlf
@@ -0,0 +1,128 @@
+
+
+
+
+
+
+ Events
+ Veranstaltungen
+
+
+ Event Modul
+ Veranstaltungs Modul
+
+
+ Event
+ Veranstaltung
+
+
+ Title
+ Titel
+
+
+ Global UID
+ Globale UID
+
+
+ Slug
+ URL-Segment
+
+
+ Highlight
+ Höhepunkt
+
+
+ Teaser
+ Kurztext
+
+
+ Details
+ Text
+
+
+ Price Info
+ Preis Information
+
+
+ Name
+ Name
+
+
+ Street
+ Straße
+
+
+ District
+ Bundesland
+
+
+ City
+ Stadt
+
+
+ Zip
+ Postleitzahl
+
+
+ Country
+ Land
+
+
+ Web
+ Internet
+
+
+ Phone
+ Telefon
+
+
+ Ticket
+ Ticket
+
+
+ Facebook
+ Facebook
+
+
+ YouTube
+ YouTube
+
+
+ Instagram
+ Instagram
+
+
+ Latitude
+ Breitengrad
+
+
+ Longitude
+ Längengrad
+
+
+ Images
+ Bilder
+
+
+ Categories
+ Kategorien
+
+
+ Dates
+ Termine
+
+
+ Organizer
+ Organisator
+
+
+ Region
+ Region
+
+
+ Organizer
+ Organisator
+
+
+
+
diff --git a/Resources/Private/Language/de.locallang_csh_organizer.xlf b/Resources/Private/Language/de.locallang_csh_organizer.xlf
new file mode 100644
index 0000000..4703dbc
--- /dev/null
+++ b/Resources/Private/Language/de.locallang_csh_organizer.xlf
@@ -0,0 +1,44 @@
+
+
+
+
+
+
+ Organizer
+ Organisator
+
+
+ Name
+ Name
+
+
+ Street
+ Straße
+
+
+ District
+ Bundesland
+
+
+ City
+ Stadt
+
+
+ Zip
+ Postleitzahl
+
+
+ Phone
+ Telefon
+
+
+ Web
+ Internet
+
+
+ E-Mail
+ E-Mail
+
+
+
+
diff --git a/Resources/Private/Language/de.locallang_csh_region.xlf b/Resources/Private/Language/de.locallang_csh_region.xlf
new file mode 100644
index 0000000..4c1c1f3
--- /dev/null
+++ b/Resources/Private/Language/de.locallang_csh_region.xlf
@@ -0,0 +1,16 @@
+
+
+
+
+
+
+ Region
+ Region
+
+
+ Title
+ Titel
+
+
+
+
diff --git a/Resources/Private/Language/de.locallang_db.xlf b/Resources/Private/Language/de.locallang_db.xlf
new file mode 100644
index 0000000..468831a
--- /dev/null
+++ b/Resources/Private/Language/de.locallang_db.xlf
@@ -0,0 +1,16 @@
+
+
+
+
+
+
+ Events
+ Veranstaltungen
+
+
+ Event Modul
+ Veranstaltungs Modul
+
+
+
+
diff --git a/Resources/Private/Language/locallang.xlf b/Resources/Private/Language/locallang.xlf
new file mode 100644
index 0000000..ca11660
--- /dev/null
+++ b/Resources/Private/Language/locallang.xlf
@@ -0,0 +1,26 @@
+
+
+
+
+
+
+ Search form
+
+
+ Search word
+
+
+ Date from
+
+
+ Date to
+
+
+ All regions
+
+
+ Search
+
+
+
+
diff --git a/Resources/Private/Language/locallang_csh_date.xlf b/Resources/Private/Language/locallang_csh_date.xlf
new file mode 100644
index 0000000..3270004
--- /dev/null
+++ b/Resources/Private/Language/locallang_csh_date.xlf
@@ -0,0 +1,20 @@
+
+
+
+
+
+
+ Date
+
+
+ Start
+
+
+ End
+
+
+ Associated event
+
+
+
+
diff --git a/Resources/Private/Language/locallang_csh_event.xlf b/Resources/Private/Language/locallang_csh_event.xlf
new file mode 100644
index 0000000..6608918
--- /dev/null
+++ b/Resources/Private/Language/locallang_csh_event.xlf
@@ -0,0 +1,95 @@
+
+
+
+
+
+
+ Events
+
+
+ Event Modul
+
+
+ Event
+
+
+ Title
+
+
+ Global UID
+
+
+ Slug
+
+
+ Highlight
+
+
+ Teaser
+
+
+ Details
+
+
+ Price Info
+
+
+ Name
+
+
+ Street
+
+
+ District
+
+
+ City
+
+
+ Zip
+
+
+ Country
+
+
+ Web
+
+
+ Phone
+
+
+ Ticket
+
+
+ Facebook
+
+
+ Youtube
+
+
+ Instagram
+
+
+ Latitude
+
+
+ Longitude
+
+
+ Images
+
+
+ Categories
+
+
+ Dates
+
+
+ Organizer
+
+
+ Region
+
+
+
+
diff --git a/Resources/Private/Language/locallang_csh_organizer.xlf b/Resources/Private/Language/locallang_csh_organizer.xlf
new file mode 100644
index 0000000..0187dab
--- /dev/null
+++ b/Resources/Private/Language/locallang_csh_organizer.xlf
@@ -0,0 +1,35 @@
+
+
+
+
+
+
+ Organizer
+
+
+ Name
+
+
+ Street
+
+
+ District
+
+
+ City
+
+
+ Zip
+
+
+ Phone
+
+
+ Web
+
+
+ E-Mail
+
+
+
+
diff --git a/Resources/Private/Language/locallang_csh_region.xlf b/Resources/Private/Language/locallang_csh_region.xlf
new file mode 100644
index 0000000..48fd713
--- /dev/null
+++ b/Resources/Private/Language/locallang_csh_region.xlf
@@ -0,0 +1,14 @@
+
+
+
+
+
+
+ Region
+
+
+ Title
+
+
+
+
diff --git a/Resources/Private/Language/locallang_db.xlf b/Resources/Private/Language/locallang_db.xlf
new file mode 100644
index 0000000..9462876
--- /dev/null
+++ b/Resources/Private/Language/locallang_db.xlf
@@ -0,0 +1,14 @@
+
+
+
+
+
+
+ Events
+
+
+ Event Modul
+
+
+
+
diff --git a/Resources/Private/Layouts/Default.html b/Resources/Private/Layouts/Default.html
new file mode 100644
index 0000000..bf25019
--- /dev/null
+++ b/Resources/Private/Layouts/Default.html
@@ -0,0 +1,5 @@
+
+
+
+
+
\ No newline at end of file
diff --git a/Resources/Private/Partials/Date/ListDefault.html b/Resources/Private/Partials/Date/ListDefault.html
new file mode 100644
index 0000000..c62a6fb
--- /dev/null
+++ b/Resources/Private/Partials/Date/ListDefault.html
@@ -0,0 +1,38 @@
+
+
+
+
+
+
+
+ {date.event.region.title} |
{date.start}
+
{date.event.title}
+
{date.event.teaser}
+
+
+
+
+
+
+
+
+
diff --git a/Resources/Private/Partials/Date/ListTable.html b/Resources/Private/Partials/Date/ListTable.html
new file mode 100644
index 0000000..d959692
--- /dev/null
+++ b/Resources/Private/Partials/Date/ListTable.html
@@ -0,0 +1,57 @@
+
+
+
+
+
+
+
+ {date.start}
+ {date.start}
+ {date.start}
+ {date.event.region.title}
+
+
+
+
+
+
+
+
+ {date.event.title}
+
+
+
{date.event.teaser}
+
{date.event.details}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/Resources/Private/Partials/Event/SearchForm.html b/Resources/Private/Partials/Event/SearchForm.html
new file mode 100644
index 0000000..34f9236
--- /dev/null
+++ b/Resources/Private/Partials/Event/SearchForm.html
@@ -0,0 +1,14 @@
+
+
+
diff --git a/Resources/Private/Templates/Date/List.html b/Resources/Private/Templates/Date/List.html
new file mode 100644
index 0000000..f447317
--- /dev/null
+++ b/Resources/Private/Templates/Date/List.html
@@ -0,0 +1,16 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Resources/Private/Templates/Date/Search.html b/Resources/Private/Templates/Date/Search.html
new file mode 100644
index 0000000..156fa2b
--- /dev/null
+++ b/Resources/Private/Templates/Date/Search.html
@@ -0,0 +1,75 @@
+
+
+
+
+
+
diff --git a/Resources/Private/Templates/Date/SearchHtml.html b/Resources/Private/Templates/Date/SearchHtml.html
new file mode 100644
index 0000000..8ea1438
--- /dev/null
+++ b/Resources/Private/Templates/Date/SearchHtml.html
@@ -0,0 +1,68 @@
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Resources/Private/Templates/Date/Show.html b/Resources/Private/Templates/Date/Show.html
new file mode 100644
index 0000000..7d9ed35
--- /dev/null
+++ b/Resources/Private/Templates/Date/Show.html
@@ -0,0 +1,70 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {date.start}
+ {date.start}
+ {date.start} Uhr
+
+
{date.event.title}
+
{date.event.teaser}
+
{date.event.details}
+
{event.price_info}
+
+
+
+
+
+
+
Preis:
+
+
+ {date.event.priceInfo}
+
+
+ Keine Information
+
+
+
+
+
+ Weitere Informationen:
+ Website
+
+
+
+
+
Veranstaltungsort:
+ {date.event.street}
+ {date.event.zip} {date.event.city}
+ {date.event.phone}
+
+
+
+
Veranstalter:
+ {date.event.organizer.name}
+ {date.event.organizer.street}
+ {date.event.organizer.zip} {date.event.organizer.city}
+ {date.event.organizer.phone}
+ Website
+
+
+
+
+
diff --git a/Resources/Private/Templates/Date/Teaser.html b/Resources/Private/Templates/Date/Teaser.html
new file mode 100644
index 0000000..4f2f9de
--- /dev/null
+++ b/Resources/Private/Templates/Date/Teaser.html
@@ -0,0 +1,42 @@
+
+
+
+
+
+
+
+
+
+
+
+
+ {date.event.region.title} |
{date.start}
+
{date.event.title}
+
{date.event.teaser}
+
+
+ Hightlight
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Resources/Private/Templates/Event/List.html b/Resources/Private/Templates/Event/List.html
new file mode 100644
index 0000000..d9ec46f
--- /dev/null
+++ b/Resources/Private/Templates/Event/List.html
@@ -0,0 +1,33 @@
+
+
+
+
+
+
+
+
+
+
+ {event.region.title}
+
{event.title}
+
{event.teaser}
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Resources/Private/Templates/Event/Search.html b/Resources/Private/Templates/Event/Search.html
new file mode 100644
index 0000000..2e5cd72
--- /dev/null
+++ b/Resources/Private/Templates/Event/Search.html
@@ -0,0 +1,29 @@
+
+
+
+
+
+
+
+
+ {event.region.title}
+
{event.title}
+
{event.teaser}
+
+
+
+
+
\ No newline at end of file
diff --git a/Resources/Private/Templates/Event/Show.html b/Resources/Private/Templates/Event/Show.html
new file mode 100644
index 0000000..49d418b
--- /dev/null
+++ b/Resources/Private/Templates/Event/Show.html
@@ -0,0 +1,37 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
{event.title}
+
{event.teaser}
+
{event.details}
+
{event.price_info}
+
+
+
+
Veranstaltungsort:
+ {event.street}
+ {event.zip} {event.city}
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Resources/Private/Templates/Event/Teaser.html b/Resources/Private/Templates/Event/Teaser.html
new file mode 100644
index 0000000..b0019bb
--- /dev/null
+++ b/Resources/Private/Templates/Event/Teaser.html
@@ -0,0 +1,33 @@
+
+
+
+
+
+
+
+
+
+
+ {event.region.title}
+
{event.title}
+
{event.teaser}
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Resources/Private/Templates/ViewHelpers/Widget/Paginate/Index.html b/Resources/Private/Templates/ViewHelpers/Widget/Paginate/Index.html
new file mode 100644
index 0000000..c8c84b1
--- /dev/null
+++ b/Resources/Private/Templates/ViewHelpers/Widget/Paginate/Index.html
@@ -0,0 +1,91 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/Resources/Public/Icons/Extension.svg b/Resources/Public/Icons/Extension.svg
new file mode 100644
index 0000000..ec1bdec
--- /dev/null
+++ b/Resources/Public/Icons/Extension.svg
@@ -0,0 +1 @@
+Extension
\ No newline at end of file
diff --git a/Resources/Public/Icons/relation.gif b/Resources/Public/Icons/relation.gif
new file mode 100644
index 0000000..db61d7e
Binary files /dev/null and b/Resources/Public/Icons/relation.gif differ
diff --git a/Resources/Public/Icons/tx_events_domain_model_date.gif b/Resources/Public/Icons/tx_events_domain_model_date.gif
new file mode 100644
index 0000000..37ba37b
Binary files /dev/null and b/Resources/Public/Icons/tx_events_domain_model_date.gif differ
diff --git a/Resources/Public/Icons/tx_events_domain_model_event.gif b/Resources/Public/Icons/tx_events_domain_model_event.gif
new file mode 100644
index 0000000..37ba37b
Binary files /dev/null and b/Resources/Public/Icons/tx_events_domain_model_event.gif differ
diff --git a/Resources/Public/Icons/tx_events_domain_model_events.gif b/Resources/Public/Icons/tx_events_domain_model_events.gif
new file mode 100644
index 0000000..37ba37b
Binary files /dev/null and b/Resources/Public/Icons/tx_events_domain_model_events.gif differ
diff --git a/Resources/Public/Icons/tx_events_domain_model_organizer.gif b/Resources/Public/Icons/tx_events_domain_model_organizer.gif
new file mode 100644
index 0000000..37ba37b
Binary files /dev/null and b/Resources/Public/Icons/tx_events_domain_model_organizer.gif differ
diff --git a/Resources/Public/Icons/tx_events_domain_model_region.gif b/Resources/Public/Icons/tx_events_domain_model_region.gif
new file mode 100644
index 0000000..37ba37b
Binary files /dev/null and b/Resources/Public/Icons/tx_events_domain_model_region.gif differ
diff --git a/Resources/Public/Icons/user_plugin_events.svg b/Resources/Public/Icons/user_plugin_events.svg
new file mode 100644
index 0000000..17e1eb1
--- /dev/null
+++ b/Resources/Public/Icons/user_plugin_events.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/Resources/Public/Images/default.jpg b/Resources/Public/Images/default.jpg
new file mode 100644
index 0000000..1d216a4
Binary files /dev/null and b/Resources/Public/Images/default.jpg differ
diff --git a/Tests/Unit/Controller/DateControllerTest.php b/Tests/Unit/Controller/DateControllerTest.php
new file mode 100644
index 0000000..e6cfc3c
--- /dev/null
+++ b/Tests/Unit/Controller/DateControllerTest.php
@@ -0,0 +1,67 @@
+
+ */
+class DateControllerTest extends \TYPO3\TestingFramework\Core\Unit\UnitTestCase
+{
+ /**
+ * @var \Wrm\Events\Controller\DateController
+ */
+ protected $subject = null;
+
+ protected function setUp()
+ {
+ parent::setUp();
+ $this->subject = $this->getMockBuilder(\Wrm\Events\Controller\DateController::class)
+ ->setMethods(['redirect', 'forward', 'addFlashMessage'])
+ ->disableOriginalConstructor()
+ ->getMock();
+ }
+
+ protected function tearDown()
+ {
+ parent::tearDown();
+ }
+
+ /**
+ * @test
+ */
+ public function listActionFetchesAllDatesFromRepositoryAndAssignsThemToView()
+ {
+
+ $allDates = $this->getMockBuilder(\TYPO3\CMS\Extbase\Persistence\ObjectStorage::class)
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $dateRepository = $this->getMockBuilder(\::class)
+ ->setMethods(['findAll'])
+ ->disableOriginalConstructor()
+ ->getMock();
+ $dateRepository->expects(self::once())->method('findAll')->will(self::returnValue($allDates));
+ $this->inject($this->subject, 'dateRepository', $dateRepository);
+
+ $view = $this->getMockBuilder(\TYPO3\CMS\Extbase\Mvc\View\ViewInterface::class)->getMock();
+ $view->expects(self::once())->method('assign')->with('dates', $allDates);
+ $this->inject($this->subject, 'view', $view);
+
+ $this->subject->listAction();
+ }
+
+ /**
+ * @test
+ */
+ public function showActionAssignsTheGivenDateToView()
+ {
+ $date = new \Wrm\Events\Domain\Model\Date();
+
+ $view = $this->getMockBuilder(\TYPO3\CMS\Extbase\Mvc\View\ViewInterface::class)->getMock();
+ $this->inject($this->subject, 'view', $view);
+ $view->expects(self::once())->method('assign')->with('date', $date);
+
+ $this->subject->showAction($date);
+ }
+}
diff --git a/Tests/Unit/Controller/EventControllerTest.php b/Tests/Unit/Controller/EventControllerTest.php
new file mode 100644
index 0000000..e68341f
--- /dev/null
+++ b/Tests/Unit/Controller/EventControllerTest.php
@@ -0,0 +1,67 @@
+
+ */
+class EventControllerTest extends \TYPO3\TestingFramework\Core\Unit\UnitTestCase
+{
+ /**
+ * @var \Wrm\Events\Controller\EventController
+ */
+ protected $subject = null;
+
+ protected function setUp()
+ {
+ parent::setUp();
+ $this->subject = $this->getMockBuilder(\Wrm\Events\Controller\EventController::class)
+ ->setMethods(['redirect', 'forward', 'addFlashMessage'])
+ ->disableOriginalConstructor()
+ ->getMock();
+ }
+
+ protected function tearDown()
+ {
+ parent::tearDown();
+ }
+
+ /**
+ * @test
+ */
+ public function listActionFetchesAllEventsFromRepositoryAndAssignsThemToView()
+ {
+
+ $allEvents = $this->getMockBuilder(\TYPO3\CMS\Extbase\Persistence\ObjectStorage::class)
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $eventRepository = $this->getMockBuilder(\::class)
+ ->setMethods(['findAll'])
+ ->disableOriginalConstructor()
+ ->getMock();
+ $eventRepository->expects(self::once())->method('findAll')->will(self::returnValue($allEvents));
+ $this->inject($this->subject, 'eventRepository', $eventRepository);
+
+ $view = $this->getMockBuilder(\TYPO3\CMS\Extbase\Mvc\View\ViewInterface::class)->getMock();
+ $view->expects(self::once())->method('assign')->with('events', $allEvents);
+ $this->inject($this->subject, 'view', $view);
+
+ $this->subject->listAction();
+ }
+
+ /**
+ * @test
+ */
+ public function showActionAssignsTheGivenEventToView()
+ {
+ $event = new \Wrm\Events\Domain\Model\Event();
+
+ $view = $this->getMockBuilder(\TYPO3\CMS\Extbase\Mvc\View\ViewInterface::class)->getMock();
+ $this->inject($this->subject, 'view', $view);
+ $view->expects(self::once())->method('assign')->with('event', $event);
+
+ $this->subject->showAction($event);
+ }
+}
diff --git a/Tests/Unit/Controller/EventsControllerTest.php b/Tests/Unit/Controller/EventsControllerTest.php
new file mode 100644
index 0000000..ce780f6
--- /dev/null
+++ b/Tests/Unit/Controller/EventsControllerTest.php
@@ -0,0 +1,67 @@
+
+ */
+class EventsControllerTest extends \TYPO3\TestingFramework\Core\Unit\UnitTestCase
+{
+ /**
+ * @var \Wrm\Events\Controller\EventsController
+ */
+ protected $subject = null;
+
+ protected function setUp()
+ {
+ parent::setUp();
+ $this->subject = $this->getMockBuilder(\Wrm\Events\Controller\EventsController::class)
+ ->setMethods(['redirect', 'forward', 'addFlashMessage'])
+ ->disableOriginalConstructor()
+ ->getMock();
+ }
+
+ protected function tearDown()
+ {
+ parent::tearDown();
+ }
+
+ /**
+ * @test
+ */
+ public function listActionFetchesAllEventssFromRepositoryAndAssignsThemToView()
+ {
+
+ $allEventss = $this->getMockBuilder(\TYPO3\CMS\Extbase\Persistence\ObjectStorage::class)
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $eventsRepository = $this->getMockBuilder(\::class)
+ ->setMethods(['findAll'])
+ ->disableOriginalConstructor()
+ ->getMock();
+ $eventsRepository->expects(self::once())->method('findAll')->will(self::returnValue($allEventss));
+ $this->inject($this->subject, 'eventsRepository', $eventsRepository);
+
+ $view = $this->getMockBuilder(\TYPO3\CMS\Extbase\Mvc\View\ViewInterface::class)->getMock();
+ $view->expects(self::once())->method('assign')->with('eventss', $allEventss);
+ $this->inject($this->subject, 'view', $view);
+
+ $this->subject->listAction();
+ }
+
+ /**
+ * @test
+ */
+ public function showActionAssignsTheGivenEventsToView()
+ {
+ $events = new \Wrm\Events\Domain\Model\Events();
+
+ $view = $this->getMockBuilder(\TYPO3\CMS\Extbase\Mvc\View\ViewInterface::class)->getMock();
+ $this->inject($this->subject, 'view', $view);
+ $view->expects(self::once())->method('assign')->with('events', $events);
+
+ $this->subject->showAction($events);
+ }
+}
diff --git a/Tests/Unit/Domain/Model/DateTest.php b/Tests/Unit/Domain/Model/DateTest.php
new file mode 100644
index 0000000..9c8945c
--- /dev/null
+++ b/Tests/Unit/Domain/Model/DateTest.php
@@ -0,0 +1,78 @@
+
+ */
+class DateTest extends \TYPO3\TestingFramework\Core\Unit\UnitTestCase
+{
+ /**
+ * @var \Wrm\Events\Domain\Model\Date
+ */
+ protected $subject = null;
+
+ protected function setUp()
+ {
+ parent::setUp();
+ $this->subject = new \Wrm\Events\Domain\Model\Date();
+ }
+
+ protected function tearDown()
+ {
+ parent::tearDown();
+ }
+
+ /**
+ * @test
+ */
+ public function getStartReturnsInitialValueForDateTime()
+ {
+ self::assertEquals(
+ null,
+ $this->subject->getStart()
+ );
+ }
+
+ /**
+ * @test
+ */
+ public function setStartForDateTimeSetsStart()
+ {
+ $dateTimeFixture = new \DateTime();
+ $this->subject->setStart($dateTimeFixture);
+
+ self::assertAttributeEquals(
+ $dateTimeFixture,
+ 'start',
+ $this->subject
+ );
+ }
+
+ /**
+ * @test
+ */
+ public function getEndReturnsInitialValueForDateTime()
+ {
+ self::assertEquals(
+ null,
+ $this->subject->getEnd()
+ );
+ }
+
+ /**
+ * @test
+ */
+ public function setEndForDateTimeSetsEnd()
+ {
+ $dateTimeFixture = new \DateTime();
+ $this->subject->setEnd($dateTimeFixture);
+
+ self::assertAttributeEquals(
+ $dateTimeFixture,
+ 'end',
+ $this->subject
+ );
+ }
+}
diff --git a/Tests/Unit/Domain/Model/EventTest.php b/Tests/Unit/Domain/Model/EventTest.php
new file mode 100644
index 0000000..c6d8af4
--- /dev/null
+++ b/Tests/Unit/Domain/Model/EventTest.php
@@ -0,0 +1,667 @@
+
+ */
+class EventTest extends \TYPO3\TestingFramework\Core\Unit\UnitTestCase
+{
+ /**
+ * @var \Wrm\Events\Domain\Model\Event
+ */
+ protected $subject = null;
+
+ protected function setUp()
+ {
+ parent::setUp();
+ $this->subject = new \Wrm\Events\Domain\Model\Event();
+ }
+
+ protected function tearDown()
+ {
+ parent::tearDown();
+ }
+
+ /**
+ * @test
+ */
+ public function getTitleReturnsInitialValueForString()
+ {
+ self::assertSame(
+ '',
+ $this->subject->getTitle()
+ );
+ }
+
+ /**
+ * @test
+ */
+ public function setTitleForStringSetsTitle()
+ {
+ $this->subject->setTitle('Conceived at T3CON10');
+
+ self::assertAttributeEquals(
+ 'Conceived at T3CON10',
+ 'title',
+ $this->subject
+ );
+ }
+
+ /**
+ * @test
+ */
+ public function getGlobalIdReturnsInitialValueForString()
+ {
+ self::assertSame(
+ '',
+ $this->subject->getGlobalId()
+ );
+ }
+
+ /**
+ * @test
+ */
+ public function setGlobalIdForStringSetsGlobalId()
+ {
+ $this->subject->setGlobalId('Conceived at T3CON10');
+
+ self::assertAttributeEquals(
+ 'Conceived at T3CON10',
+ 'globalId',
+ $this->subject
+ );
+ }
+
+ /**
+ * @test
+ */
+ public function getSlugReturnsInitialValueForString()
+ {
+ self::assertSame(
+ '',
+ $this->subject->getSlug()
+ );
+ }
+
+ /**
+ * @test
+ */
+ public function setSlugForStringSetsSlug()
+ {
+ $this->subject->setSlug('Conceived at T3CON10');
+
+ self::assertAttributeEquals(
+ 'Conceived at T3CON10',
+ 'slug',
+ $this->subject
+ );
+ }
+
+ /**
+ * @test
+ */
+ public function getHighlightReturnsInitialValueForBool()
+ {
+ self::assertSame(
+ false,
+ $this->subject->getHighlight()
+ );
+ }
+
+ /**
+ * @test
+ */
+ public function setHighlightForBoolSetsHighlight()
+ {
+ $this->subject->setHighlight(true);
+
+ self::assertAttributeEquals(
+ true,
+ 'highlight',
+ $this->subject
+ );
+ }
+
+ /**
+ * @test
+ */
+ public function getTeaserReturnsInitialValueForString()
+ {
+ self::assertSame(
+ '',
+ $this->subject->getTeaser()
+ );
+ }
+
+ /**
+ * @test
+ */
+ public function setTeaserForStringSetsTeaser()
+ {
+ $this->subject->setTeaser('Conceived at T3CON10');
+
+ self::assertAttributeEquals(
+ 'Conceived at T3CON10',
+ 'teaser',
+ $this->subject
+ );
+ }
+
+ /**
+ * @test
+ */
+ public function getDetailsReturnsInitialValueForString()
+ {
+ self::assertSame(
+ '',
+ $this->subject->getDetails()
+ );
+ }
+
+ /**
+ * @test
+ */
+ public function setDetailsForStringSetsDetails()
+ {
+ $this->subject->setDetails('Conceived at T3CON10');
+
+ self::assertAttributeEquals(
+ 'Conceived at T3CON10',
+ 'details',
+ $this->subject
+ );
+ }
+
+ /**
+ * @test
+ */
+ public function getPriceInfoReturnsInitialValueForString()
+ {
+ self::assertSame(
+ '',
+ $this->subject->getPriceInfo()
+ );
+ }
+
+ /**
+ * @test
+ */
+ public function setPriceInfoForStringSetsPriceInfo()
+ {
+ $this->subject->setPriceInfo('Conceived at T3CON10');
+
+ self::assertAttributeEquals(
+ 'Conceived at T3CON10',
+ 'priceInfo',
+ $this->subject
+ );
+ }
+
+ /**
+ * @test
+ */
+ public function getStreetReturnsInitialValueForString()
+ {
+ self::assertSame(
+ '',
+ $this->subject->getStreet()
+ );
+ }
+
+ /**
+ * @test
+ */
+ public function setStreetForStringSetsStreet()
+ {
+ $this->subject->setStreet('Conceived at T3CON10');
+
+ self::assertAttributeEquals(
+ 'Conceived at T3CON10',
+ 'street',
+ $this->subject
+ );
+ }
+
+ /**
+ * @test
+ */
+ public function getDistrictReturnsInitialValueForString()
+ {
+ self::assertSame(
+ '',
+ $this->subject->getDistrict()
+ );
+ }
+
+ /**
+ * @test
+ */
+ public function setDistrictForStringSetsDistrict()
+ {
+ $this->subject->setDistrict('Conceived at T3CON10');
+
+ self::assertAttributeEquals(
+ 'Conceived at T3CON10',
+ 'district',
+ $this->subject
+ );
+ }
+
+ /**
+ * @test
+ */
+ public function getCityReturnsInitialValueForString()
+ {
+ self::assertSame(
+ '',
+ $this->subject->getCity()
+ );
+ }
+
+ /**
+ * @test
+ */
+ public function setCityForStringSetsCity()
+ {
+ $this->subject->setCity('Conceived at T3CON10');
+
+ self::assertAttributeEquals(
+ 'Conceived at T3CON10',
+ 'city',
+ $this->subject
+ );
+ }
+
+ /**
+ * @test
+ */
+ public function getZipReturnsInitialValueForString()
+ {
+ self::assertSame(
+ '',
+ $this->subject->getZip()
+ );
+ }
+
+ /**
+ * @test
+ */
+ public function setZipForStringSetsZip()
+ {
+ $this->subject->setZip('Conceived at T3CON10');
+
+ self::assertAttributeEquals(
+ 'Conceived at T3CON10',
+ 'zip',
+ $this->subject
+ );
+ }
+
+ /**
+ * @test
+ */
+ public function getCountryReturnsInitialValueForString()
+ {
+ self::assertSame(
+ '',
+ $this->subject->getCountry()
+ );
+ }
+
+ /**
+ * @test
+ */
+ public function setCountryForStringSetsCountry()
+ {
+ $this->subject->setCountry('Conceived at T3CON10');
+
+ self::assertAttributeEquals(
+ 'Conceived at T3CON10',
+ 'country',
+ $this->subject
+ );
+ }
+
+ /**
+ * @test
+ */
+ public function getWebReturnsInitialValueForString()
+ {
+ self::assertSame(
+ '',
+ $this->subject->getWeb()
+ );
+ }
+
+ /**
+ * @test
+ */
+ public function setWebForStringSetsWeb()
+ {
+ $this->subject->setWeb('Conceived at T3CON10');
+
+ self::assertAttributeEquals(
+ 'Conceived at T3CON10',
+ 'web',
+ $this->subject
+ );
+ }
+
+ /**
+ * @test
+ */
+ public function getBookingReturnsInitialValueForString()
+ {
+ self::assertSame(
+ '',
+ $this->subject->getBooking()
+ );
+ }
+
+ /**
+ * @test
+ */
+ public function setBookingForStringSetsBooking()
+ {
+ $this->subject->setBooking('Conceived at T3CON10');
+
+ self::assertAttributeEquals(
+ 'Conceived at T3CON10',
+ 'booking',
+ $this->subject
+ );
+ }
+
+ /**
+ * @test
+ */
+ public function getTicketReturnsInitialValueForString()
+ {
+ self::assertSame(
+ '',
+ $this->subject->getTicket()
+ );
+ }
+
+ /**
+ * @test
+ */
+ public function setTicketForStringSetsTicket()
+ {
+ $this->subject->setTicket('Conceived at T3CON10');
+
+ self::assertAttributeEquals(
+ 'Conceived at T3CON10',
+ 'ticket',
+ $this->subject
+ );
+ }
+
+ /**
+ * @test
+ */
+ public function getFacebookReturnsInitialValueForString()
+ {
+ self::assertSame(
+ '',
+ $this->subject->getFacebook()
+ );
+ }
+
+ /**
+ * @test
+ */
+ public function setFacebookForStringSetsFacebook()
+ {
+ $this->subject->setFacebook('Conceived at T3CON10');
+
+ self::assertAttributeEquals(
+ 'Conceived at T3CON10',
+ 'facebook',
+ $this->subject
+ );
+ }
+
+ /**
+ * @test
+ */
+ public function getYoutubeReturnsInitialValueForString()
+ {
+ self::assertSame(
+ '',
+ $this->subject->getYoutube()
+ );
+ }
+
+ /**
+ * @test
+ */
+ public function setYoutubeForStringSetsYoutube()
+ {
+ $this->subject->setYoutube('Conceived at T3CON10');
+
+ self::assertAttributeEquals(
+ 'Conceived at T3CON10',
+ 'youtube',
+ $this->subject
+ );
+ }
+
+ /**
+ * @test
+ */
+ public function getLatitudeReturnsInitialValueForString()
+ {
+ self::assertSame(
+ '',
+ $this->subject->getLatitude()
+ );
+ }
+
+ /**
+ * @test
+ */
+ public function setLatitudeForStringSetsLatitude()
+ {
+ $this->subject->setLatitude('Conceived at T3CON10');
+
+ self::assertAttributeEquals(
+ 'Conceived at T3CON10',
+ 'latitude',
+ $this->subject
+ );
+ }
+
+ /**
+ * @test
+ */
+ public function getLongitudeReturnsInitialValueForString()
+ {
+ self::assertSame(
+ '',
+ $this->subject->getLongitude()
+ );
+ }
+
+ /**
+ * @test
+ */
+ public function setLongitudeForStringSetsLongitude()
+ {
+ $this->subject->setLongitude('Conceived at T3CON10');
+
+ self::assertAttributeEquals(
+ 'Conceived at T3CON10',
+ 'longitude',
+ $this->subject
+ );
+ }
+
+ /**
+ * @test
+ */
+ public function getImagesReturnsInitialValueForFileReference()
+ {
+ self::assertEquals(
+ null,
+ $this->subject->getImages()
+ );
+ }
+
+ /**
+ * @test
+ */
+ public function setImagesForFileReferenceSetsImages()
+ {
+ $fileReferenceFixture = new \TYPO3\CMS\Extbase\Domain\Model\FileReference();
+ $this->subject->setImages($fileReferenceFixture);
+
+ self::assertAttributeEquals(
+ $fileReferenceFixture,
+ 'images',
+ $this->subject
+ );
+ }
+
+ /**
+ * @test
+ */
+ public function getCategoriesReturnsInitialValueForInt()
+ {
+ self::assertSame(
+ 0,
+ $this->subject->getCategories()
+ );
+ }
+
+ /**
+ * @test
+ */
+ public function setCategoriesForIntSetsCategories()
+ {
+ $this->subject->setCategories(12);
+
+ self::assertAttributeEquals(
+ 12,
+ 'categories',
+ $this->subject
+ );
+ }
+
+ /**
+ * @test
+ */
+ public function getDatesReturnsInitialValueForDate()
+ {
+ $newObjectStorage = new \TYPO3\CMS\Extbase\Persistence\ObjectStorage();
+ self::assertEquals(
+ $newObjectStorage,
+ $this->subject->getDates()
+ );
+ }
+
+ /**
+ * @test
+ */
+ public function setDatesForObjectStorageContainingDateSetsDates()
+ {
+ $date = new \Wrm\Events\Domain\Model\Date();
+ $objectStorageHoldingExactlyOneDates = new \TYPO3\CMS\Extbase\Persistence\ObjectStorage();
+ $objectStorageHoldingExactlyOneDates->attach($date);
+ $this->subject->setDates($objectStorageHoldingExactlyOneDates);
+
+ self::assertAttributeEquals(
+ $objectStorageHoldingExactlyOneDates,
+ 'dates',
+ $this->subject
+ );
+ }
+
+ /**
+ * @test
+ */
+ public function addDateToObjectStorageHoldingDates()
+ {
+ $date = new \Wrm\Events\Domain\Model\Date();
+ $datesObjectStorageMock = $this->getMockBuilder(\TYPO3\CMS\Extbase\Persistence\ObjectStorage::class)
+ ->setMethods(['attach'])
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $datesObjectStorageMock->expects(self::once())->method('attach')->with(self::equalTo($date));
+ $this->inject($this->subject, 'dates', $datesObjectStorageMock);
+
+ $this->subject->addDate($date);
+ }
+
+ /**
+ * @test
+ */
+ public function removeDateFromObjectStorageHoldingDates()
+ {
+ $date = new \Wrm\Events\Domain\Model\Date();
+ $datesObjectStorageMock = $this->getMockBuilder(\TYPO3\CMS\Extbase\Persistence\ObjectStorage::class)
+ ->setMethods(['detach'])
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $datesObjectStorageMock->expects(self::once())->method('detach')->with(self::equalTo($date));
+ $this->inject($this->subject, 'dates', $datesObjectStorageMock);
+
+ $this->subject->removeDate($date);
+ }
+
+ /**
+ * @test
+ */
+ public function getOrganizerReturnsInitialValueForOrganizer()
+ {
+ self::assertEquals(
+ null,
+ $this->subject->getOrganizer()
+ );
+ }
+
+ /**
+ * @test
+ */
+ public function setOrganizerForOrganizerSetsOrganizer()
+ {
+ $organizerFixture = new \Wrm\Events\Domain\Model\Organizer();
+ $this->subject->setOrganizer($organizerFixture);
+
+ self::assertAttributeEquals(
+ $organizerFixture,
+ 'organizer',
+ $this->subject
+ );
+ }
+
+ /**
+ * @test
+ */
+ public function getRegionReturnsInitialValueForRegion()
+ {
+ self::assertEquals(
+ null,
+ $this->subject->getRegion()
+ );
+ }
+
+ /**
+ * @test
+ */
+ public function setRegionForRegionSetsRegion()
+ {
+ $regionFixture = new \Wrm\Events\Domain\Model\Region();
+ $this->subject->setRegion($regionFixture);
+
+ self::assertAttributeEquals(
+ $regionFixture,
+ 'region',
+ $this->subject
+ );
+ }
+}
diff --git a/Tests/Unit/Domain/Model/EventsTest.php b/Tests/Unit/Domain/Model/EventsTest.php
new file mode 100644
index 0000000..7510f7a
--- /dev/null
+++ b/Tests/Unit/Domain/Model/EventsTest.php
@@ -0,0 +1,617 @@
+
+ */
+class EventsTest extends \TYPO3\TestingFramework\Core\Unit\UnitTestCase
+{
+ /**
+ * @var \Wrm\Events\Domain\Model\Events
+ */
+ protected $subject = null;
+
+ protected function setUp()
+ {
+ parent::setUp();
+ $this->subject = new \Wrm\Events\Domain\Model\Events();
+ }
+
+ protected function tearDown()
+ {
+ parent::tearDown();
+ }
+
+ /**
+ * @test
+ */
+ public function getGlobalIdReturnsInitialValueForString()
+ {
+ self::assertSame(
+ '',
+ $this->subject->getGlobalId()
+ );
+ }
+
+ /**
+ * @test
+ */
+ public function setGlobalIdForStringSetsGlobalId()
+ {
+ $this->subject->setGlobalId('Conceived at T3CON10');
+
+ self::assertAttributeEquals(
+ 'Conceived at T3CON10',
+ 'globalId',
+ $this->subject
+ );
+ }
+
+ /**
+ * @test
+ */
+ public function getTitleReturnsInitialValueForString()
+ {
+ self::assertSame(
+ '',
+ $this->subject->getTitle()
+ );
+ }
+
+ /**
+ * @test
+ */
+ public function setTitleForStringSetsTitle()
+ {
+ $this->subject->setTitle('Conceived at T3CON10');
+
+ self::assertAttributeEquals(
+ 'Conceived at T3CON10',
+ 'title',
+ $this->subject
+ );
+ }
+
+ /**
+ * @test
+ */
+ public function getTeaserReturnsInitialValueForString()
+ {
+ self::assertSame(
+ '',
+ $this->subject->getTeaser()
+ );
+ }
+
+ /**
+ * @test
+ */
+ public function setTeaserForStringSetsTeaser()
+ {
+ $this->subject->setTeaser('Conceived at T3CON10');
+
+ self::assertAttributeEquals(
+ 'Conceived at T3CON10',
+ 'teaser',
+ $this->subject
+ );
+ }
+
+ /**
+ * @test
+ */
+ public function getDetailsReturnsInitialValueForString()
+ {
+ self::assertSame(
+ '',
+ $this->subject->getDetails()
+ );
+ }
+
+ /**
+ * @test
+ */
+ public function setDetailsForStringSetsDetails()
+ {
+ $this->subject->setDetails('Conceived at T3CON10');
+
+ self::assertAttributeEquals(
+ 'Conceived at T3CON10',
+ 'details',
+ $this->subject
+ );
+ }
+
+ /**
+ * @test
+ */
+ public function getPriceInfoReturnsInitialValueForString()
+ {
+ self::assertSame(
+ '',
+ $this->subject->getPriceInfo()
+ );
+ }
+
+ /**
+ * @test
+ */
+ public function setPriceInfoForStringSetsPriceInfo()
+ {
+ $this->subject->setPriceInfo('Conceived at T3CON10');
+
+ self::assertAttributeEquals(
+ 'Conceived at T3CON10',
+ 'priceInfo',
+ $this->subject
+ );
+ }
+
+ /**
+ * @test
+ */
+ public function getStreetReturnsInitialValueForString()
+ {
+ self::assertSame(
+ '',
+ $this->subject->getStreet()
+ );
+ }
+
+ /**
+ * @test
+ */
+ public function setStreetForStringSetsStreet()
+ {
+ $this->subject->setStreet('Conceived at T3CON10');
+
+ self::assertAttributeEquals(
+ 'Conceived at T3CON10',
+ 'street',
+ $this->subject
+ );
+ }
+
+ /**
+ * @test
+ */
+ public function getDistrictReturnsInitialValueForString()
+ {
+ self::assertSame(
+ '',
+ $this->subject->getDistrict()
+ );
+ }
+
+ /**
+ * @test
+ */
+ public function setDistrictForStringSetsDistrict()
+ {
+ $this->subject->setDistrict('Conceived at T3CON10');
+
+ self::assertAttributeEquals(
+ 'Conceived at T3CON10',
+ 'district',
+ $this->subject
+ );
+ }
+
+ /**
+ * @test
+ */
+ public function getCityReturnsInitialValueForString()
+ {
+ self::assertSame(
+ '',
+ $this->subject->getCity()
+ );
+ }
+
+ /**
+ * @test
+ */
+ public function setCityForStringSetsCity()
+ {
+ $this->subject->setCity('Conceived at T3CON10');
+
+ self::assertAttributeEquals(
+ 'Conceived at T3CON10',
+ 'city',
+ $this->subject
+ );
+ }
+
+ /**
+ * @test
+ */
+ public function getZipReturnsInitialValueForString()
+ {
+ self::assertSame(
+ '',
+ $this->subject->getZip()
+ );
+ }
+
+ /**
+ * @test
+ */
+ public function setZipForStringSetsZip()
+ {
+ $this->subject->setZip('Conceived at T3CON10');
+
+ self::assertAttributeEquals(
+ 'Conceived at T3CON10',
+ 'zip',
+ $this->subject
+ );
+ }
+
+ /**
+ * @test
+ */
+ public function getWebReturnsInitialValueForString()
+ {
+ self::assertSame(
+ '',
+ $this->subject->getWeb()
+ );
+ }
+
+ /**
+ * @test
+ */
+ public function setWebForStringSetsWeb()
+ {
+ $this->subject->setWeb('Conceived at T3CON10');
+
+ self::assertAttributeEquals(
+ 'Conceived at T3CON10',
+ 'web',
+ $this->subject
+ );
+ }
+
+ /**
+ * @test
+ */
+ public function getBookingReturnsInitialValueForString()
+ {
+ self::assertSame(
+ '',
+ $this->subject->getBooking()
+ );
+ }
+
+ /**
+ * @test
+ */
+ public function setBookingForStringSetsBooking()
+ {
+ $this->subject->setBooking('Conceived at T3CON10');
+
+ self::assertAttributeEquals(
+ 'Conceived at T3CON10',
+ 'booking',
+ $this->subject
+ );
+ }
+
+ /**
+ * @test
+ */
+ public function getTicketReturnsInitialValueForString()
+ {
+ self::assertSame(
+ '',
+ $this->subject->getTicket()
+ );
+ }
+
+ /**
+ * @test
+ */
+ public function setTicketForStringSetsTicket()
+ {
+ $this->subject->setTicket('Conceived at T3CON10');
+
+ self::assertAttributeEquals(
+ 'Conceived at T3CON10',
+ 'ticket',
+ $this->subject
+ );
+ }
+
+ /**
+ * @test
+ */
+ public function getFacebookReturnsInitialValueForString()
+ {
+ self::assertSame(
+ '',
+ $this->subject->getFacebook()
+ );
+ }
+
+ /**
+ * @test
+ */
+ public function setFacebookForStringSetsFacebook()
+ {
+ $this->subject->setFacebook('Conceived at T3CON10');
+
+ self::assertAttributeEquals(
+ 'Conceived at T3CON10',
+ 'facebook',
+ $this->subject
+ );
+ }
+
+ /**
+ * @test
+ */
+ public function getYoutubeReturnsInitialValueForString()
+ {
+ self::assertSame(
+ '',
+ $this->subject->getYoutube()
+ );
+ }
+
+ /**
+ * @test
+ */
+ public function setYoutubeForStringSetsYoutube()
+ {
+ $this->subject->setYoutube('Conceived at T3CON10');
+
+ self::assertAttributeEquals(
+ 'Conceived at T3CON10',
+ 'youtube',
+ $this->subject
+ );
+ }
+
+ /**
+ * @test
+ */
+ public function getLatitudeReturnsInitialValueForString()
+ {
+ self::assertSame(
+ '',
+ $this->subject->getLatitude()
+ );
+ }
+
+ /**
+ * @test
+ */
+ public function setLatitudeForStringSetsLatitude()
+ {
+ $this->subject->setLatitude('Conceived at T3CON10');
+
+ self::assertAttributeEquals(
+ 'Conceived at T3CON10',
+ 'latitude',
+ $this->subject
+ );
+ }
+
+ /**
+ * @test
+ */
+ public function getLongitudeReturnsInitialValueForString()
+ {
+ self::assertSame(
+ '',
+ $this->subject->getLongitude()
+ );
+ }
+
+ /**
+ * @test
+ */
+ public function setLongitudeForStringSetsLongitude()
+ {
+ $this->subject->setLongitude('Conceived at T3CON10');
+
+ self::assertAttributeEquals(
+ 'Conceived at T3CON10',
+ 'longitude',
+ $this->subject
+ );
+ }
+
+ /**
+ * @test
+ */
+ public function getImagesReturnsInitialValueForFileReference()
+ {
+ self::assertEquals(
+ null,
+ $this->subject->getImages()
+ );
+ }
+
+ /**
+ * @test
+ */
+ public function setImagesForFileReferenceSetsImages()
+ {
+ $fileReferenceFixture = new \TYPO3\CMS\Extbase\Domain\Model\FileReference();
+ $this->subject->setImages($fileReferenceFixture);
+
+ self::assertAttributeEquals(
+ $fileReferenceFixture,
+ 'images',
+ $this->subject
+ );
+ }
+
+ /**
+ * @test
+ */
+ public function getSlugReturnsInitialValueForString()
+ {
+ self::assertSame(
+ '',
+ $this->subject->getSlug()
+ );
+ }
+
+ /**
+ * @test
+ */
+ public function setSlugForStringSetsSlug()
+ {
+ $this->subject->setSlug('Conceived at T3CON10');
+
+ self::assertAttributeEquals(
+ 'Conceived at T3CON10',
+ 'slug',
+ $this->subject
+ );
+ }
+
+ /**
+ * @test
+ */
+ public function getOrganizerReturnsInitialValueFor()
+ {
+ }
+
+ /**
+ * @test
+ */
+ public function setOrganizerForSetsOrganizer()
+ {
+ }
+
+ /**
+ * @test
+ */
+ public function getDateReturnsInitialValueFor()
+ {
+ $newObjectStorage = new \TYPO3\CMS\Extbase\Persistence\ObjectStorage();
+ self::assertEquals(
+ $newObjectStorage,
+ $this->subject->getDate()
+ );
+ }
+
+ /**
+ * @test
+ */
+ public function setDateForObjectStorageContainingSetsDate()
+ {
+ $date = new ();
+ $objectStorageHoldingExactlyOneDate = new \TYPO3\CMS\Extbase\Persistence\ObjectStorage();
+ $objectStorageHoldingExactlyOneDate->attach($date);
+ $this->subject->setDate($objectStorageHoldingExactlyOneDate);
+
+ self::assertAttributeEquals(
+ $objectStorageHoldingExactlyOneDate,
+ 'date',
+ $this->subject
+ );
+ }
+
+ /**
+ * @test
+ */
+ public function addDateToObjectStorageHoldingDate()
+ {
+ $date = new ();
+ $dateObjectStorageMock = $this->getMockBuilder(\TYPO3\CMS\Extbase\Persistence\ObjectStorage::class)
+ ->setMethods(['attach'])
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $dateObjectStorageMock->expects(self::once())->method('attach')->with(self::equalTo($date));
+ $this->inject($this->subject, 'date', $dateObjectStorageMock);
+
+ $this->subject->addDate($date);
+ }
+
+ /**
+ * @test
+ */
+ public function removeDateFromObjectStorageHoldingDate()
+ {
+ $date = new ();
+ $dateObjectStorageMock = $this->getMockBuilder(\TYPO3\CMS\Extbase\Persistence\ObjectStorage::class)
+ ->setMethods(['detach'])
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $dateObjectStorageMock->expects(self::once())->method('detach')->with(self::equalTo($date));
+ $this->inject($this->subject, 'date', $dateObjectStorageMock);
+
+ $this->subject->removeDate($date);
+ }
+
+ /**
+ * @test
+ */
+ public function getRegionReturnsInitialValueFor()
+ {
+ $newObjectStorage = new \TYPO3\CMS\Extbase\Persistence\ObjectStorage();
+ self::assertEquals(
+ $newObjectStorage,
+ $this->subject->getRegion()
+ );
+ }
+
+ /**
+ * @test
+ */
+ public function setRegionForObjectStorageContainingSetsRegion()
+ {
+ $region = new ();
+ $objectStorageHoldingExactlyOneRegion = new \TYPO3\CMS\Extbase\Persistence\ObjectStorage();
+ $objectStorageHoldingExactlyOneRegion->attach($region);
+ $this->subject->setRegion($objectStorageHoldingExactlyOneRegion);
+
+ self::assertAttributeEquals(
+ $objectStorageHoldingExactlyOneRegion,
+ 'region',
+ $this->subject
+ );
+ }
+
+ /**
+ * @test
+ */
+ public function addRegionToObjectStorageHoldingRegion()
+ {
+ $region = new ();
+ $regionObjectStorageMock = $this->getMockBuilder(\TYPO3\CMS\Extbase\Persistence\ObjectStorage::class)
+ ->setMethods(['attach'])
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $regionObjectStorageMock->expects(self::once())->method('attach')->with(self::equalTo($region));
+ $this->inject($this->subject, 'region', $regionObjectStorageMock);
+
+ $this->subject->addRegion($region);
+ }
+
+ /**
+ * @test
+ */
+ public function removeRegionFromObjectStorageHoldingRegion()
+ {
+ $region = new ();
+ $regionObjectStorageMock = $this->getMockBuilder(\TYPO3\CMS\Extbase\Persistence\ObjectStorage::class)
+ ->setMethods(['detach'])
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $regionObjectStorageMock->expects(self::once())->method('detach')->with(self::equalTo($region));
+ $this->inject($this->subject, 'region', $regionObjectStorageMock);
+
+ $this->subject->removeRegion($region);
+ }
+}
diff --git a/Tests/Unit/Domain/Model/OrganizerTest.php b/Tests/Unit/Domain/Model/OrganizerTest.php
new file mode 100644
index 0000000..d4487cf
--- /dev/null
+++ b/Tests/Unit/Domain/Model/OrganizerTest.php
@@ -0,0 +1,226 @@
+
+ */
+class OrganizerTest extends \TYPO3\TestingFramework\Core\Unit\UnitTestCase
+{
+ /**
+ * @var \Wrm\Events\Domain\Model\Organizer
+ */
+ protected $subject = null;
+
+ protected function setUp()
+ {
+ parent::setUp();
+ $this->subject = new \Wrm\Events\Domain\Model\Organizer();
+ }
+
+ protected function tearDown()
+ {
+ parent::tearDown();
+ }
+
+ /**
+ * @test
+ */
+ public function getNameReturnsInitialValueForString()
+ {
+ self::assertSame(
+ '',
+ $this->subject->getName()
+ );
+ }
+
+ /**
+ * @test
+ */
+ public function setNameForStringSetsName()
+ {
+ $this->subject->setName('Conceived at T3CON10');
+
+ self::assertAttributeEquals(
+ 'Conceived at T3CON10',
+ 'name',
+ $this->subject
+ );
+ }
+
+ /**
+ * @test
+ */
+ public function getStreetReturnsInitialValueForString()
+ {
+ self::assertSame(
+ '',
+ $this->subject->getStreet()
+ );
+ }
+
+ /**
+ * @test
+ */
+ public function setStreetForStringSetsStreet()
+ {
+ $this->subject->setStreet('Conceived at T3CON10');
+
+ self::assertAttributeEquals(
+ 'Conceived at T3CON10',
+ 'street',
+ $this->subject
+ );
+ }
+
+ /**
+ * @test
+ */
+ public function getDistrictReturnsInitialValueForString()
+ {
+ self::assertSame(
+ '',
+ $this->subject->getDistrict()
+ );
+ }
+
+ /**
+ * @test
+ */
+ public function setDistrictForStringSetsDistrict()
+ {
+ $this->subject->setDistrict('Conceived at T3CON10');
+
+ self::assertAttributeEquals(
+ 'Conceived at T3CON10',
+ 'district',
+ $this->subject
+ );
+ }
+
+ /**
+ * @test
+ */
+ public function getCityReturnsInitialValueForString()
+ {
+ self::assertSame(
+ '',
+ $this->subject->getCity()
+ );
+ }
+
+ /**
+ * @test
+ */
+ public function setCityForStringSetsCity()
+ {
+ $this->subject->setCity('Conceived at T3CON10');
+
+ self::assertAttributeEquals(
+ 'Conceived at T3CON10',
+ 'city',
+ $this->subject
+ );
+ }
+
+ /**
+ * @test
+ */
+ public function getZipReturnsInitialValueForString()
+ {
+ self::assertSame(
+ '',
+ $this->subject->getZip()
+ );
+ }
+
+ /**
+ * @test
+ */
+ public function setZipForStringSetsZip()
+ {
+ $this->subject->setZip('Conceived at T3CON10');
+
+ self::assertAttributeEquals(
+ 'Conceived at T3CON10',
+ 'zip',
+ $this->subject
+ );
+ }
+
+ /**
+ * @test
+ */
+ public function getPhoneReturnsInitialValueForString()
+ {
+ self::assertSame(
+ '',
+ $this->subject->getPhone()
+ );
+ }
+
+ /**
+ * @test
+ */
+ public function setPhoneForStringSetsPhone()
+ {
+ $this->subject->setPhone('Conceived at T3CON10');
+
+ self::assertAttributeEquals(
+ 'Conceived at T3CON10',
+ 'phone',
+ $this->subject
+ );
+ }
+
+ /**
+ * @test
+ */
+ public function getWebReturnsInitialValueForString()
+ {
+ self::assertSame(
+ '',
+ $this->subject->getWeb()
+ );
+ }
+
+ /**
+ * @test
+ */
+ public function setWebForStringSetsWeb()
+ {
+ $this->subject->setWeb('Conceived at T3CON10');
+
+ self::assertAttributeEquals(
+ 'Conceived at T3CON10',
+ 'web',
+ $this->subject
+ );
+ }
+
+ /**
+ * @test
+ */
+ public function getEmailReturnsInitialValueForString()
+ {
+ self::assertSame(
+ '',
+ $this->subject->getEmail()
+ );
+ }
+
+ /**
+ * @test
+ */
+ public function setEmailForStringSetsEmail()
+ {
+ $this->subject->setEmail('Conceived at T3CON10');
+
+ self::assertAttributeEquals(
+ 'Conceived at T3CON10',
+ 'email',
+ $this->subject
+ );
+ }
+}
diff --git a/Tests/Unit/Domain/Model/RegionTest.php b/Tests/Unit/Domain/Model/RegionTest.php
new file mode 100644
index 0000000..6eeea3b
--- /dev/null
+++ b/Tests/Unit/Domain/Model/RegionTest.php
@@ -0,0 +1,51 @@
+
+ */
+class RegionTest extends \TYPO3\TestingFramework\Core\Unit\UnitTestCase
+{
+ /**
+ * @var \Wrm\Events\Domain\Model\Region
+ */
+ protected $subject = null;
+
+ protected function setUp()
+ {
+ parent::setUp();
+ $this->subject = new \Wrm\Events\Domain\Model\Region();
+ }
+
+ protected function tearDown()
+ {
+ parent::tearDown();
+ }
+
+ /**
+ * @test
+ */
+ public function getTitleReturnsInitialValueForString()
+ {
+ self::assertSame(
+ '',
+ $this->subject->getTitle()
+ );
+ }
+
+ /**
+ * @test
+ */
+ public function setTitleForStringSetsTitle()
+ {
+ $this->subject->setTitle('Conceived at T3CON10');
+
+ self::assertAttributeEquals(
+ 'Conceived at T3CON10',
+ 'title',
+ $this->subject
+ );
+ }
+}
diff --git a/composer.json b/composer.json
new file mode 100644
index 0000000..02b7e15
--- /dev/null
+++ b/composer.json
@@ -0,0 +1,28 @@
+{
+ "name": "wrm/events",
+ "type": "typo3-cms-extension",
+ "description": "Extension to manage Destination Data managed events",
+ "authors": [
+ {
+ "name": "Dirk Koritnik",
+ "role": "Developer"
+ }
+ ],
+ "require": {
+ "typo3/cms-core": "^9.5"
+ },
+ "autoload": {
+ "psr-4": {
+ "Wrm\\Events\\": "Classes"
+ }
+ },
+ "autoload-dev": {
+ "psr-4": {
+ "Wrm\\Events\\Tests\\": "Tests"
+ }
+ },
+ "replace": {
+ "events": "self.version",
+ "typo3-ter/events": "self.version"
+ }
+}
diff --git a/ext_emconf.php b/ext_emconf.php
new file mode 100644
index 0000000..604ace8
--- /dev/null
+++ b/ext_emconf.php
@@ -0,0 +1,31 @@
+ 'Events',
+ 'description' => 'Extension to manage events',
+ 'category' => 'plugin',
+ 'author' => 'Dirk Koritnik',
+ 'author_email' => 'koritnik@werkraum-media.de',
+ 'state' => 'alpha',
+ 'uploadfolder' => 1,
+ 'createDirs' => '',
+ 'clearCacheOnLoad' => 0,
+ 'version' => '1.0.1',
+ 'constraints' => [
+ 'depends' => [
+ 'typo3' => '9.5.0-9.5.99',
+ ],
+ 'conflicts' => [],
+ 'suggests' => [],
+ ],
+];
diff --git a/ext_localconf.php b/ext_localconf.php
new file mode 100644
index 0000000..672dd3b
--- /dev/null
+++ b/ext_localconf.php
@@ -0,0 +1,71 @@
+ 'search'
+ ],
+ [
+ 'Date' => 'search'
+ ]
+ );
+
+ \TYPO3\CMS\Extbase\Utility\ExtensionUtility::configurePlugin(
+ 'Wrm.Events',
+ 'DateList',
+ [
+ 'Date' => 'list'
+ ],
+ [
+ 'Date' => 'list'
+ ]
+ );
+
+ \TYPO3\CMS\Extbase\Utility\ExtensionUtility::configurePlugin(
+ 'Wrm.Events',
+ 'DateShow',
+ [
+ 'Date' => 'show'
+ ],
+ [
+ 'Date' => 'show'
+ ]
+ );
+
+ /*
+ $iconRegistry = \TYPO3\CMS\Core\Utility\GeneralUtility::makeInstance(\TYPO3\CMS\Core\Imaging\IconRegistry::class);
+
+ $iconRegistry->registerIcon(
+ 'events-plugin',
+ \TYPO3\CMS\Core\Imaging\IconProvider\SvgIconProvider::class,
+ ['source' => 'EXT:events/Resources/Public/Icons/user_plugin_events.svg']
+ );
+
+ // wizards
+ \TYPO3\CMS\Core\Utility\ExtensionManagementUtility::addPageTSConfig(
+ 'mod {
+ wizards.newContentElement.wizardItems.plugins {
+ elements {
+ events {
+ iconIdentifier = events-plugin
+ title = LLL:EXT:events/Resources/Private/Language/locallang_db.xlf:tx_events.name
+ description = LLL:EXT:events/Resources/Private/Language/locallang_db.xlf:tx_events.description
+ tt_content_defValues {
+ CType = list
+ list_type = events_pi1
+ }
+ }
+ }
+ show = *
+ }
+ }'
+ );
+ */
+ }
+);
diff --git a/ext_tables.php b/ext_tables.php
new file mode 100644
index 0000000..960f0f4
--- /dev/null
+++ b/ext_tables.php
@@ -0,0 +1,32 @@
+