diff --git a/Classes/Controller/BackendController.php b/Classes/Controller/BackendController.php
new file mode 100755
index 0000000..92481d1
--- /dev/null
+++ b/Classes/Controller/BackendController.php
@@ -0,0 +1,213 @@
+, websedit AG
+ *
+ ***/
+
+/**
+ * ServiceController
+ */
+class BackendController extends \TYPO3\CMS\Extbase\Mvc\Controller\ActionController
+{
+ /**
+ * serviceRepository
+ *
+ * @var \Websedit\WeCookieConsent\Domain\Repository\ServiceRepository
+ */
+ protected $serviceRepository = null;
+
+ /**
+ * Inject a service repository
+ *
+ * @param \Websedit\WeCookieConsent\Domain\Repository\ServiceRepository $serviceRepository
+ */
+ public function injectServiceRepository(\Websedit\WeCookieConsent\Domain\Repository\ServiceRepository $serviceRepository)
+ {
+ $this->serviceRepository = $serviceRepository;
+ }
+
+ /**
+ * Action initializer
+ *
+ * @return void
+ */
+ protected function initializeAction()
+ {
+ $pageId = (int)\TYPO3\CMS\Core\Utility\GeneralUtility::_GP('id');
+ $frameworkConfiguration = $this->configurationManager->getConfiguration(\TYPO3\CMS\Extbase\Configuration\ConfigurationManagerInterface::CONFIGURATION_TYPE_FRAMEWORK);
+ $persistenceConfiguration = array('persistence' => array('storagePid' => $pageId));
+ $this->configurationManager->setConfiguration(array_merge($frameworkConfiguration, $persistenceConfiguration));
+ }
+
+ /**
+ * Preview the config
+ *
+ * @return void
+ */
+ public function gtmWizardAction()
+ {
+ $services = $this->serviceRepository->findByProvider('google-tagmanager-service');
+
+ $blocks = ['tags' => 1, 'triggers' => 1, 'variables' => 1];
+
+ $this->view->assignMultiple([
+ 'services' => $services,
+ 'gtmArray' => $this->createGtmArray($services, $blocks)
+ ]);
+ }
+
+ /**
+ * Download the config as JSON File
+ *
+ * @param array $blocks
+ *
+ * @return void
+ */
+ public function jsonDownloadAction($blocks)
+ {
+ $this->response->setHeader('Content-type', 'application/json');
+ $this->response->setHeader('Content-Disposition', 'attachment; filename=import-this-to-gtm.json');
+
+ $services = $this->serviceRepository->findByProvider('google-tagmanager-service');
+ $this->view->assignMultiple([
+ 'gtmArray' => $this->createGtmArray($services, $blocks)
+ ]);
+ }
+
+ /**
+ * Process the JSON for the Google Tag Manager
+ *
+ * @param \TYPO3\CMS\Extbase\Persistence\Generic\QueryResult $services
+ * @param array $blocks
+ * @return array
+ */
+ private function createGtmArray($services, $blocks)
+ {
+ $gtmArray = [
+ "exportFormatVersion" => 2,
+ "containerVersion" => [
+ "tag" => [],
+ "trigger" => [],
+ "variable" => [],
+ "folder" => [
+ [
+ "accountId" => "0",
+ "containerId" => "0",
+ "folderId" => "0",
+ "name" => "we_cookie_consent"
+ ]
+ ]
+ ]
+ ];
+
+ foreach ($services as $service) {
+ //Build Tag
+ if ($blocks['tags']) {
+ $gtmArray['containerVersion']['tag'][] = [
+ "accountId" => "0",
+ "containerId" => "0",
+ "tagId" => $service->getUid(),
+ "name" => $service->getGtmTagTitle(),
+ "type" => "html",
+ "parameter" => [
+ [
+ "type" => "TEMPLATE",
+ "key" => "html",
+ "value" => ""
+ ]
+ ],
+ "firingTriggerId" => [
+ $service->getUid()
+ ],
+ "parentFolderId" => "0"
+ ];
+ }
+
+ //Build Trigger
+ if ($blocks['triggers']) {
+ $gtmArray['containerVersion']['trigger'][] = [
+ "accountId" => "0",
+ "containerId" => "0",
+ "triggerId" => $service->getUid(),
+ "name" => $service->getGtmTriggerTitle(),
+ "type" => "CUSTOM_EVENT",
+ "customEventFilter" => [
+ [
+ "type" => "EQUALS",
+ "parameter" => [
+ [
+ "type" => "TEMPLATE",
+ "key" => "arg0",
+ "value" => "{{_event}}"
+ ],
+ [
+ "type" => "TEMPLATE",
+ "key" => "arg1",
+ "value" => $service->getGtmTriggerName()
+ ]
+ ]
+ ]
+ ],
+ "filter" => [
+ [
+ "type" => "EQUALS",
+ "parameter" => [
+ [
+ "type" => "TEMPLATE",
+ "key" => "arg0",
+ "value" => "{{" . $service->getGtmVariableTitle() . "}}"
+ ],
+ [
+ "type" => "TEMPLATE",
+ "key" => "arg1",
+ "value" => "true"
+ ]
+ ]
+ ]
+ ],
+ "parentFolderId" => "0"
+ ];
+ }
+
+ //Build Variable
+ if ($blocks['variables']) {
+ $gtmArray['containerVersion']['variable'][] = [
+ "accountId" => "0",
+ "containerId" => "0",
+ "variableId" => $service->getUid(),
+ "name" => $service->getGtmVariableTitle(),
+ "type" => "v",
+ "parameter" => [
+ [
+ "type" => "INTEGER",
+ "key" => "dataLayerVersion",
+ "value" => "2"
+ ],
+ [
+ "type" => "BOOLEAN",
+ "key" => "setDefaultValue",
+ "value" => "false"
+ ],
+ [
+ "type" => "TEMPLATE",
+ "key" => "name",
+ "value" => $service->getGtmVariableName()
+ ]
+ ],
+ "parentFolderId" => "0"
+ ];
+ }
+ }
+
+ return $gtmArray;
+ }
+}
diff --git a/Classes/Controller/ConsentController.php b/Classes/Controller/ConsentController.php
new file mode 100755
index 0000000..817156a
--- /dev/null
+++ b/Classes/Controller/ConsentController.php
@@ -0,0 +1,206 @@
+, websedit AG
+ *
+ ***/
+
+/**
+ * ConsentController
+ */
+class ConsentController extends \TYPO3\CMS\Extbase\Mvc\Controller\ActionController
+{
+ /**
+ * serviceRepository
+ *
+ * @var \Websedit\WeCookieConsent\Domain\Repository\ServiceRepository
+ */
+ protected $serviceRepository = null;
+
+ /**
+ * Inject a service repository
+ *
+ * @param \Websedit\WeCookieConsent\Domain\Repository\ServiceRepository $serviceRepository
+ */
+ public function injectServiceRepository(\Websedit\WeCookieConsent\Domain\Repository\ServiceRepository $serviceRepository)
+ {
+ $this->serviceRepository = $serviceRepository;
+ }
+
+ /**
+ * Generate JSON data for the consent Modal
+ *
+ * @param Websedit\WeCookieConsent\Domain\Model\Service
+ * @return void
+ */
+ public function consentAction()
+ {
+ $services = $this->serviceRepository->findAll();
+
+ //These two lines are only required for TYPO3 7 backwards compatibility. in TYPO3 >=8 renderAssetsForRequest is used
+ $klaroConfig = $this->klaroConfigBuild($services);
+ $typo3Version = \TYPO3\CMS\Core\Utility\VersionNumberUtility::convertVersionNumberToInteger(TYPO3_version);
+
+ $this->view->assignMultiple([
+ 'services' => $services,
+ 'klaroConfig' => $klaroConfig,
+ 'typo3Version' => $typo3Version
+ ]);
+ }
+
+ /**
+ * Show used cookies at the data privacy page
+ *
+ * @param Websedit\WeCookieConsent\Domain\Model\Service
+ * @return void
+ */
+ public function listAction()
+ {
+ $servicesUids = explode(',', $this->settings['flexforms']['services']);
+
+ $services = [];
+ foreach ($servicesUids as $uid) {
+ //No custom findByUids function to keep the sorting
+ $services[] = $this->serviceRepository->findByUid($uid);
+ }
+
+ $this->view->assignMultiple([
+ 'services' => $services
+ ]);
+ }
+
+ /**
+ * @param \TYPO3\CMS\Extbase\Mvc\RequestInterface $request
+ */
+ protected function renderAssetsForRequest($request)
+ {
+ if (!$this->view instanceof \TYPO3Fluid\Fluid\View\TemplateView) {
+ return;
+ }
+
+ $services = $this->serviceRepository->findAll();
+ $klaroConfig = $this->klaroConfigBuild($services);
+
+ $pageRenderer = $this->objectManager->get(\TYPO3\CMS\Core\Page\PageRenderer::class);
+ $variables = [
+ 'request' => $request,
+ 'arguments' => $this->arguments,
+ 'services' => $services,
+ 'klaroConfig' => $klaroConfig
+ ];
+
+ $headerAssets = $this->view->renderSection('HeaderAssets', $variables, true);
+ $footerAssets = $this->view->renderSection('FooterAssets', $variables, true);
+
+ if (!empty(trim($headerAssets))) {
+ $pageRenderer->addHeaderData($headerAssets);
+ }
+ if (!empty(trim($footerAssets))) {
+ $pageRenderer->addFooterData($footerAssets);
+ }
+ }
+
+ /**
+ * Build the klaro config object used in frontend
+ *
+ * @param \TYPO3\CMS\Extbase\Persistence\Generic\QueryResult $services
+ * @return array
+ */
+ private function klaroConfigBuild(\TYPO3\CMS\Extbase\Persistence\Generic\QueryResult $services)
+ {
+ if (is_numeric($this->settings['klaro']['privacyPolicy'])) {
+ $privacyPage = $this->uriBuilder
+ ->reset()
+ ->setTargetPageUid((int) $this->settings['klaro']['privacyPolicy'])
+ ->setCreateAbsoluteUri(true)
+ ->build();
+ } else {
+ $privacyPage = $this->settings['klaro']['privacyPolicy'];
+ }
+
+ if (is_numeric($this->settings['klaro']['poweredBy'])) {
+ $poweredByPage = $this->uriBuilder
+ ->reset()
+ ->setTargetPageUid((int) $this->settings['klaro']['poweredBy'])
+ ->setCreateAbsoluteUri(true)
+ ->build();
+ } else {
+ $poweredByPage = $this->settings['klaro']['poweredBy'];
+ }
+
+ $klaroConfig = [
+ 'elementID' => $this->settings['klaro']['elementID'],
+ 'storageMethod' => $this->settings['klaro']['storageMethod'],
+ 'cookieName' => $this->settings['klaro']['cookieName'],
+ 'cookieExpiresAfterDays' => $this->settings['klaro']['cookieExpiresAfterDays'],
+ 'privacyPolicy' => $privacyPage,
+ 'default' => $this->settings['klaro']['default'] === '1',
+ 'mustConsent' => $this->settings['klaro']['mustConsent'] === '1',
+ 'hideDeclineAll' => $this->settings['klaro']['hideDeclineAll'] === '1',
+ 'hideLearnMore' => $this->settings['klaro']['hideLearnMore'] === '1',
+ 'lang' => $this->settings['klaro']['lang'],
+ 'poweredBy' => $poweredByPage,
+ 'translations' => [
+ 'en' => [
+ 'consentModal' => [
+ 'title' => LocalizationUtility::translate('klaro.consentModal.title', 'we_cookie_consent'),
+ 'description' => LocalizationUtility::translate('klaro.consentModal.description', 'we_cookie_consent'),
+ 'privacyPolicy' => [
+ 'text' => LocalizationUtility::translate('klaro.consentModal.privacyPolicy.text', 'we_cookie_consent'),
+ 'name' => LocalizationUtility::translate('klaro.consentModal.privacyPolicy.name', 'we_cookie_consent')
+ ]
+ ],
+ 'consentNotice' => [
+ 'description' => LocalizationUtility::translate('klaro.consentNotice.description', 'we_cookie_consent'),
+ 'changeDescription' => LocalizationUtility::translate('klaro.consentNotice.changeDescription', 'we_cookie_consent'),
+ 'learnMore' => LocalizationUtility::translate('klaro.consentNotice.learnMore', 'we_cookie_consent')
+ ],
+ 'app' => [
+ 'disableAll' => [
+ 'title' => LocalizationUtility::translate('klaro.app.disableAll.title', 'we_cookie_consent'),
+ 'description' => LocalizationUtility::translate('klaro.app.disableAll.description', 'we_cookie_consent')
+ ],
+ 'optOut' => [
+ 'title' => LocalizationUtility::translate('klaro.app.optOut.title', 'we_cookie_consent'),
+ 'description' => LocalizationUtility::translate('klaro.app.optOut.description', 'we_cookie_consent')
+ ],
+ 'required' => [
+ 'title' => LocalizationUtility::translate('klaro.app.required.title', 'we_cookie_consent'),
+ 'description' => LocalizationUtility::translate('klaro.app.required.description', 'we_cookie_consent')
+ ],
+ 'purpose' => LocalizationUtility::translate('klaro.app.purpose', 'we_cookie_consent'),
+ 'purposes' => LocalizationUtility::translate('klaro.app.purposes', 'we_cookie_consent')
+ ],
+ 'purposes' => [
+ 'unknown' => LocalizationUtility::translate('klaro.purposes.unknown', 'we_cookie_consent')
+ ],
+ 'ok' => LocalizationUtility::translate('klaro.ok', 'we_cookie_consent'),
+ 'save' => LocalizationUtility::translate('klaro.save', 'we_cookie_consent'),
+ 'acceptSelected' => LocalizationUtility::translate('klaro.save', 'we_cookie_consent'),
+ 'decline' => LocalizationUtility::translate('klaro.decline', 'we_cookie_consent'),
+ 'close' => LocalizationUtility::translate('klaro.close', 'we_cookie_consent'),
+ 'poweredBy' => LocalizationUtility::translate('klaro.poweredBy', 'we_cookie_consent')
+ ]
+ ],
+ 'apps' => []
+ ];
+
+ foreach ($services as $service) {
+ foreach ($service->getCategories() as $category) {
+ $klaroConfig['translations']['en']['purposes'][strtolower($category->getTitle())] = $category->getTitle();
+ }
+ }
+
+ return $klaroConfig;
+ }
+}
diff --git a/Classes/Domain/Model/Cookie.php b/Classes/Domain/Model/Cookie.php
new file mode 100755
index 0000000..9855265
--- /dev/null
+++ b/Classes/Domain/Model/Cookie.php
@@ -0,0 +1,136 @@
+, websedit AG
+ *
+ ***/
+
+/**
+ * Cookie
+ */
+class Cookie extends \TYPO3\CMS\Extbase\DomainObject\AbstractEntity
+{
+ /**
+ * Name des Cookies
+ * String oder RegEx des Cookie Namens. Diese Cookies werden automatisch gelöscht,
+ * wenn der Besucher der Verwendung dieser App nicht zustimmt (z. B. /^_ga_.*$/
+ * oder custom_tracker_cookie)
+ *
+ * @var string
+ */
+ protected $title = '';
+
+ /**
+ * regex
+ *
+ * @var string
+ */
+ protected $regex = '';
+
+ /**
+ * Beschreibung
+ *
+ * @var string
+ */
+ protected $description = '';
+
+ /**
+ * maxAge
+ *
+ * @var string
+ */
+ protected $maxAge = '';
+
+ /**
+ * 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;
+ }
+
+ /**
+ * Returns the description
+ *
+ * @return string description
+ */
+ public function getDescription()
+ {
+ return $this->description;
+ }
+
+ /**
+ * Sets the description
+ *
+ * @param string $description
+ * @return void
+ */
+ public function setDescription($description)
+ {
+ $this->description = $description;
+ }
+
+ /**
+ * Returns the maxAge
+ *
+ * @return string maxAge
+ */
+ public function getMaxAge()
+ {
+ return $this->maxAge;
+ }
+
+ /**
+ * Sets the maxAge
+ *
+ * @param string $maxAge
+ * @return void
+ */
+ public function setMaxAge($maxAge)
+ {
+ $this->maxAge = $maxAge;
+ }
+
+ /**
+ * Returns the regex
+ *
+ * @return string $regex
+ */
+ public function getRegex()
+ {
+ return $this->regex;
+ }
+
+ /**
+ * Sets the regex
+ *
+ * @param string $regex
+ * @return void
+ */
+ public function setRegex($regex)
+ {
+ $this->regex = $regex;
+ }
+}
\ No newline at end of file
diff --git a/Classes/Domain/Model/Service.php b/Classes/Domain/Model/Service.php
new file mode 100755
index 0000000..644ab32
--- /dev/null
+++ b/Classes/Domain/Model/Service.php
@@ -0,0 +1,703 @@
+, websedit AG
+ *
+ ***/
+
+/**
+ * Service like Google Analytics, Facebook, Matomo, ...
+ */
+class Service extends \TYPO3\CMS\Extbase\DomainObject\AbstractEntity
+{
+ /**
+ * @var \TYPO3\CMS\Extbase\Persistence\ObjectStorage<\TYPO3\CMS\Extbase\Domain\Model\Category>
+ */
+ protected $categories = null;
+
+ /**
+ * Der Anbieter des Services
+ *
+ * @var string
+ */
+ protected $provider = '';
+
+ /**
+ * ID des ScriptTages
+ *
+ * @var string
+ */
+ protected $name = '';
+
+ /**
+ * Ein einfacher und kurzer Name (z. B. google-analytics)
+ *
+ * @var string
+ */
+ protected $title = '';
+
+ /**
+ * Beschreibung fürs Frontend
+ *
+ * @var string
+ */
+ protected $description = '';
+
+ /**
+ * Kategorie
+ *
+ * @var string
+ */
+ protected $purpose = '';
+
+ /**
+ * Zustand ohne Zustimmung
+ *
+ * @var bool
+ */
+ protected $state = false;
+
+ /**
+ * Ob diese App standardmässig aktiviert sein soll. Diese Option überschreibt die
+ * globale Einstellung.
+ *
+ * @var bool
+ */
+ protected $preselected = false;
+
+ /**
+ * Die Zustimmung für diese App kann vom Kunden nicht deaktiviert werden
+ *
+ * @var bool
+ */
+ protected $required = false;
+
+ /**
+ * Die Scripts dieser App werden beim ersten Seitenaufruf geladen. Der Kunde muss
+ * die Verwendung explizit verweigern.
+ *
+ * @var bool
+ */
+ protected $optOut = false;
+
+ /**
+ * Die Scripts dieser App nur einmal laden, auch wenn der Besucher die Zustimmung
+ * mehrfach de- und wieder aktiviert.
+ *
+ * @var bool
+ */
+ protected $onlyOnce = false;
+
+ /**
+ * JavaScript Snippet für unbekannte Dienste
+ *
+ * @var string
+ */
+ protected $snippet = '';
+
+ /**
+ * Diese JavaScript Funktion wird immer dann ausgeführt, wenn diese App vom Kunden
+ * zugelassen wird. function (consent, app) { // ... }
+ *
+ * @var string
+ */
+ protected $callback = '';
+
+ /**
+ * Die Domain unter der, der Service läuft.
+ *
+ * @var string
+ */
+ protected $domain = '';
+
+ /**
+ * Der API Key, falls zur Identifizierung notwendig.
+ *
+ * @var string
+ */
+ protected $apiKey = '';
+
+ /**
+ * gtmTagTitle
+ *
+ * @var string
+ */
+ protected $gtmTagTitle = '';
+
+ /**
+ * Google Tag Manager Trigger Name
+ *
+ * @var string
+ */
+ protected $gtmTriggerTitle = '';
+
+ /**
+ * gtmTriggerName
+ *
+ * @var string
+ */
+ protected $gtmTriggerName = '';
+
+ /**
+ * Google Tag Manager Variablenname
+ *
+ * @var string
+ */
+ protected $gtmVariableTitle = '';
+
+ /**
+ * gtmVariableName
+ *
+ * @var string
+ */
+ protected $gtmVariableName = '';
+
+ /**
+ * Cookies die von diesem Service eingesetzt werden
+ *
+ * @var \TYPO3\CMS\Extbase\Persistence\ObjectStorage<\Websedit\WeCookieConsent\Domain\Model\Cookie>
+ * @TYPO3\CMS\Extbase\Annotation\ORM\Cascade remove
+ * @TYPO3\CMS\Extbase\Annotation\ORM\Lazy
+ */
+ protected $cookies = null;
+
+ /**
+ * __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()
+ {
+ $this->cookies = new \TYPO3\CMS\Extbase\Persistence\ObjectStorage();
+ }
+
+ /**
+ * @return \TYPO3\CMS\Extbase\Persistence\ObjectStorage
+ */
+ public function getCategories()
+ {
+ return $this->categories;
+ }
+
+ /**
+ * @param \TYPO3\CMS\Extbase\Persistence\ObjectStorage $categories
+ */
+ public function setCategories(\TYPO3\CMS\Extbase\Persistence\ObjectStorage $categories)
+ {
+ $this->categories = $categories;
+ }
+
+ /**
+ * Returns the provider
+ *
+ * @return string provider
+ */
+ public function getProvider()
+ {
+ return $this->provider;
+ }
+
+ /**
+ * Sets the provider
+ *
+ * @param string $provider
+ * @return void
+ */
+ public function setProvider($provider)
+ {
+ $this->provider = $provider;
+ }
+
+ /**
+ * 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 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;
+ }
+
+ /**
+ * Returns the description
+ *
+ * @return string description
+ */
+ public function getDescription()
+ {
+ return $this->description;
+ }
+
+ /**
+ * Sets the description
+ *
+ * @param string $description
+ * @return void
+ */
+ public function setDescription($description)
+ {
+ $this->description = $description;
+ }
+
+ /**
+ * Returns the purpose
+ *
+ * @return string purpose
+ */
+ public function getPurpose()
+ {
+ return $this->purpose;
+ }
+
+ /**
+ * Sets the purpose
+ *
+ * @param string $purpose
+ * @return void
+ */
+ public function setPurpose($purpose)
+ {
+ $this->purpose = $purpose;
+ }
+
+ /**
+ * Returns the state
+ *
+ * @return bool state
+ */
+ public function getState()
+ {
+ return $this->state;
+ }
+
+ /**
+ * Sets the state
+ *
+ * @param bool $state
+ * @return void
+ */
+ public function setState($state)
+ {
+ $this->state = $state;
+ }
+
+ /**
+ * Returns the boolean state of state
+ *
+ * @return bool state
+ */
+ public function isState()
+ {
+ return $this->state;
+ }
+
+ /**
+ * Returns the preselected
+ *
+ * @return bool preselected
+ */
+ public function getPreselected()
+ {
+ return $this->preselected;
+ }
+
+ /**
+ * Sets the preselected
+ *
+ * @param bool $preselected
+ * @return void
+ */
+ public function setPreselected($preselected)
+ {
+ $this->preselected = $preselected;
+ }
+
+ /**
+ * Returns the boolean state of preselected
+ *
+ * @return bool preselected
+ */
+ public function isPreselected()
+ {
+ return $this->preselected;
+ }
+
+ /**
+ * Returns the required
+ *
+ * @return bool required
+ */
+ public function getRequired()
+ {
+ return $this->required;
+ }
+
+ /**
+ * Sets the required
+ *
+ * @param bool $required
+ * @return void
+ */
+ public function setRequired($required)
+ {
+ $this->required = $required;
+ }
+
+ /**
+ * Returns the boolean state of required
+ *
+ * @return bool required
+ */
+ public function isRequired()
+ {
+ return $this->required;
+ }
+
+ /**
+ * Returns the optOut
+ *
+ * @return bool optOut
+ */
+ public function getOptOut()
+ {
+ return $this->optOut;
+ }
+
+ /**
+ * Sets the optOut
+ *
+ * @param bool $optOut
+ * @return void
+ */
+ public function setOptOut($optOut)
+ {
+ $this->optOut = $optOut;
+ }
+
+ /**
+ * Returns the boolean state of optOut
+ *
+ * @return bool optOut
+ */
+ public function isOptOut()
+ {
+ return $this->optOut;
+ }
+
+ /**
+ * Returns the onlyOnce
+ *
+ * @return bool onlyOnce
+ */
+ public function getOnlyOnce()
+ {
+ return $this->onlyOnce;
+ }
+
+ /**
+ * Sets the onlyOnce
+ *
+ * @param bool $onlyOnce
+ * @return void
+ */
+ public function setOnlyOnce($onlyOnce)
+ {
+ $this->onlyOnce = $onlyOnce;
+ }
+
+ /**
+ * Returns the boolean state of onlyOnce
+ *
+ * @return bool onlyOnce
+ */
+ public function isOnlyOnce()
+ {
+ return $this->onlyOnce;
+ }
+
+ /**
+ * Returns the callback
+ *
+ * @return string callback
+ */
+ public function getCallback()
+ {
+ return $this->callback;
+ }
+
+ /**
+ * Sets the callback
+ *
+ * @param string $callback
+ * @return void
+ */
+ public function setCallback($callback)
+ {
+ $this->callback = $callback;
+ }
+
+ /**
+ * Returns the domain
+ *
+ * @return string domain
+ */
+ public function getDomain()
+ {
+ return $this->domain;
+ }
+
+ /**
+ * Sets the domain
+ *
+ * @param string $domain
+ * @return void
+ */
+ public function setDomain($domain)
+ {
+ $this->domain = $domain;
+ }
+
+ /**
+ * Returns the apiKey
+ *
+ * @return string apiKey
+ */
+ public function getApiKey()
+ {
+ return $this->apiKey;
+ }
+
+ /**
+ * Sets the apiKey
+ *
+ * @param string $apiKey
+ * @return void
+ */
+ public function setApiKey($apiKey)
+ {
+ $this->apiKey = $apiKey;
+ }
+
+ /**
+ * Returns the snippet
+ *
+ * @return string snippet
+ */
+ public function getSnippet()
+ {
+ return $this->snippet;
+ }
+
+ /**
+ * Sets the snippet
+ *
+ * @param string $snippet
+ * @return void
+ */
+ public function setSnippet($snippet)
+ {
+ $this->snippet = $snippet;
+ }
+
+ /**
+ * Returns the gtmVariableTitle
+ *
+ * @return string gtmVariableTitle
+ */
+ public function getGtmVariableTitle()
+ {
+ return $this->gtmVariableTitle;
+ }
+
+ /**
+ * Sets the gtmVariableTitle
+ *
+ * @param string $gtmVariableTitle
+ * @return void
+ */
+ public function setGtmVariableTitle($gtmVariableTitle)
+ {
+ $this->gtmVariableTitle = $gtmVariableTitle;
+ }
+
+ /**
+ * Returns the gtmTriggerTitle
+ *
+ * @return string gtmTriggerTitle
+ */
+ public function getGtmTriggerTitle()
+ {
+ return $this->gtmTriggerTitle;
+ }
+
+ /**
+ * Sets the gtmTriggerTitle
+ *
+ * @param string $gtmTriggerTitle
+ * @return void
+ */
+ public function setGtmTriggerTitle($gtmTriggerTitle)
+ {
+ $this->gtmTriggerTitle = $gtmTriggerTitle;
+ }
+
+ /**
+ * Adds a Cookie
+ *
+ * @param \Websedit\WeCookieConsent\Domain\Model\Cookie $cooky
+ * @return void
+ */
+ public function addCooky(\Websedit\WeCookieConsent\Domain\Model\Cookie $cooky)
+ {
+ $this->cookies->attach($cooky);
+ }
+
+ /**
+ * Removes a Cookie
+ *
+ * @param \Websedit\WeCookieConsent\Domain\Model\Cookie $cookyToRemove The Cookie to be removed
+ * @return void
+ */
+ public function removeCooky(\Websedit\WeCookieConsent\Domain\Model\Cookie $cookyToRemove)
+ {
+ $this->cookies->detach($cookyToRemove);
+ }
+
+ /**
+ * Returns the cookies
+ *
+ * @return \TYPO3\CMS\Extbase\Persistence\ObjectStorage<\Websedit\WeCookieConsent\Domain\Model\Cookie> cookies
+ */
+ public function getCookies()
+ {
+ return $this->cookies;
+ }
+
+ /**
+ * Sets the cookies
+ *
+ * @param \TYPO3\CMS\Extbase\Persistence\ObjectStorage<\Websedit\WeCookieConsent\Domain\Model\Cookie> $cookies
+ * @return void
+ */
+ public function setCookies(\TYPO3\CMS\Extbase\Persistence\ObjectStorage $cookies)
+ {
+ $this->cookies = $cookies;
+ }
+
+ /**
+ * Returns the gtmTagTitle
+ *
+ * @return string $gtmTagTitle
+ */
+ public function getGtmTagTitle()
+ {
+ return $this->gtmTagTitle;
+ }
+
+ /**
+ * Sets the gtmTagTitle
+ *
+ * @param string $gtmTagTitle
+ * @return void
+ */
+ public function setGtmTagTitle($gtmTagTitle)
+ {
+ $this->gtmTagTitle = $gtmTagTitle;
+ }
+
+ /**
+ * Returns the gtmTriggerName
+ *
+ * @return string $gtmTriggerName
+ */
+ public function getGtmTriggerName()
+ {
+ return $this->gtmTriggerName;
+ }
+
+ /**
+ * Sets the gtmTriggerName
+ *
+ * @param string $gtmTriggerName
+ * @return void
+ */
+ public function setGtmTriggerName($gtmTriggerName)
+ {
+ $this->gtmTriggerName = $gtmTriggerName;
+ }
+
+ /**
+ * Returns the gtmVariableName
+ *
+ * @return string $gtmVariableName
+ */
+ public function getGtmVariableName()
+ {
+ return $this->gtmVariableName;
+ }
+
+ /**
+ * Sets the gtmVariableName
+ *
+ * @param string $gtmVariableName
+ * @return void
+ */
+ public function setGtmVariableName($gtmVariableName)
+ {
+ $this->gtmVariableName = $gtmVariableName;
+ }
+}
diff --git a/Classes/Domain/Repository/ServiceRepository.php b/Classes/Domain/Repository/ServiceRepository.php
new file mode 100755
index 0000000..ccedc12
--- /dev/null
+++ b/Classes/Domain/Repository/ServiceRepository.php
@@ -0,0 +1,28 @@
+, websedit AG
+ *
+ ***/
+
+/**
+ * The repository for Services
+ */
+class ServiceRepository extends \TYPO3\CMS\Extbase\Persistence\Repository
+{
+ /**
+ * @var array
+ */
+ protected $defaultOrderings = [
+ 'sorting' => \TYPO3\CMS\Extbase\Persistence\QueryInterface::ORDER_ASCENDING
+ ];
+}
\ No newline at end of file
diff --git a/Classes/Hook/AfterSaveHook.php b/Classes/Hook/AfterSaveHook.php
new file mode 100755
index 0000000..50cae29
--- /dev/null
+++ b/Classes/Hook/AfterSaveHook.php
@@ -0,0 +1,38 @@
+registerArgument('value', 'mixed', 'The incoming data to convert, or null if VH children should be used');
+ $this->registerArgument('forceObject', 'bool', 'Outputs an JSON object rather than an array', false, false);
+ }
+
+ public function render() {
+ $value = $this->renderChildren();
+ $options = JSON_HEX_TAG;
+ if ($this->arguments['forceObject'] !== false) {
+ $options = $options | JSON_FORCE_OBJECT;
+ }
+ return json_encode($value, $options);
+ }
+}
\ No newline at end of file
diff --git a/Classes/ViewHelpers/ScriptTagViewHelper.php b/Classes/ViewHelpers/ScriptTagViewHelper.php
new file mode 100755
index 0000000..362eb2c
--- /dev/null
+++ b/Classes/ViewHelpers/ScriptTagViewHelper.php
@@ -0,0 +1,28 @@
+registerArgument('snippet', 'string', 'The snippets to make valide', true);
+ $this->registerArgument('name', 'string', 'The snippets name to active', true);
+ }
+
+ public function render() {
+ $snippet = $this->arguments['snippet'];
+ $name = $this->arguments['name'];
+
+ $snippet = str_replace('type="text/javascript"', '', $snippet);
+ $snippet = str_replace('src="', 'data-src="', $snippet);
+ $snippet = str_replace('
+