TCEMainHook.php 98 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306230723082309231023112312231323142315231623172318231923202321232223232324232523262327232823292330233123322333233423352336233723382339234023412342234323442345234623472348234923502351235223532354235523562357235823592360236123622363236423652366236723682369237023712372237323742375237623772378
  1. <?php
  2. namespace Meramo\mrm_be\Hooks\TCE;
  3. use DOMDocument;
  4. use \TYPO3\CMS\Core\Utility\GeneralUtility;
  5. use \TYPO3\CMS\Core\Database\ConnectionPool;
  6. use \TYPO3\CMS\Core\Database\Connection;
  7. use \TYPO3\CMS\Core\Service\FlexFormService;
  8. use \TYPO3\CMS\Core\Configuration\FlexForm\FlexFormTools;
  9. use TYPO3\CMS\Core\Database\Query\Restriction\DeletedRestriction;
  10. use TYPO3\CMS\Core\Database\Query\Restriction\HiddenRestriction;
  11. use TYPO3\CMS\Extbase\Utility\DebuggerUtility;
  12. use \Meramo\mrm_be\Mongoer as Mongoer;
  13. require_once GeneralUtility::getFileAbsFileName('typo3conf/ext/mrm_be/Resources/Private/PHP/phpqrcode/qrlib.php');
  14. class TCEMainHook
  15. {
  16. protected $imageSizes = array(
  17. 'mrm_be_cm_publication' => array(
  18. 'passthru' => array(
  19. 'small' => array('width' => 256),
  20. 'big' => array('width' => 512)
  21. )
  22. ),
  23. 'mrm_be_cm_homeheaderinfo' => array(
  24. 'i_1_1' => array(
  25. 'i_1_1' => array('width' => 140, 'height' => 140),
  26. ),
  27. 'i_16_9' => array(
  28. 'i_16_9' => array('width' => 140, 'height' => 79),
  29. ),
  30. 'default' => array(
  31. 'default' => array('width' => 140, 'height' => 94),
  32. )
  33. ),
  34. 'mrm_be_cm_explorerbox' => array(
  35. 'i_1_1' => array(
  36. 'img' => array('width' => 500, 'height' => 500),
  37. )
  38. ),
  39. 'mrm_be_cm_statementbox' => array(
  40. 'i_1_1' => array(
  41. 'img' => array('width' => 160, 'height' => 160),
  42. )
  43. ),
  44. 'mrm_be_cm_checklist-radiorange' => array(
  45. 'i_1_1' => array(
  46. 'img' => array('width' => 160, 'height' => 160),
  47. )
  48. ),
  49. 'mrm_be_cm_tileoverview' => array(
  50. 'default' => array(
  51. 'default_hero_lte600' => array('width' => 560, 'height' => 373),
  52. )
  53. ),
  54. 'mrm_be_cm_heroimage' => array(
  55. 'default' => array(
  56. 'lte600' => array('width' => 560, 'height' => 373),
  57. 'gt600' => array('width' => 408, 'height' => 272)
  58. ),
  59. ),
  60. 'mrm_be_cm_imageplus' => array(
  61. 'default' => array(
  62. 'ratio32' => array('width' => 439, 'height' => 293)
  63. ),
  64. 'i_16_9' => array(
  65. 'ratio169' => array('width' => 727, 'height' => 409)
  66. ),
  67. 'i_21_9' => array(
  68. 'ratio219' => array('width' => 984, 'height' => 422)
  69. )
  70. ),
  71. 'mrm_be_cm_contentimage' => array(
  72. 'i_1_1' => array(
  73. 'content_image' => array('width' => 160, 'height' => 160),
  74. 'content_image_maximized_lte600' => array('width' => 560, 'height' => 560),
  75. 'content_image_maximized_gt600' => array('width' => 460, 'height' => 460),
  76. ),
  77. ),
  78. 'mrm_be_cm_rawimage' => array('passthru' => true),
  79. 'mrm_be_cm_animation' => array('passthru' => true),
  80. 'mrm_be_cm_picturechoice' => array(
  81. 'i_1_1' => array(
  82. 'pic' => array('width' => 300, 'height' => 300)
  83. )
  84. ),
  85. 'overview_image' => array(
  86. 'default' => array(
  87. 'home_topics_lte767' => array('width' => 725, 'height' => 484),
  88. 'home_topics_gt767' => array('width' => 313, 'height' => 209),
  89. 'sidebar_banner_lte840' => array('width' => 100, 'height' => 66),
  90. 'rubrik_overview' => array('width' => 318, 'height' => 212),
  91. 'default_hero_lte600' => array('width' => 560, 'height' => 373),
  92. 'default_hero_gt600' => array('width' => 408, 'height' => 272, 'allowed_doktypes' => ['102']),
  93. ),
  94. 'i_1_1' => array(
  95. 'home_rubrik' => array('width' => 95, 'height' => 95),
  96. 'archive_block' => array('width' => 160, 'height' => 160),
  97. 'square_big' => array('width' => 520, 'height' => 520),
  98. ),
  99. 'i_16_9' => array(
  100. 'og' => array('width' => 1200, 'height' => 675),
  101. 'sidebar_banner_gt840' => array('width' => 282, 'height' => 159),
  102. ),
  103. 'i_21_9' => array(
  104. 'flat_tile' => array('width' => 400, 'height' => 171),
  105. 'flat_big' => array('width' => 700, 'height' => 300),
  106. ),
  107. )
  108. );
  109. private $imageService;
  110. private $resourceFactory;
  111. private $fileRepository;
  112. private $environmentService;
  113. private $queryBuilder;
  114. private $pageQueryBuilder;
  115. private $pageRepository;
  116. private $linkService;
  117. private $connection;
  118. function __construct()
  119. {
  120. $this->environmentService = GeneralUtility::makeInstance("TYPO3\CMS\Extbase\Service\EnvironmentService");
  121. $this->resourceFactory = GeneralUtility::makeInstance('TYPO3\CMS\Core\Resource\ResourceFactory');
  122. $this->imageService = GeneralUtility::makeInstance("TYPO3\CMS\Extbase\Service\ImageService");
  123. $this->fileRepository = GeneralUtility::makeInstance('TYPO3\CMS\Core\Resource\FileRepository');
  124. $this->pageRepository = GeneralUtility::makeInstance('TYPO3\CMS\Frontend\Page\PageRepository');
  125. $this->linkService = GeneralUtility::makeInstance('TYPO3\CMS\Core\LinkHandling\LinkService');
  126. $connection = GeneralUtility::makeInstance(ConnectionPool::class);
  127. $this->connection = $connection;
  128. $this->queryBuilder = $connection->getQueryBuilderForTable('tt_content');
  129. $this->queryBuilder->getRestrictions()->removeAll()
  130. ->add(GeneralUtility::makeInstance(DeletedRestriction::class))
  131. ->add(GeneralUtility::makeInstance(HiddenRestriction::class));
  132. $this->pageQueryBuilder = $connection->getQueryBuilderForTable('pages');
  133. $this->pageQueryBuilder->getRestrictions()->removeAll();
  134. }
  135. public function processDatamap_beforeStart($pObj)
  136. {
  137. if (!isset($pObj->datamap['pages'])) return;
  138. foreach ($pObj->datamap['pages'] as $pid => &$_d) {
  139. if (!$pid || $pid < 0) continue;
  140. $starttime = $_d["starttime"];
  141. if ($starttime != 0)
  142. $_d["starttime"] = $this->startOfDay($starttime, null, true, true);
  143. $endtime = $_d["endtime"];
  144. if ($endtime != 0)
  145. $_d["endtime"] = $this->endOfDay($endtime, null, true, true);
  146. switch ($_d["red_status"]) {
  147. case "-1": //neu angelegt
  148. case "1": //in Bearbeitung
  149. case "2": //vorbereitet
  150. case "3": //geprüft
  151. case "21": //gesperrt
  152. case "22": //archiviert
  153. $_d["hidden"] = 1;
  154. break;
  155. case "11": //frei
  156. case "12": //online
  157. $_d["hidden"] = 0;
  158. break;
  159. default:
  160. break;
  161. }
  162. }
  163. }
  164. public function processCmdmap_afterFinish(\TYPO3\CMS\Core\DataHandling\DataHandler &$pObj)
  165. {
  166. if (!isset($pObj->datamap['pages'])) return;
  167. foreach ($pObj->datamap['pages'] as $pid => $_d) {
  168. if (!$pid || $pid < 0) continue;
  169. $this->log('processing PID: ' . $pid);
  170. $pageStatement = $this->pageQueryBuilder
  171. ->select('*')
  172. ->from('pages')
  173. ->setMaxResults(1)
  174. ->where(
  175. $this->pageQueryBuilder->expr()->eq('uid', $this->pageQueryBuilder->createNamedParameter($pid))
  176. )
  177. ->execute();
  178. $post = $pageStatement->fetchAll();
  179. $post = $post[0];
  180. if (!$post) continue;
  181. if ($post['doktype'] == 254) {
  182. $this->processFolderContent($post);
  183. continue;
  184. }
  185. if ($post['hidden'] == 1 || $post['deleted'] == 1) {
  186. Mongoer::sendRequest("pages", "delete", array("pageuid" => $pid));
  187. Mongoer::sendRequest("abialtcache", "delete", array("pageuid" => $pid));
  188. Mongoer::sendRequest("search", "delete", array("pageuid" => $pid));
  189. Mongoer::sendRequest("security", "delete", array("pageuid" => $pid));
  190. // DELETE existing page PDF
  191. $this->deletePagePDFIfExists($post['slug']);
  192. //continue;
  193. }
  194. $rootlineutil = GeneralUtility::makeInstance('TYPO3\CMS\Core\Utility\RootlineUtility', $pid);
  195. $rootline = array_reverse($rootlineutil->get($pid));
  196. $processedImages = array();
  197. $slugData = $this->constructSlug($pid);
  198. if (!$slugData) {
  199. $this->log($pid . " slugData empty");
  200. continue;
  201. }
  202. $qrfilename = '/var/www/html/public/typo3temp/' . mt_rand(0, 0xffffff) . '_' . mt_rand(0, 0xffffff) . '.svg';
  203. \QRcode::svg("https://abi.de" . $slugData, $qrfilename);
  204. $qrsvg = file_get_contents($qrfilename);
  205. unlink($qrfilename);
  206. $statement = $this->queryBuilder
  207. ->select('*')
  208. ->from('tt_content')
  209. ->where(
  210. $this->queryBuilder->expr()->eq('pid', $this->queryBuilder->createNamedParameter($pid))
  211. )
  212. ->execute();
  213. $fetchedTTContent = array();
  214. $pageType = "article";
  215. //$this->log($post["doktype"]);
  216. if ($post["doktype"] == 100) $pageType = "event-page";
  217. if ($post["doktype"] == 101) $pageType = "blog-page";
  218. if ($post["doktype"] == 102) $pageType = "blogger-page";
  219. if ($post["doktype"] == 103) $pageType = "archive";
  220. if ($post["doktype"] == 104) $pageType = "video-page";
  221. if ($post['is_siteroot'] == 1) $pageType = "home";
  222. // $overview_image = null;
  223. while ($row = $statement->fetch()) {
  224. $fetchedTTContent[] = $row;
  225. $row["doktype"] = $post["doktype"];
  226. }
  227. /* look for overview_image start */
  228. if ($pageType == "blogger-page" || $pageType == "video-page") {
  229. $overview_image = $this->processImagesTTContent($post, 'overview_image', 'pages', 'overview_image');
  230. $overview_image = $overview_image[0] ? $overview_image[0] : null;
  231. }
  232. if (!$overview_image) {
  233. $x = $this->findFirstAppearingElementByType("mrm_be_cm_postimage", $fetchedTTContent, "CType");
  234. if ($x) {
  235. $overview_image = $this->processImagesTTContent($x, 'overview_image');
  236. $overview_image = $overview_image[0] ? $overview_image[0] : null;
  237. }
  238. }
  239. if (!$overview_image) {
  240. foreach ($fetchedTTContent as $row) {
  241. if (!$overview_image && ($row['CType'] == "mrm_be_cm_heroimage" || $row['CType'] == "mrm_be_cm_contentimage" || $row['CType'] == "mrm_be_cm_rawimage")) {
  242. $overview_image = $this->processImagesTTContent($row, 'overview_image');
  243. $overview_image = $overview_image[0] ? $overview_image[0] : null;
  244. }
  245. }
  246. }
  247. /* look for overview_image end */
  248. if ($pageType != "home") {
  249. $initialContent = $this->createContentElement($pageType, array(), (object) array(), array());
  250. $initialH1Attribs = array();
  251. if ($post["roof"] && $post["roof"] != '') $initialH1Attribs["roof"] = $post["roof"];
  252. if ($post["title"] && $post["title"] != '') $initialH1Attribs["text"] = $post["title"];
  253. if (sizeof($initialH1Attribs) > 0) $initialContent["subElements"][] = $this->createContentElement("h1", array(), $initialH1Attribs);
  254. }
  255. $processedData = array(
  256. 'pageuid' => $pid,
  257. 'documentLanguage' => $post['documentlanguage'],
  258. 'url' => $slugData,
  259. 'shareableUrl' => "https://abi.de" . $slugData,
  260. 'title' => ($post['roof'] != '' ? $post['roof'] . ": " : "") . $post['title'],
  261. 'activeMenuPage' => $post['targetgroup'],
  262. 'overviewImage' => $overview_image,
  263. 'teasers' => array(
  264. 'teaserHome' => $post['teaserHome'],
  265. 'abstract' => $this->removeLinebreaks($post['abstract']),
  266. 'teaserOverview' => $post['teaserOverview'],
  267. 'title' => $post['title'],
  268. 'roof' => $post['roof'],
  269. 'intro' => ($pageType == 'blogger-page') ? $post['overview'] : $post['intro']
  270. ),
  271. 'sharingActivated' => $post['sharing_activated'] == 1 ? true : false,
  272. 'linkableInHTMLSitemap' => $post['forHTMLSitemap'] == 1 ? true : false,
  273. 'linkableOnHome' => $post['forHome'] == 1 ? true : false,
  274. 'linkableOnCategoryOverview' => $post['forCategoryOverview'] == 1 ? true : false,
  275. 'moveToTopPositionOnCategoryOverview' => $post['forCategoryOverviewTopPosition'] == 1 ? true : false,
  276. 'pageType' => $pageType,
  277. 'pageData' => array(
  278. 'title' => ($post['roof'] != '' ? $post['roof'] . ": " : "") . $post['title'],
  279. 'metas' => array(
  280. "<meta name=\"keywords\" content=\"" . $post["keywords"] . "\">",
  281. "<meta name=\"dcterms.date\" content=\"" . date("Y-m-d", $post['tstamp'] > $post['starttime'] ? $post['tstamp'] : $post['starttime']) . "\">",
  282. "<meta name=\"robots\" content=\"" . ($post['no_index'] == 0 ? "index" : "noindex") . ", " . ($post['no_follow'] == 0 ? "follow" : "nofollow") . "\" />",
  283. "<meta property=\"og:title\" content=\"" . ($post['roof'] != '' ? $post['roof'] . ": " : "") . $post['title'] . "\">",
  284. ($overview_image ? "<meta property=\"og:image\" content=\"https://abi.de/cdn/" . $overview_image["sources"]["og"] . "\" >" : ""),
  285. ),
  286. 'breadcrumbs' => $this->constructBreadCrumb($rootline, $post, $pageType),
  287. 'content' => $initialContent,
  288. 'sidebar' => $this->createContentElement("sidebar", array(), (object) array(), array()),
  289. ),
  290. 'linkedPosts' => array(),
  291. 'injections' => array(),
  292. 'qr2page' => $qrsvg,
  293. 'status' => $this->constructStatus($post)
  294. );
  295. //before content
  296. switch ($pageType) {
  297. case "blog-page":
  298. $processedData["pageData"]["content"]["subElements"][] = $this->createContentElement("injection", array("type" => "blog-author-info"));
  299. $processedData["injections"][] = "blog-author-info";
  300. $processedData["pageData"]["sidebar"]["subElements"][] = $this->createContentElement("injection", array("type" => "blog-page-sidebar"));
  301. $processedData["injections"][] = "blog-page-sidebar";
  302. break;
  303. case "blogger-page":
  304. $processedData["pageData"]["content"]["subElements"][] = $this->createContentElement("injection", array("type" => "blogger-page-author-image"));
  305. $processedData["injections"][] = "blogger-page-author-image";
  306. $text = $post['overview'] ?? $post['abstract'];
  307. $processedData["pageData"]["content"]["subElements"][] = $this->createContentElement("typo3_paragraph", array(), array('text' => '<p>' . $this->exchangeLinkBreaksWithBr($text) . '</p>'), null);
  308. $processedData["pageData"]["content"]["subElements"][] = $this->createContentElement("injection", array("type" => "blogger-page-author-latest-blogs"));
  309. $processedData["injections"][] = "blogger-page-author-latest-blogs";
  310. $processedData["pageData"]["sidebar"]["subElements"][] = $this->createContentElement("injection", array("type" => "blogger-page-sidebar"));
  311. $processedData["injections"][] = "blogger-page-sidebar";
  312. break;
  313. case "video-page":
  314. $processedData["pageData"]["content"]["subElements"][] = $this->createContentElement("injection", array("type" => "video-date-category"));
  315. $processedData["injections"][] = "video-date-category";
  316. $processedData["pageData"]["content"]["subElements"][] = $this->createContentElement("injection", array("type" => "video-info"));
  317. $processedData["injections"][] = "video-info";
  318. break;
  319. }
  320. foreach ($fetchedTTContent as $row) {
  321. $this->processData($row, $processedData, $processedImages);
  322. }
  323. //after content
  324. $processedData['pageData']['metas'][] = $this->constructMetaDescription($post['abstract'], $processedData['pageData']['content']);
  325. $processedData['pageData']['metas'][] = $this->constructMetaDescription($post['abstract'], $processedData['pageData']['content'], true);
  326. if ($pageType == "blog-page") {
  327. $processedData['pageData']['metas'][] = $this->constructMetaDescriptionForBlogPage('', $processedData['pageData']['content']);
  328. $processedData['pageData']['metas'][] = $this->constructMetaDescriptionForBlogPage('', $processedData['pageData']['content'], true);
  329. }
  330. $processedData['pageData']['metas'] = array_filter($processedData['pageData']['metas'], function ($val) {
  331. return $val != "";
  332. });
  333. switch ($pageType) {
  334. case "archive":
  335. $hasSpecificOverviewInjection = false;
  336. foreach ($processedData["injections"] as $inj) {
  337. if (str_contains($inj, "-archive-")) {
  338. $hasSpecificOverviewInjection = true;
  339. break;
  340. }
  341. }
  342. if (!$hasSpecificOverviewInjection) {
  343. $processedData["pageData"]["content"]["subElements"][] = $this->createContentElement("injection", array("type" => "archive-of-direct-childurls"));
  344. $processedData["injections"][] = "archive-of-direct-childurls";
  345. }
  346. break;
  347. case "event-page":
  348. if ($post["event_link"] && $post["event_link"] != "") {
  349. $processedData["pageData"]["content"]["subElements"][] = $this->createContentElement("typo3_paragraph", array(), array('text' => '<p><a href="' . $post["event_link"] . '" target="_blank">Weitere Infos zu dieser Veranstaltung »</a></p>'));
  350. }
  351. break;
  352. }
  353. if (sizeof($processedData['pageData']['sidebar']['subElements']) == 0) {
  354. $processedData['pageData']['sidebar'] = null;
  355. }
  356. if (sizeof($processedData['linkedPosts']) == 0) $processedData['linkedPosts'] = null;
  357. else
  358. $processedData['linkedPosts'] = array_values(array_unique($processedData['linkedPosts']));
  359. if (sizeof($processedData['injections']) == 0) $processedData['injections'] = null;
  360. else
  361. $processedData['injections'] = array_unique($processedData['injections']);
  362. if ($post['hidden'] == 1) {
  363. //TODO: SET STATUS ..
  364. }
  365. $this->deletePagePDFIfExists($processedData['url']);
  366. Mongoer::sendRequest("pages", "save", $processedData);
  367. $this->generatePDFPath($processedData['pageuid'], $processedData['url']);
  368. Mongoer::sendRequest("abialtcache", "delete", array("pageuid" => $pid));
  369. $security_user_pass = $post["security_user_pass"];
  370. if (!$security_user_pass || $security_user_pass == '')
  371. Mongoer::sendRequest("security", "delete", array("pageuid" => $pid));
  372. else {
  373. $tmp = array();
  374. foreach (preg_split('/\n|\r\n?/', $security_user_pass) as $itm) {
  375. $itm = trim($itm);
  376. $itm = explode('|', $itm);
  377. $tmp[$itm[0]] = $itm[1];
  378. }
  379. $security_user_pass = $tmp;
  380. Mongoer::sendRequest("security", "save", array("pageuid" => $pid, "url" => $processedData["url"], "data" => $security_user_pass));
  381. }
  382. //if($post['doktype'] != 1) continue;
  383. if ($post['no_search'] == 0) {
  384. $dkzer = new \Meramo\mrm_be\DKZer();
  385. $searchwords = $dkzer->getSearchWords($post['dkz_code_nrs']);
  386. $freesearchwords = preg_split('/\n|\r|,\n?/', $post['free_searchwords']);
  387. foreach ($freesearchwords as $sw) {
  388. $searchwords[] = $this->convertStringToTechnicalName($sw);
  389. }
  390. $ignoredsearchwords = preg_split('/\n|\r|,\n?/', $post['ignored_searchwords']);
  391. foreach ($ignoredsearchwords as &$sw) {
  392. $sw = $this->convertStringToTechnicalName($sw);
  393. }
  394. $searchwords = array_values(array_diff($searchwords, $ignoredsearchwords));
  395. $searchabletext = $this->constructSearchableText($processedData, true);
  396. $searchabletext_full = $this->constructSearchableText($processedData, false);
  397. $arra = array("pageuid" => $pid, "searchwords" => $searchwords, "text" => $searchabletext, "fulltext" => $searchabletext_full, "lesson" => null);
  398. $lessons = array_values(explode(',', $post['lesson']));
  399. if (sizeof($lessons) == 1 && $lessons[0] == "") $lessons = [];
  400. if (sizeof($lessons) > 0) {
  401. foreach ($lessons as &$l) $l = (int) $l;
  402. $arra['lesson'] = $lessons;
  403. }
  404. Mongoer::sendRequest("search", "save", $arra);
  405. } else Mongoer::sendRequest("search", "delete", array("pageuid" => $pid));
  406. }
  407. }
  408. private function createPDFHash($url)
  409. {
  410. $page = md5($url);
  411. return $page[0] . $page[1] . '/' . $page[2] . $page[3] . '/' . $page . '.pdf';
  412. }
  413. private function deletePagePDFIfExists($url)
  414. {
  415. $partialpath = \TYPO3\CMS\Core\Core\Environment::getPublicPath() . '/pdf-storage/';
  416. $file = $this->createPDFHash($url);
  417. $filepath = $partialpath . $file;
  418. if (file_exists($filepath)) {
  419. unlink($filepath);
  420. return true;
  421. } else {
  422. return false;
  423. }
  424. }
  425. private function generatePDFPath($pageuid, $url)
  426. {
  427. $urlencoded = urlencode($url);
  428. // $this->log($url, true);
  429. $urlpart = "https://abi.de/pdfgen?u=";
  430. $pdfgenurl = $urlpart . $urlencoded;
  431. $data = [
  432. 'pageuid' => $pageuid,
  433. 'url' => $pdfgenurl,
  434. 'pdfhash' => $this->createPDFHash($url)
  435. ];
  436. Mongoer::sendRequest('pdfgenjobs', 'save', $data);
  437. }
  438. private function processFolderContent(&$post)
  439. {
  440. $statement = $this->queryBuilder
  441. ->select('*')
  442. ->from('tt_content')
  443. ->where(
  444. $this->queryBuilder->expr()->eq('pid', $this->queryBuilder->createNamedParameter($post["uid"]))
  445. )
  446. ->execute();
  447. $fetchedTTContent = array();
  448. while ($row = $statement->fetch()) {
  449. $fetchedTTContent[] = $row;
  450. }
  451. if ($post['backend_layout'] == 'pagets__19') {
  452. $themenderwoche = array();
  453. $ffs = GeneralUtility::makeInstance(FlexFormService::class);
  454. foreach ($fetchedTTContent as $row) {
  455. $flex = $ffs->convertFlexFormContentToArray($row['pi_flexform']);
  456. $themenderwoche[] = array(
  457. "key" => $flex['key'],
  458. "starttime" => $this->startOfDay($flex['starttime']),
  459. "endtime" => $this->endOfDay($flex['starttime'], '+6 days'),
  460. "monday" => (int) $this->parseUIDFromT3Url($flex['monday']),
  461. "tuesday" => (int) $this->parseUIDFromT3Url($flex['tuesday']),
  462. "wednesday" => (int) $this->parseUIDFromT3Url($flex['wednesday']),
  463. "thursday" => (int) $this->parseUIDFromT3Url($flex['thursday']),
  464. "friday" => (int) $this->parseUIDFromT3Url($flex['friday']),
  465. "saturday" => (int) $this->parseUIDFromT3Url($flex['saturday']),
  466. "sunday" => (int) $this->parseUIDFromT3Url($flex['sunday']),
  467. );
  468. }
  469. Mongoer::sendRequest("themaderwoche", "save", array("data" => $themenderwoche));
  470. }
  471. if ($post['backend_layout'] == 'pagets__20') {
  472. $menus = array();
  473. $ffs = GeneralUtility::makeInstance(FlexFormService::class);
  474. foreach ($fetchedTTContent as $row) {
  475. $flex = $ffs->convertFlexFormContentToArray($row['pi_flexform']);
  476. $items = array();
  477. foreach ((array) $flex["dynamicComponents"] as $link) {
  478. $linkedPostIds = array();
  479. $itm = $this->parseFlexFormLink($link["links"]["link"], null, $linkedPostIds);
  480. //$this->log($itm, false);
  481. unset($itm["href"]);
  482. $itm["pageuid"] = $linkedPostIds["linkedPosts"][0];
  483. $items[] = $itm;
  484. }
  485. $menus[] = array(
  486. 'headline' => $flex['headline'],
  487. 'menu_id' => $flex['mid'],
  488. 'items' => $items
  489. );
  490. }
  491. Mongoer::sendRequest("menues", "save", array("data" => $menus));
  492. }
  493. if ($post['backend_layout'] == 'pagets__21') {
  494. $topthemen = array();
  495. $ffs = GeneralUtility::makeInstance(FlexFormService::class);
  496. foreach ($fetchedTTContent as $row) {
  497. $flex = $ffs->convertFlexFormContentToArray($row['pi_flexform']);
  498. $topthemen[] = array(
  499. "key" => $flex['key'],
  500. "starttime" => $this->startOfDay($flex['starttime']),
  501. "endtime" => $this->endOfDay($flex['starttime'], '+13 days'),
  502. "section1" => (int) $this->parseUIDFromT3Url($flex['section1']),
  503. "section2" => (int) $this->parseUIDFromT3Url($flex['section2']),
  504. "section3" => (int) $this->parseUIDFromT3Url($flex['section3']),
  505. "section4" => (int) $this->parseUIDFromT3Url($flex['section4']),
  506. "section5" => (int) $this->parseUIDFromT3Url($flex['section5']),
  507. );
  508. }
  509. Mongoer::sendRequest("topthemen", "save", array("data" => $topthemen));
  510. }
  511. if ($post['backend_layout'] == 'pagets__23') {
  512. $maintenance = array();
  513. $ffs = GeneralUtility::makeInstance(FlexFormService::class);
  514. foreach ($fetchedTTContent as $row) {
  515. $flex = $ffs->convertFlexFormContentToArray($row['pi_flexform']);
  516. $maintenance[] = array(
  517. "starttime" => $flex['starttime'],
  518. "endtime" => $flex['endtime'],
  519. "infotext" => $flex['infotext']
  520. );
  521. }
  522. Mongoer::sendRequest("maintenance", "save", array("data" => $maintenance));
  523. }
  524. if ($post['backend_layout'] == 'pagets__27' || $post['backend_layout' == 'pagets__28']) {
  525. $chatbot = array();
  526. $ffs = GeneralUtility::makeInstance(FlexFormService::class);
  527. foreach ($fetchedTTContent as $row) {
  528. $isDirect = $row['CType'] == 'mrm_be_cm_chatbot-direct';
  529. $flex = $ffs->convertFlexFormContentToArray($row['pi_flexform']);
  530. $item = array();
  531. $item['terms'] = explode("\n", str_replace(',', '', $flex['settings']['terms']));
  532. $item['type'] = $isDirect ? 'direct' : $flex['settings']['type'];
  533. if ($isDirect) {
  534. $item['url'] = $this->replaceT3Link($flex['settings']['url'], null, $row, false);
  535. }
  536. if ($flex['settings']['type'] == 'reverse') {
  537. $item["category"] = (($flex['settings']['category'] == "Auswählen") ? '' : $flex['settings']['category']);
  538. }
  539. $chatbot[] = $item;
  540. }
  541. Mongoer::sendRequest("chatbot", "save", array("data" => $chatbot));
  542. }
  543. }
  544. private function removeLinebreaks($str)
  545. {
  546. return trim(preg_replace('/\s+/', ' ', $str));
  547. }
  548. private function exchangeLinkBreaksWithBr($str)
  549. {
  550. return trim(preg_replace('/\r\n/', '<br />', $str));
  551. }
  552. private function startOfDay($ts, $modify = null, $isAtomDate = false, $returnAtomDate = false)
  553. {
  554. $dt = null;
  555. if ($isAtomDate) {
  556. if (is_numeric($ts)) {
  557. $ts = $ts + 0;
  558. $dt = new \DateTime();
  559. $dt->setTimezone(new \DateTimeZone('UTC'));
  560. $dt->setTimestamp($ts);
  561. } else {
  562. $dt = new \DateTime($ts);
  563. $dt->setTimezone(new \DateTimeZone('UTC'));
  564. }
  565. } else {
  566. $dt = new \DateTime(null, new \DateTimeZone('Europe/Berlin'));
  567. $dt->setTimestamp($ts);
  568. }
  569. if ($modify) $dt->modify($modify);
  570. $bodStr = $dt->format('Y-m-d 00:00:00');
  571. $bodObj = \DateTime::createFromFormat('Y-m-d H:i:s', $bodStr, $returnAtomDate ? new \DateTimeZone('UTC') : new \DateTimeZone('Europe/Berlin'));
  572. if ($returnAtomDate) return $bodObj->format(\DateTimeInterface::ATOM);
  573. return (int) $bodObj->getTimestamp();
  574. }
  575. private function endOfDay($ts, $modify = null, $isAtomDate = false, $returnAtomDate = false)
  576. {
  577. $dt = null;
  578. if ($isAtomDate) {
  579. if (is_numeric($ts)) {
  580. $ts = $ts + 0;
  581. $dt = new \DateTime();
  582. $dt->setTimezone(new \DateTimeZone('UTC'));
  583. $dt->setTimestamp($ts);
  584. } else {
  585. $dt = new \DateTime($ts);
  586. $dt->setTimezone(new \DateTimeZone('UTC'));
  587. }
  588. } else {
  589. $dt = new \DateTime(null, new \DateTimeZone('Europe/Berlin'));
  590. $dt->setTimestamp($ts);
  591. }
  592. if ($modify) $dt->modify($modify);
  593. $eodStr = $dt->format('Y-m-d 23:59:59');
  594. $eodObj = \DateTime::createFromFormat('Y-m-d H:i:s', $eodStr, $returnAtomDate ? new \DateTimeZone('UTC') : new \DateTimeZone('Europe/Berlin'));
  595. if ($returnAtomDate) return $eodObj->format(\DateTimeInterface::ATOM);
  596. return (int) $eodObj->getTimestamp();
  597. }
  598. function array_search_by_key_recursive($needle, array $haystack, &$return)
  599. {
  600. foreach ($haystack as $k => $v) {
  601. if (is_array($v)) {
  602. $this->array_search_by_key_recursive($needle, $v, $return);
  603. } else {
  604. if ($k === $needle) {
  605. $return[] = $v;
  606. }
  607. }
  608. }
  609. }
  610. private function findFirstAppearingElementByType($type, $subs, $typeKey = "type")
  611. {
  612. foreach ($subs as $v) {
  613. if ($v[$typeKey] == $type) return $v;
  614. }
  615. return null;
  616. }
  617. private function checkOrReduceDescriptionLength($desc, $len)
  618. {
  619. $newStr = '';
  620. $desc = $this->removeLinebreaks($desc);
  621. if (is_string($desc) && mb_strlen($desc) < $len) {
  622. $newStr = $desc;
  623. } else {
  624. $newStr = substr($desc, 0, $len);
  625. $pos = strrpos($newStr, ' ');
  626. $newStr = substr($desc, 0, $pos);
  627. }
  628. return $newStr;
  629. }
  630. private function constructMetaDescription($abstract = '', $content, $isOgTag = false)
  631. {
  632. $desc = '';
  633. if ($abstract != '') $desc = $abstract;
  634. if (!$desc || $desc == '') {
  635. $desc = $this->findFirstAppearingElementByType("introtext", $content["subElements"]);
  636. if ($desc)
  637. $desc = $desc["attributes"]["text"];
  638. }
  639. if (!$desc || $desc == '')
  640. return '';
  641. if ($isOgTag)
  642. return "<meta property=\"og:description\" content=\"" . $this->checkOrReduceDescriptionLength($desc, 320) . "\">";
  643. return "<meta name=\"description\" content=\"" . $this->checkOrReduceDescriptionLength($desc, 320) . "\">";
  644. }
  645. private function constructMetaDescriptionForBlogPage($text = '', $content, $isOgTag = false)
  646. {
  647. $desc = '';
  648. if ($text != '') $desc = $text;
  649. if (!$desc || $desc == '') {
  650. $desc = $this->findFirstAppearingElementByType('typo3_paragraph', $content["subElements"]);
  651. if ($desc)
  652. $desc = strip_tags($desc["attributes"]["text"]);
  653. }
  654. if (!$desc || $desc == '')
  655. return '';
  656. if ($isOgTag)
  657. return "<meta property=\"og:description\" content=\"" . $this->checkOrReduceDescriptionLength($desc, 165) . ' …' . "\">";
  658. return "<meta name=\"description\" content=\"" . $this->checkOrReduceDescriptionLength($desc, 165) . ' …' . "\">";
  659. }
  660. private function constructSearchableText($content, $minimum = true)
  661. {
  662. $cr = [];
  663. if (!$minimum) {
  664. $this->array_search_by_key_recursive("text", $content["pageData"]["content"], $cr);
  665. } else {
  666. //$roof = $this->findFirstAppearingElementByType("roof", $content["pageData"]["content"]["subElements"]);
  667. //if($roof) $cr[] = $roof["attributes"]["text"];
  668. $h1 = $this->findFirstAppearingElementByType("h1", $content["pageData"]["content"]["subElements"]);
  669. if ($h1) {
  670. $cr[] = $h1["attributes"]["roof"];
  671. $cr[] = $h1["attributes"]["text"];
  672. }
  673. $introtext = $this->findFirstAppearingElementByType("introtext", $content["pageData"]["content"]["subElements"]);
  674. if ($introtext) $cr[] = $introtext["attributes"]["text"];
  675. }
  676. $cr = preg_replace("/\r|\n/", " ", strip_tags(implode(" ", $cr)));
  677. return $cr;
  678. }
  679. private function constructStatus($post)
  680. {
  681. $publicationType = null;
  682. switch ($post["red_status"]) {
  683. case "-1": //neu angelegt
  684. case "1": //in Bearbeitung
  685. case "2": //vorbereitet
  686. case "3": //geprüft
  687. case "21": //gesperrt
  688. case "22": //archiviert
  689. $publicationType = "preview";
  690. break;
  691. case "11": //frei
  692. case "12": //online
  693. $publicationType = "live";
  694. break;
  695. default:
  696. break;
  697. }
  698. $status = array(
  699. 'isLiveFrom' => -1,
  700. 'isLiveTill' => -1,
  701. 'publicationType' => $publicationType,
  702. 'seo' => array(
  703. 'sitemap_changefreq' => $post['sitemap_changefreq'],
  704. 'sitemap_priority' => $post['sitemap_priority'],
  705. 'sitemap_lastmod' => time(),
  706. ),
  707. );
  708. if ($post['starttime'] != 0) {
  709. $status['isLiveFrom'] = $this->startOfDay($post['starttime']);
  710. }
  711. if ($post['endtime'] != 0) {
  712. $status['isLiveTill'] = $this->endOfDay($post['endtime']);
  713. }
  714. if ($post['doktype'] == '101') {
  715. $status['blog_author'] = $post['blog_author'];
  716. $status['blog_category'] = $post['blog_category'];
  717. }
  718. if ($post['doktype'] == '100') {
  719. $status['event_state'] = $post['event_state'];
  720. $status['event_category'] = $post['event_category'];
  721. }
  722. if ($post['doktype'] == '104') {
  723. $status['video_category'] = $post['event_category'];
  724. }
  725. //$this->log($status, false);
  726. return $status;
  727. }
  728. private function constructRedirects($pageData)
  729. {
  730. $redirects = array(
  731. '/?id=' . $pageData['uid']
  732. );
  733. //TODO: Add a single \r to match old Macs line breaks?
  734. foreach (preg_split('/\n|\r\n?/', $pageData['redirects']) as $redir) {
  735. $redir = trim($redir);
  736. if ($redir == '') continue;
  737. $redirects[] = $redir;
  738. }
  739. return $redirects;
  740. }
  741. private function convertStringToTechnicalName($string)
  742. {
  743. $string = $this->sanitizeString($string);
  744. $string = preg_replace('/-/', '', $string);
  745. return strtoupper($string);
  746. }
  747. private function sanitizeString($string)
  748. {
  749. $table = array(
  750. 'Š' => 'S', 'š' => 's', 'Đ' => 'Dj', 'đ' => 'dj', 'Ž' => 'Z', 'ž' => 'z', 'Č' => 'C', 'č' => 'c', 'Ć' => 'C', 'ć' => 'c',
  751. 'À' => 'A', 'Á' => 'A', 'Â' => 'A', 'Ã' => 'A', 'Ä' => 'AE', 'Å' => 'A', 'Æ' => 'A', 'Ç' => 'C', 'È' => 'E', 'É' => 'E',
  752. 'Ê' => 'E', 'Ë' => 'E', 'Ì' => 'I', 'Í' => 'I', 'Î' => 'I', 'Ï' => 'I', 'Ñ' => 'N', 'Ò' => 'O', 'Ó' => 'O', 'Ô' => 'O',
  753. 'Õ' => 'O', 'Ö' => 'OE', 'Ø' => 'O', 'Ù' => 'U', 'Ú' => 'U', 'Û' => 'U', 'Ü' => 'UE', 'Ý' => 'Y', 'Þ' => 'B', 'ß' => 'Ss',
  754. 'à' => 'a', 'á' => 'a', 'â' => 'a', 'ã' => 'a', 'ä' => 'ae', 'å' => 'a', 'æ' => 'a', 'ç' => 'c', 'è' => 'e', 'é' => 'e',
  755. 'ê' => 'e', 'ë' => 'e', 'ì' => 'i', 'í' => 'i', 'î' => 'i', 'ï' => 'i', 'ð' => 'o', 'ñ' => 'n', 'ò' => 'o', 'ó' => 'o',
  756. 'ô' => 'o', 'õ' => 'o', 'ö' => 'oe', 'ø' => 'o', 'ü' => 'ue', 'ù' => 'u', 'ú' => 'u', 'û' => 'u', 'ý' => 'y', 'ý' => 'y',
  757. 'þ' => 'b', 'ÿ' => 'y', 'Ŕ' => 'R', 'ŕ' => 'r', '/' => ''
  758. );
  759. $x = preg_replace(array('/\s{2,}/', '/[\t\n]/'), ' ', $string);
  760. $x = trim(strtr($x, $table));
  761. $x = preg_replace('/[^A-Za-z0-9]+/', ' ', $x);
  762. $x = trim($x);
  763. $x = preg_replace('/ {1,}/', '-', $x);
  764. $x = trim($x, "-");
  765. return $x;
  766. }
  767. private function constructSlug($pid)
  768. {
  769. $postStatement = $this->pageQueryBuilder
  770. ->select('slug')
  771. ->from('pages')
  772. ->setMaxResults(1)
  773. ->where(
  774. $this->pageQueryBuilder->expr()->eq('uid', $this->pageQueryBuilder->createNamedParameter($pid))
  775. )
  776. ->execute();
  777. $postSlug = $postStatement->fetchAll();
  778. $postSlug = $postSlug[0];
  779. return $postSlug ? $postSlug["slug"] : null;
  780. }
  781. private function constructBreadCrumb($rootline, $page, $pageType)
  782. {
  783. $breadCrumb = $this->createContentElement('breadcrumbs');
  784. foreach ($rootline as $post) {
  785. if ($post['doktype'] == 254) continue;
  786. if ($post['is_siteroot'] == 1) continue;
  787. if ($page['uid'] == $post['uid'] && ($pageType == "blogger-page" || $pageType == "video-page"))
  788. $tit = $post['title'];
  789. else
  790. if ($post['use_roof_as_breadcrumb_text'] == 0)
  791. $tit = $post['title'];
  792. else
  793. $tit = $post['roof'] && $post['roof'] != '' ? $post['roof'] : $post['title'];
  794. $breadCrumb['subElements'][] = $this->createContentElement(
  795. 'breadcrumblink',
  796. array(
  797. 'title' => $tit,
  798. 'alt' => $tit,
  799. 'text' => $tit,
  800. 'href' => $this->constructSlug($post['uid'])
  801. )
  802. );
  803. }
  804. return $breadCrumb;
  805. }
  806. private function processData($dbReference, &$processedData, &$processedImages)
  807. {
  808. $isSidebar = $dbReference['colPos'] == 1;
  809. if ($isSidebar)
  810. $subs = &$processedData['pageData']['sidebar']['subElements'];
  811. else
  812. $subs = &$processedData['pageData']['content']['subElements'];
  813. $ffs = GeneralUtility::makeInstance(FlexFormService::class);
  814. $flex = $ffs->convertFlexFormContentToArray($dbReference['pi_flexform']);
  815. // print_r($flex);
  816. // die();
  817. switch ($dbReference['CType']) {
  818. case "mrm_be_cm_postimage":
  819. break;
  820. case "mrm_be_cm_voting":
  821. $s = $this->createContentElement(
  822. "voting",
  823. array(
  824. "labels" => array(
  825. "startbutton" => $flex["startbuttontext"],
  826. ),
  827. "resultscreen" => array(
  828. "headingTop" => $flex["resultheadingtop"],
  829. ),
  830. ),
  831. array(
  832. "items" => array(array(
  833. "text" => $flex["questiontext"],
  834. "type" => $flex["questiontype"] == "1" || $flex["questiontype"] == 1 ? "multi" : "single",
  835. "answers" => array_values(array_map(function ($x) {
  836. return array("text" => $x["settings"]["answer"]["text"], "value" => null);
  837. }, $flex["dynamicComponents"]))
  838. )),
  839. "validation" => array(
  840. "alreadyVoted" => $this->createContentElement("injection", array("type" => "voting-alreadyVoted")),
  841. "chartData" => $this->createContentElement("injection", array("type" => "voting-chartData|")),
  842. ),
  843. )
  844. );
  845. $cntr = 0;
  846. foreach ($s["attributes"]["items"][0]["answers"] as &$a) {
  847. $a["value"] = $cntr;
  848. $cntr++;
  849. }
  850. $s["attributes"]["validation"]["chartData"]["props"]["type"] .= $cntr;
  851. $processedData["injections"][] = "voting-alreadyVoted";
  852. $processedData["injections"][] = "voting-chartData|" . $cntr;
  853. $subs[] = $s;
  854. $processedData["status"]["hasVoting"] = true;
  855. break;
  856. case "mrm_be_cm_checklist-todo":
  857. $elements = $this->createContentElement(
  858. "checklist-todo",
  859. array(
  860. "headlines" => array(
  861. "main" => $flex["headline_main"],
  862. "done" => $flex["headline_done"],
  863. "not_done" => $flex["headline_not_done"],
  864. ),
  865. "controls" => array(
  866. "print" => $flex["enable_print"] == "1",
  867. "pdf" => $flex["enable_pdf"] == "1",
  868. ),
  869. "labels" => array(
  870. "submit" => $flex["label_submit"],
  871. "print" => $flex["label_print"],
  872. "pdf" => $flex["label_pdf"],
  873. ),
  874. "items" => (function ($flex, $dbReference) {
  875. $itms = array();
  876. $imgs = array();
  877. if ($flex["images"] != "0" && $flex["images"] != 0) {
  878. $imgs = $this->processImagesTTContent($dbReference, 'mrm_be_cm_contentimage', 'tt_content', 'image', 'uid', true, true);
  879. }
  880. foreach ($flex["items"] as $itm) {
  881. $i = $itm["item"];
  882. $a = array();
  883. if ($i["text"] != "") $a["text"] = $i["text"];
  884. if ($i["contains_image"] == "1" || $i["contains_image"] == 1) {
  885. $im = array_shift($imgs);
  886. if (isset($im)) $a["img"] = $im;
  887. }
  888. $itms[] = $a;
  889. }
  890. return $itms;
  891. })($flex, $dbReference),
  892. )
  893. );
  894. $subs[] = $elements;
  895. $processedData["status"]["hasChecklist"] = true;
  896. break;
  897. case "mrm_be_cm_checklist_todo_multi":
  898. $elements = $this->createContentElement(
  899. 'checklist-todo-multi',
  900. array(
  901. "texts" => array(
  902. "mainhead" => $flex['mainhead'],
  903. "description" => $flex['description'],
  904. ),
  905. "controls" => array(
  906. "print" => $flex["enable_print"] == "1",
  907. "pdf" => $flex["enable_pdf"] == "1",
  908. ),
  909. "labels" => array(
  910. "print" => $flex["label_print"],
  911. "pdf" => $flex["label_pdf"],
  912. ),
  913. "items" => (function ($flex) {
  914. $itms = [];
  915. $a = array();
  916. foreach ($flex['items'] as $itm) {
  917. if (is_array($itm)) {
  918. $a['head'] = $itm['item']['head'];
  919. $list = $itm['item']['list'];
  920. $doc = new \DOMDocument('1.0', 'utf-8');
  921. $doc->loadHTML('<?xml encoding="UTF-8">' . $list);
  922. $listitems = $doc->getElementsByTagName('li');
  923. $list = [];
  924. foreach ($listitems as $node) {
  925. foreach ($node->childNodes as $child) {
  926. $list[] = array('text' => $child->nodeValue);
  927. }
  928. $a['items'] = $list;
  929. }
  930. }
  931. $itms[] = $a;
  932. }
  933. return $itms;
  934. })($flex),
  935. ),
  936. );
  937. $subs[] = $elements;
  938. break;
  939. case "mrm_be_cm_checklist-input":
  940. $items = array();
  941. $dynContentCounter = 0;
  942. while (true) {
  943. $dynContentCounter++;
  944. if (!isset($flex["label" . $dynContentCounter])) break;
  945. if ($flex["label" . $dynContentCounter] === "") continue;
  946. $label = array(
  947. "label" => $flex["label" . $dynContentCounter]
  948. );
  949. $items[] = $label;
  950. }
  951. $elements = $this->createContentElement(
  952. "checklist-input",
  953. array(
  954. "headlines" => array(
  955. "main" => $flex["headline_main"],
  956. "results" => $flex["headline_result"],
  957. ),
  958. "intro" => $flex["intro"],
  959. "controls" => array(
  960. "print" => $flex["enable_print"] == "1",
  961. "pdf" => $flex["enable_pdf"] == "1",
  962. ),
  963. "labels" => array(
  964. "submit" => $flex["label_submit"],
  965. "print" => $flex["label_print"],
  966. "pdf" => $flex["label_pdf"],
  967. ),
  968. "items" => $items,
  969. )
  970. );
  971. $subs[] = $elements;
  972. $processedData["status"]["hasChecklist"] = true;
  973. break;
  974. case "mrm_be_cm_checklist-scale":
  975. $items = array();
  976. $dynContentCounter = 0;
  977. while (true) {
  978. $dynContentCounter++;
  979. if (!isset($flex["label" . $dynContentCounter])) break;
  980. if ($flex["label" . $dynContentCounter] === "") continue;
  981. $label = array(
  982. "label" => $flex["label" . $dynContentCounter]
  983. );
  984. $items[] = $label;
  985. }
  986. $elements = $this->createContentElement(
  987. "checklist-scale",
  988. array(
  989. "headlines" => array(
  990. "main" => $flex["headline_main"],
  991. "results" => $flex["headline_result"],
  992. ),
  993. "intro" => $flex["intro"],
  994. "maxPoints" => (int)$flex["maxpoints"],
  995. "controls" => array(
  996. "print" => $flex["enable_print"] == "1",
  997. "pdf" => $flex["enable_pdf"] == "1",
  998. ),
  999. "labels" => array(
  1000. "nextbutton" => $flex["label_nextbutton"],
  1001. "lastbutton" => $flex["label_lastbutton"],
  1002. "print" => $flex["label_print"],
  1003. "pdf" => $flex["label_pdf"],
  1004. ),
  1005. "items" => $items,
  1006. )
  1007. );
  1008. $subs[] = $elements;
  1009. $processedData["status"]["hasChecklist"] = true;
  1010. break;
  1011. case "mrm_be_cm_checklist-radiorange":
  1012. $items = array();
  1013. $dynContentCounter = 0;
  1014. while (true) {
  1015. $dynContentCounter++;
  1016. if (!isset($flex["pointsFrom" . $dynContentCounter])) break;
  1017. if ($flex["pointsFrom" . $dynContentCounter] === "") continue;
  1018. $item = array(
  1019. "pointsFrom" => (int)$flex["pointsFrom" . $dynContentCounter],
  1020. "pointsTo" => (int)$flex["pointsTo" . $dynContentCounter],
  1021. "validationText" => $flex["validationText" . $dynContentCounter]
  1022. );
  1023. if ($flex["image" . $dynContentCounter] == 1) {
  1024. $images = $this->processImagesTTContent($dbReference, 'mrm_be_cm_checklist-radiorange', 'tt_content', 'flex_image_' . $dynContentCounter, 'uid', false, true);
  1025. $images = $images[0];
  1026. $images["src"] = $images["sources"]["img"];
  1027. unset($images["sources"]);
  1028. $item["img"] = $images;
  1029. }
  1030. $items[] = $item;
  1031. }
  1032. $elements = $this->createContentElement(
  1033. "checklist-radiorange",
  1034. array(
  1035. "headlines" => array(
  1036. "main" => $flex["headline_main"],
  1037. ),
  1038. "intro" => $flex["intro"],
  1039. "validation" => array(
  1040. "maxPoints" => (int)$flex["maxpoints"],
  1041. "items" => $items,
  1042. )
  1043. )
  1044. );
  1045. $subs[] = $elements;
  1046. $processedData["status"]["hasChecklist"] = true;
  1047. break;
  1048. case "mrm_be_cm_checklist-yesmaybeno":
  1049. $items = array();
  1050. foreach ($flex["dynamicComponents"] as $component) {
  1051. foreach ($component as $key => $value) {
  1052. $item = array(
  1053. "heading" => $value["headline"],
  1054. "text" => $value["text"]
  1055. );
  1056. }
  1057. if ($item) {
  1058. $items[] = $item;
  1059. }
  1060. unset($value);
  1061. }
  1062. $choices = array();
  1063. $choice_yes = array(
  1064. "label" => $flex["choice_value_yes"],
  1065. "value" => "yes"
  1066. );
  1067. $choice_maybe = array(
  1068. "label" => $flex["choice_value_maybe"],
  1069. "value" => "maybe"
  1070. );
  1071. $choice_no = array(
  1072. "label" => $flex["choice_value_no"],
  1073. "value" => "no"
  1074. );
  1075. $choices[] = $choice_yes;
  1076. $choices[] = $choice_maybe;
  1077. $choices[] = $choice_no;
  1078. $elements = $this->createContentElement(
  1079. "checklist-yesmaybeno",
  1080. array(
  1081. "headlines" => array(
  1082. "main" => $flex["headline_main"],
  1083. "results" => $flex["headline_result"],
  1084. ),
  1085. "intro" => $flex["intro"],
  1086. "controls" => array(
  1087. "print" => $flex["enable_print"] == "1",
  1088. "pdf" => $flex["enable_pdf"] == "1",
  1089. ),
  1090. "labels" => array(
  1091. "nextbutton" => $flex["label_nextbutton"],
  1092. "lastbutton" => $flex["label_lastbutton"],
  1093. "print" => $flex["label_print"],
  1094. "pdf" => $flex["label_pdf"],
  1095. ),
  1096. "choices" => $choices,
  1097. "items" => $items,
  1098. )
  1099. );
  1100. $subs[] = $elements;
  1101. $processedData["status"]["hasChecklist"] = true;
  1102. break;
  1103. case "mrm_be_cm_picturechoice":
  1104. $s = $this->createContentElement(
  1105. "picturechoice",
  1106. array(
  1107. "labels" => array(
  1108. "startbutton" => $flex["startbuttontext"],
  1109. "nextbutton" => $flex["nextbuttontext"],
  1110. "lastbutton" => $flex["lastbuttontext"],
  1111. "question" => $flex["question"],
  1112. "repeatbutton" => $flex["repeatbuttontext"],
  1113. ),
  1114. "resultscreen" => array(
  1115. "headingTop" => $flex["resultheadingtop"],
  1116. "end" => $flex["thanks"]
  1117. ),
  1118. "isRestartAble" => $flex["isRestartAble"] == 1 || $flex["isRestartAble"] == "1",
  1119. ),
  1120. array(
  1121. "items" => (function ($flex, $dbReference) {
  1122. $ret = array();
  1123. for ($i = 1; $i <= 3; $i++) {
  1124. $item = array();
  1125. for ($j = 1; $j <= 5; $j++) {
  1126. if ($flex["image" . $i . "_" . $j] == "1") {
  1127. $img = $this->processImagesTTContent($dbReference, 'mrm_be_cm_picturechoice', 'tt_content', 'flex_image_' . $i . "_" . $j, 'uid', false, true);
  1128. $img = $img[0];
  1129. $item[] = array(
  1130. "image" => $img,
  1131. "points" => (int) $flex["pointsOfImage" . $i . "_" . $j]
  1132. );
  1133. }
  1134. }
  1135. if (sizeof($item) > 0)
  1136. $ret[] = $item;
  1137. }
  1138. return $ret;
  1139. })($flex, $dbReference),
  1140. "validation" => array(
  1141. "maxPoints" => (int)$flex["maxpoints"],
  1142. "alreadyReachedPoints" => $this->createContentElement("injection", array("type" => "picturechoice-alreadyReachedPoints")),
  1143. "items" => array_map(
  1144. function ($i) {
  1145. $i["validationText"] = $this->checkTextForInternalLinks($i["validationText"], $dbReference, $processedData);
  1146. $i["pointsFrom"] = (int)$i["pointsFrom"];
  1147. $i["pointsTo"] = (int)$i["pointsTo"];
  1148. return $i;
  1149. },
  1150. array_filter(array_values(array_map(function ($v) {
  1151. return $v['settings']['validation'];
  1152. }, $flex["validations"])), function ($x) {
  1153. return $x != null;
  1154. })
  1155. //TODO: Core: Error handler (BE): PHP Warning: array_filter() expects parameter 1 (or 2 in another error message) to be array, null given in /var/www/html/typo3conf/ext/mrm_be/Classes/Hooks/TCE/TCEMainHook.php line 830
  1156. ),
  1157. ),
  1158. )
  1159. );
  1160. $processedData["injections"][] = "picturechoice-alreadyReachedPoints";
  1161. $subs[] = $s;
  1162. $processedData["status"]["hasPicturechoice"] = true;
  1163. break;
  1164. case "mrm_be_cm_quiz":
  1165. $s = $this->createContentElement(
  1166. "quiz",
  1167. array(
  1168. "labels" => array(
  1169. "startbutton" => $flex["startbuttontext"],
  1170. "nextbutton" => $flex["nextbuttontext"],
  1171. "lastbutton" => $flex["lastbuttontext"],
  1172. "question" => $flex["question"],
  1173. "repeatbutton" => $flex["repeatbuttontext"],
  1174. ),
  1175. "resultscreen" => array(
  1176. "headingTop" => $flex["resultheadingtop"],
  1177. "headingSub" => $flex["resultheadingsub"],
  1178. "validation" => $flex["validationstr"],
  1179. "end" => $flex["thanks"]
  1180. ),
  1181. "isRestartAble" => $flex["isRestartAble"] == 1 || $flex["isRestartAble"] == "1",
  1182. ),
  1183. array(
  1184. "items" => array_values(array_map(function ($v) {
  1185. $questionType = null;
  1186. $quest = $v['settings']['question'];
  1187. if (!isset($quest)) {
  1188. $quest = $v['settings']['question_multi'];
  1189. $questionType = "multi";
  1190. }
  1191. if (isset($quest["additional_text"]) && $quest["additional_text"] != "") {
  1192. $quest["text"] = $quest["text"] . " (" . $quest["additional_text"] . ")";
  1193. unset($quest["additional_text"]);
  1194. }
  1195. if ($questionType) $quest["type"] = $questionType;
  1196. unset($quest["rightanswer"]);
  1197. $i = 0;
  1198. $quest["answers"] = array();
  1199. while (1) {
  1200. $i++;
  1201. if (!isset($quest["answertext" . $i])) break;
  1202. if ($quest["answertext" . $i] === "") continue;
  1203. $quest["answers"][] = array("text" => $quest["answertext" . $i], "points" => (int)$quest["answerpoints" . $i]);
  1204. unset($quest["answertext" . $i]);
  1205. unset($quest["answerpoints" . $i]);
  1206. }
  1207. /* NOTE: DEPRECATED BY SINGLE INPUTS
  1208. $quest["answers"] = array_map(function($x) {
  1209. $x = explode("|", $x);
  1210. $x = array("text" => $x[0], "points" => (int)$x[1]);
  1211. return $x;
  1212. }, explode("\n", $quest["answers"]));
  1213. */
  1214. return $quest;
  1215. }, $flex["dynamicComponents"])),
  1216. "validation" => array(
  1217. "maxPoints" => (int)$flex["maxpoints"],
  1218. "averagePoints" => $this->createContentElement("injection", array("type" => "quiz-averagePoints")),
  1219. "alreadyReachedPoints" => $this->createContentElement("injection", array("type" => "quiz-alreadyReachedPoints")),
  1220. "items" => array_map(
  1221. function ($i) {
  1222. $i["validationText"] = $this->checkTextForInternalLinks($i["validationText"], $dbReference, $processedData);
  1223. return $i;
  1224. },
  1225. array_filter(array_values(array_map(function ($v) {
  1226. return $v['settings']['validation'];
  1227. }, $flex["dynamicComponents2"])), function ($x) {
  1228. return $x != null;
  1229. })
  1230. ),
  1231. ),
  1232. )
  1233. );
  1234. $processedData["injections"][] = "quiz-averagePoints";
  1235. $processedData["injections"][] = "quiz-alreadyReachedPoints";
  1236. $subs[] = $s;
  1237. $processedData["status"]["hasQuiz"] = true;
  1238. break;
  1239. case "mrm_be_cm_animation":
  1240. $script = $flex["script"];
  1241. if ($flex["staticfiles"] != "0" && $flex["staticfiles"] != 0) {
  1242. $imgs = $this->processImagesTTContent($dbReference);
  1243. foreach ($imgs as $idx => $v) {
  1244. $script = implode("#cdnurl#/" . $v["sources"]["passthru"], explode("%ASSET_" . ($idx + 1) . "%", $script));
  1245. }
  1246. }
  1247. $subs[] = $this->createContentElement("animation", array("addJQuery" => $flex["addJQuery"] == 1 || $flex["addJQuery"] == "1"), array("script" => $script));
  1248. $processedData["status"]["hasAnimation"] = true;
  1249. break;
  1250. case "mrm_be_cm_injection":
  1251. $subs[] = $this->createContentElement("injection", array("type" => $flex["text"]));
  1252. $processedData["injections"][] = $flex["text"];
  1253. break;
  1254. case "mrm_be_cm_roof":
  1255. $subs[] = $this->createContentElement("roof", array(), array("text" => $flex["text"]));
  1256. break;
  1257. case "mrm_be_cm_h1":
  1258. $subs[] = $this->createContentElement("h1", array(), array("text" => $flex["text"]));
  1259. break;
  1260. case "mrm_be_cm_h2":
  1261. $subs[] = $this->createContentElement("h2", array(), array("text" => $flex["text"]));
  1262. break;
  1263. case "mrm_be_cm_h3":
  1264. $subs[] = $this->createContentElement("h3", array(), array("text" => $flex["text"]));
  1265. break;
  1266. case "mrm_be_cm_introtext":
  1267. $text = preg_replace("/\n/", "<br />", $flex["text"]);
  1268. $subs[] = $this->createContentElement("introtext", array(), array("text" => $text));
  1269. break;
  1270. case "mrm_be_cm_button":
  1271. $href = $this->parseFlexFormLink($flex["button"], $dbReference, $processedData);
  1272. $buttonType = ($flex['buttonType'] == "0") ? 'button-link' : 'button-scream';
  1273. $button = $this->createContentElement("button", array('buttonType' => $buttonType), array("text" => $flex["text"], "href" => $href["href"], "target" => $href["target"]));
  1274. $subs[] = $button;
  1275. break;
  1276. case "mrm_be_cm_html":
  1277. $subs[] = $this->createContentElement("html", array(), array("text" => $flex["html"]));
  1278. break;
  1279. case "mrm_be_cm_heroimage":
  1280. $props = $this->processImagesTTContent($dbReference)[0];
  1281. $props["type"] = "typo3_hero";
  1282. $subs[] = $this->createContentElement("image", $props);
  1283. break;
  1284. case "mrm_be_cm_contentimage":
  1285. $props = $this->processImagesTTContent($dbReference)[0];
  1286. $props["type"] = "typo3_content";
  1287. $subs[] = $this->createContentElement("image", $props);
  1288. break;
  1289. case "mrm_be_cm_publication":
  1290. $imgprops = $this->processImagesTTContent($dbReference, 'mrm_be_cm_publication')[0];
  1291. $imgprops["type"] = "typo3_publication";
  1292. $publication = $this->createContentElement(
  1293. "publication",
  1294. array(
  1295. "starttime" => $this->startOfDay($flex['starttime']),
  1296. "endtime" => $this->endOfDay($flex['endtime']),
  1297. "issuekey" => $flex['issuekey'],
  1298. ),
  1299. array(
  1300. "image" => $imgprops,
  1301. "number" => $flex["issuenumber"],
  1302. "title" => $flex["issuetitle"],
  1303. "headline" => $flex["issueheadline"],
  1304. "link" => $this->parseFlexFormLink($flex["htmllink"], $dbReference, $processedData),
  1305. "pdf" => $this->parseFlexFormLink($flex["pdflink"], $dbReference, $processedData),
  1306. )
  1307. );
  1308. $subs[] = $publication;
  1309. break;
  1310. case "mrm_be_cm_rawimage":
  1311. $props = $this->processImagesTTContent($dbReference)[0];
  1312. $props["type"] = "typo3_raw";
  1313. $subs[] = $this->createContentElement("image", $props);
  1314. break;
  1315. case "mrm_be_cm_movingimagesvideo":
  1316. $subs[] = $this->createContentElement(
  1317. "movingimagesvideo",
  1318. array(
  1319. "hasNoticeForCrossPromotion" => $flex["hasNoticeForCrossPromotion"] == 1,
  1320. "hasNoticeForAccessibility" => $flex["hasNoticeForAccessibility"] == 1
  1321. ),
  1322. array("vid" => $flex["vid"])
  1323. );
  1324. break;
  1325. case "mrm_be_cm_paragraph":
  1326. $elements = $this->checkText($flex["text"], $dbReference, $processedData, "typo3_paragraph");
  1327. $subs = array_merge($subs, $elements);
  1328. break;
  1329. case "mrm_be_cm_additionalinfobox":
  1330. case "mrm_be_cm_infobox":
  1331. case "mrm_be_cm_extra_infosbox":
  1332. $type = null;
  1333. $open = null;
  1334. $noAutoOpen = null;
  1335. if ($dbReference['CType'] == "mrm_be_cm_additionalinfobox") $type = "typo3_additionalinfobox";
  1336. elseif ($dbReference['CType'] == "mrm_be_cm_infobox") $type = "typo3_infobox";
  1337. else $type = "typo3_extrainfosbox";
  1338. if ($dbReference['CType'] == "mrm_be_cm_additionalinfobox" || $dbReference['CType'] == "mrm_me_cm_extra_infosbox") $open = true;
  1339. else $open = $flex["isInitialyOpen"] == "1";
  1340. if ($dbReference['CType'] == "mrm_be_cm_additionalinfobox" || $dbReference['CType'] == "mrm_be_cm_infobox") $headline = $flex["headline"];
  1341. elseif ($dbReference['CType'] == "mrm_be_cm_extra_infosbox") $headline = '';
  1342. $this->log('Headline: ' . $headline, true);
  1343. $sub = $this->createContentElement(
  1344. $type,
  1345. array("open" => $open, "noAutoOpen" => $flex["noAutoOpen"] == 1),
  1346. array("headline" => $flex["headline"])
  1347. );
  1348. if ($flex["image"] == "1") {
  1349. $props = $this->processImagesTTContent($dbReference, "mrm_be_cm_contentimage")[0];
  1350. $props["type"] = "typo3_content";
  1351. $sub["subElements"][] = $this->createContentElement("image", $props);
  1352. } else {
  1353. switch ($flex["icon"]) {
  1354. case "1":
  1355. $sub["attributes"]["icon"] = "stadtinfo_basics";
  1356. break;
  1357. case "2":
  1358. $sub["attributes"]["icon"] = "geschichte";
  1359. break;
  1360. case "3":
  1361. $sub["attributes"]["icon"] = "kultur_freizeit";
  1362. break;
  1363. case "4":
  1364. $sub["attributes"]["icon"] = "besonderheiten";
  1365. break;
  1366. case "5":
  1367. $sub["attributes"]["icon"] = "kosten_geld";
  1368. break;
  1369. case "6":
  1370. $sub["attributes"]["icon"] = "hochschulen";
  1371. break;
  1372. case "7":
  1373. $sub["attributes"]["icon"] = "studieren";
  1374. break;
  1375. }
  1376. }
  1377. if ($flex["dynamicComponents"] && sizeof($flex["dynamicComponents"]) > 0)
  1378. foreach ($flex["dynamicComponents"] as $comp) {
  1379. $stype = array_keys($comp['settings'])[0];
  1380. $elements = [];
  1381. switch ($stype) {
  1382. case "box":
  1383. $box = $this->createContentElement("boxwrapper");
  1384. $box["subElements"] = array_merge($box["subElements"], $this->checkText($comp['settings']['box']['boxheadline'], $dbReference, $processedData, "h3"));
  1385. $box["subElements"] = array_merge($box["subElements"], $this->checkText($comp['settings']['box']['boxtext'], $dbReference, $processedData, "typo3_paragraph"));
  1386. $elements = [$box];
  1387. break;
  1388. case "boxheadline":
  1389. $elements = $this->checkText($comp['settings'][$stype][$stype], $dbReference, $processedData, "h3");
  1390. //$this->log($elements, false);
  1391. break;
  1392. case "boxtext":
  1393. $elements = $this->checkText($comp['settings'][$stype][$stype], $dbReference, $processedData, "typo3_paragraph");
  1394. break;
  1395. case "html":
  1396. $elements = $this->checkText($comp['settings'][$stype][$stype], $dbReference, $processedData, "html");
  1397. break;
  1398. }
  1399. $sub["subElements"] = array_merge($sub["subElements"], $elements);
  1400. $this->log($sub["subElements"], false);
  1401. }
  1402. $subs[] = $sub;
  1403. break;
  1404. case "mrm_be_cm_foldout":
  1405. $sub = $this->createContentElement("typo3_foldout", array("open" => $flex["isInitialyOpen"] == "1", "noAutoOpen" => $flex["noAutoOpen"] == "1"), array("headline" => $flex["headline"]), array());
  1406. if ($flex["image"] == "1") {
  1407. $props = $this->processImagesTTContent($dbReference, "mrm_be_cm_contentimage")[0];
  1408. $props["type"] = "typo3_content";
  1409. $sub["subElements"][] = $this->createContentElement("image", $props);
  1410. } else {
  1411. switch ($flex["icon"]) {
  1412. case "1":
  1413. $sub["attributes"]["icon"] = "stadtinfo_basics";
  1414. break;
  1415. case "2":
  1416. $sub["attributes"]["icon"] = "geschichte";
  1417. break;
  1418. case "3":
  1419. $sub["attributes"]["icon"] = "kultur_freizeit";
  1420. break;
  1421. case "4":
  1422. $sub["attributes"]["icon"] = "besonderheiten";
  1423. break;
  1424. case "5":
  1425. $sub["attributes"]["icon"] = "kosten_geld";
  1426. break;
  1427. case "6":
  1428. $sub["attributes"]["icon"] = "hochschulen";
  1429. break;
  1430. case "7":
  1431. $sub["attributes"]["icon"] = "studieren";
  1432. break;
  1433. }
  1434. }
  1435. if ($flex["dynamicComponents"] && sizeof($flex["dynamicComponents"]) > 0)
  1436. foreach ($flex["dynamicComponents"] as $comp) {
  1437. $stype = array_keys($comp['settings'])[0];
  1438. $elements = $this->checkText($comp['settings'][$stype][$stype], $dbReference, $processedData, $stype == "paragraph" ? "typo3_paragraph" : ($stype == "headline" ? "h3" : $stype));
  1439. $sub["subElements"] = array_merge($sub["subElements"], $elements);
  1440. }
  1441. $subs[] = $sub;
  1442. break;
  1443. case "mrm_be_cm_newsletterabo":
  1444. $newsletterabo = $this->createContentElement("newsletterabo", array("cr_url" => $flex["cr_url"], "cr_url_BIZ" => $flex["cr_url_BIZ"]));
  1445. $subs[] = $newsletterabo;
  1446. break;
  1447. case "mrm_be_cm_linkage":
  1448. $subs[] = $this->createContentElement("sidebarheadline", array(), array("text" => $flex['headline']));
  1449. $banners = $this->createContentElement("sidebarbanners");
  1450. if ($flex['dynamicComponents'] && sizeof($flex['dynamicComponents']) > 0)
  1451. foreach ($flex['dynamicComponents'] as $banner) {
  1452. $banners["subElements"][] = $this->createContentElement("banner", $this->parseFlexFormLink($banner["settings"]["link"]["link"], $dbReference, $processedData));
  1453. }
  1454. $subs[] = $banners;
  1455. $subs[] = $this->createContentElement("injection", array("type" => "rubrik_content"));
  1456. $processedData["injections"][] = "rubrik_content";
  1457. $berufenet = $this->createContentElement("sidebarexternallinks", array("type" => "berufenet"), array("items" => []));
  1458. if ($flex['dynamicComponentsBerufeNet'] && sizeof($flex['dynamicComponentsBerufeNet']) != 0)
  1459. foreach ($flex['dynamicComponentsBerufeNet'] as $itm) {
  1460. $link = $this->parseFlexFormLink($itm["settings"]["link"]["link"], $dbReference, $processedData);
  1461. $link = '<a href="' . $link['href'] . '" target="' . $link['target'] . '" aria-label="Externer Link">' . $link['alt'] . '</a>';
  1462. $berufenet["attributes"]["items"][] = $link;
  1463. }
  1464. if (sizeof($berufenet["attributes"]["items"]) > 0) $subs[] = $berufenet;
  1465. $berufetv = $this->createContentElement("sidebarexternallinks", array("type" => "berufetv"), array("items" => []));
  1466. if ($flex['dynamicComponentsBerufeTV'] && sizeof($flex['dynamicComponentsBerufeTV']) != 0)
  1467. foreach ($flex['dynamicComponentsBerufeTV'] as $itm) {
  1468. $link = $this->parseFlexFormLink($itm["settings"]["link"]["link"], $dbReference, $processedData);
  1469. $link = '<a href="' . $link['href'] . '" target="' . $link['target'] . '" aria-label="Externer Link">' . $link['alt'] . '</a>';
  1470. $berufetv["attributes"]["items"][] = $link;
  1471. }
  1472. if (sizeof($berufetv["attributes"]["items"]) > 0) $subs[] = $berufetv;
  1473. $berufsausbildung = $this->createContentElement("sidebarexternallinks", array("type" => "berufsausbildung"), array("items" => []));
  1474. if ($flex['dynamicComponentsBerufsausbildung'] && sizeof($flex['dynamicComponentsBerufsausbildung']) != 0)
  1475. foreach ($flex['dynamicComponentsBerufsausbildung'] as $itm) {
  1476. $link = $this->parseFlexFormLink($itm["settings"]["link"]["link"], $dbReference, $processedData);
  1477. $link = '<a href="' . $link['href'] . '" target="' . $link['target'] . '" aria-label="Externer Link">' . $link['alt'] . '</a>';
  1478. $berufsausbildung["attributes"]["items"][] = $link;
  1479. }
  1480. if (sizeof($berufsausbildung["attributes"]["items"]) > 0) $subs[] = $berufsausbildung;
  1481. $ba_search = $this->createContentElement("sidebarexternallinks", array("type" => "ba_search"), array("items" => []));
  1482. if ($flex['dynamicComponentsBASearch'] && sizeof($flex['dynamicComponentsBASearch']) != 0)
  1483. foreach ($flex['dynamicComponentsBASearch'] as $itm) {
  1484. $link = $this->parseFlexFormLink($itm["settings"]["link"]["link"], $dbReference, $processedData);
  1485. $link = '<a href="' . $link['href'] . '" target="' . $link['target'] . '" aria-label="Externer Link">' . $link['alt'] . '</a>';
  1486. $ba_search["attributes"]["items"][] = $link;
  1487. }
  1488. if (sizeof($ba_search["attributes"]["items"]) > 0) $subs[] = $ba_search;
  1489. $studienwahl = $this->createContentElement("sidebarexternallinks", array("type" => "studienwahl"), array("items" => []));
  1490. if ($flex['dynamicComponentsStudienwahl'] && sizeof($flex['dynamicComponentsStudienwahl']) != 0)
  1491. foreach ($flex['dynamicComponentsStudienwahl'] as $itm) {
  1492. $link = $this->parseFlexFormLink($itm["settings"]["link"]["link"], $dbReference, $processedData);
  1493. $link = '<a href="' . $link['href'] . '" target="' . $link['target'] . '" aria-label="Externer Link">' . $link['alt'] . '</a>';
  1494. $studienwahl["attributes"]["items"][] = $link;
  1495. }
  1496. if (sizeof($studienwahl["attributes"]["items"]) > 0) $subs[] = $studienwahl;
  1497. if ($flex['enable_check_u']) {
  1498. $check_u = $this->createContentElement("extimgbutton", array("ariaLabel" => "Zur Check-U-Website", "href" => "https://www.arbeitsagentur.de/bildung/welche-ausbildung-welches-studium-passt", "target" => "_blank"), array("imgsrc" => "/public/media/ext-link_check_u.png"));
  1499. $subs[] = $check_u;
  1500. }
  1501. if ($flex['enable_studiencheck']) {
  1502. $studiencheck = $this->createContentElement("extimgbutton", array("ariaLabel" => "Zur Studiencheck-Website", "href" => "https://studiencheck.de/", "target" => "_blank"), array("imgsrc" => "/public/media/ext-link_studiencheck.png"));
  1503. $subs[] = $studiencheck;
  1504. }
  1505. break;
  1506. case "mrm_be_cm_homeheaderinfo":
  1507. $items = array();
  1508. for ($i = 1; $i <= 3; $i++) {
  1509. if ($flex["headline" . $i] != "" && $flex["text" . $i] != "") {
  1510. $item = array("heading" => $flex["headline" . $i], "text" => $flex["text" . $i]);
  1511. if ($flex["link" . $i] != "") {
  1512. $link = $this->parseFlexFormLink($flex["link" . $i], $dbReference, $processedData);
  1513. $item["href"] = $link["href"];
  1514. $item["linkTarget"] = $link["target"];
  1515. }
  1516. if ($flex["image" . $i] == "1") {
  1517. $imgs = $this->processImagesTTContent($dbReference, 'mrm_be_cm_homeheaderinfo', 'tt_content', 'flex_image_' . $i, 'uid', false);
  1518. $item["image"] = "#cdnurl#/" . $imgs[0]["sources"][$flex["imagesize" . $i]];
  1519. }
  1520. $items[] = $item;
  1521. }
  1522. }
  1523. $subs[] = $this->createContentElement("abimessages", array("data" => $items));
  1524. break;
  1525. case "mrm_be_cm_tileoverview":
  1526. $items = array();
  1527. for ($i = 1; $i <= 8; $i++) {
  1528. if ($flex["link" . $i] == "") continue;
  1529. $item = array();
  1530. $link = $this->parseFlexFormLink($flex["link" . $i], $dbReference, $processedData);
  1531. $item["href"] = $link["href"];
  1532. $item["linkTarget"] = $link["target"];
  1533. $item["text"] = $link["alt"];
  1534. if ($flex["image" . $i] == "1") {
  1535. $imgs = $this->processImagesTTContent($dbReference, 'mrm_be_cm_tileoverview', 'tt_content', 'flex_image_' . $i, 'uid', false);
  1536. $item["image"] = "#cdnurl#/" . $imgs[0]["sources"]["default_hero_lte600"];
  1537. }
  1538. $items[] = $item;
  1539. }
  1540. $subs[] = $this->createContentElement("tileoverview", array("items" => $items));
  1541. break;
  1542. case "mrm_be_cm_highlightbox":
  1543. $elements = $this->checkText($flex["text"], $dbReference, $processedData, "typo3_paragraph");
  1544. $subs[] = $this->createContentElement("highlightbox", array("icon" => $flex["icon"]), array(), $elements);
  1545. break;
  1546. case "mrm_be_cm_statementbox":
  1547. $items = array();
  1548. $dynContentCounter = 0;
  1549. while (1) {
  1550. $dynContentCounter++;
  1551. if (!isset($flex['text' . $dynContentCounter])) break;
  1552. if ($flex['text' . $dynContentCounter] === '' || $flex['name' . $dynContentCounter] === '') continue;
  1553. $item = array(
  1554. 'quote' => $flex['text' . $dynContentCounter],
  1555. 'cite' => $flex['name' . $dynContentCounter]
  1556. );
  1557. if ($flex['image' . $dynContentCounter] == 1) {
  1558. $imgs = $this->processImagesTTContent($dbReference, 'mrm_be_cm_statementbox', 'tt_content', 'flex_image_' . $dynContentCounter, 'uid', false);
  1559. $imgs = $imgs[0];
  1560. $imgs['src'] = "#cdnurl#/" . $imgs['sources']['img'];
  1561. unset($imgs['sources']);
  1562. $item['img'] = $imgs;
  1563. }
  1564. $items[] = $item;
  1565. }
  1566. $subs[] = $this->createContentElement('statementbox', array('items' => $items));
  1567. break;
  1568. case "mrm_be_cm_explorerbox":
  1569. $items = array();
  1570. $dynContentCounter = 0;
  1571. while (1) {
  1572. $dynContentCounter++;
  1573. if (!isset($flex['head' . $dynContentCounter])) break;
  1574. if ($flex['head' . $dynContentCounter] === '' || $flex['claim' . $dynContentCounter] === '' || $flex['image' . $dynContentCounter] == 0) continue;
  1575. $item = array(
  1576. 'heading' => $flex['head' . $dynContentCounter],
  1577. 'subheading' => $flex['claim' . $dynContentCounter],
  1578. 'text' => $flex['text' . $dynContentCounter]
  1579. );
  1580. if ($flex['image' . $dynContentCounter] == 1) {
  1581. $imgs = $this->processImagesTTContent($dbReference, 'mrm_be_cm_explorerbox', 'tt_content', 'flex_image_' . $dynContentCounter, 'uid', false);
  1582. $imgs = $imgs[0];
  1583. $imgs['src'] = "#cdnurl#/" . $imgs['sources']['img'];
  1584. unset($imgs['sources']);
  1585. $item['img'] = $imgs;
  1586. }
  1587. if ($flex['link' . $dynContentCounter] !== '') {
  1588. $button = $this->parseFlexFormLink($flex['link' . $dynContentCounter], $dbReference, $processedData);
  1589. $item['button'] = $button;
  1590. }
  1591. $items[] = $item;
  1592. }
  1593. $subs[] = $this->createContentElement('explorerbox', array('items' => $items));
  1594. break;
  1595. case "mrm_be_cm_dynamic_tileoverview":
  1596. $items = array();
  1597. foreach ($flex["dynamicComponents"] as $comp) {
  1598. foreach ($comp as $k => $v) {
  1599. $itm = null;
  1600. switch ($k) {
  1601. case "links":
  1602. $lnk = $this->parseFlexFormLink($v["link"], $dbReference, $processedData);
  1603. $itm = $this->createContentElement("tile_default", array("link" => $lnk, "coloured" => $v["coloured"] == 1, "allowed" => preg_split('/\+/', $v["type"]), "format" => $v["format"]));
  1604. if ($lnk["alt"]) $itm["props"]["headline"] = $lnk["alt"];
  1605. break;
  1606. case "buttons":
  1607. $itm = $this->createContentElement(
  1608. "tile_content",
  1609. array(
  1610. "headline" => $v["headline"],
  1611. "content" => $this->checkTextForInternalLinks($v["buttons"], $dbReference, $processedData)
  1612. )
  1613. );
  1614. break;
  1615. case "icons":
  1616. $lnk = $this->parseFlexFormLink($v["link"], $dbReference, $processedData);
  1617. $itm = $this->createContentElement("tile_icon", array("link" => $lnk, "icon" => $v["icon"]), array());
  1618. if ($lnk["alt"]) $itm["props"]["headline"] = $lnk["alt"];
  1619. break;
  1620. case "flat":
  1621. $lnk = $this->parseFlexFormLink($v["link"], $dbReference, $processedData);
  1622. $itm = $this->createContentElement("tile_flat", array("link" => $lnk));
  1623. if ($lnk["alt"]) $itm["props"]["headline"] = $lnk["alt"];
  1624. break;
  1625. case "injections":
  1626. $itm = $this->createContentElement("injection", array("type" => $v["text"]));
  1627. $processedData["injections"][] = $v["text"];
  1628. break;
  1629. }
  1630. if ($itm)
  1631. $items[] = $itm;
  1632. }
  1633. }
  1634. $dto = $this->createContentElement('dynamic_tileoverview', array(), array(), $items);
  1635. if ($flex["cssClass"] && $flex["cssClass"] !== "")
  1636. $dto["attributes"]["cssClassName"] = $flex["cssClass"];
  1637. $subs[] = $dto;
  1638. $processedData["status"]["hasDynamicTileOverview"] = true;
  1639. break;
  1640. case "mrm_be_cm_podcast":
  1641. //$items = array();
  1642. if ($flex['media'] == "1")
  1643. $media = $this->processAudio($dbReference, 'mrm_be_cm_podcast', 'tt_content', 'media', 'uid', true, true);
  1644. if ($flex['transcript'])
  1645. $transcript = $flex['transcript'];
  1646. $subs[] = $this->createContentElement('podcast', array(), array('media' => $media, 'transcript' => $transcript));
  1647. break;
  1648. case "mrm_be_cm_imageplus":
  1649. $props = $this->processImagesTTContent($dbReference)[0];
  1650. $props["type"] = "imageplus";
  1651. $props["headline"] = $flex['headline'] ?? '';
  1652. $props["description"] = $flex['description'] ?? '';
  1653. $props["link"] = $this->parseFlexFormLink($flex["link"], $dbReference, $processedData);
  1654. $props["customcss"] = $flex['customcss'] ?? '';
  1655. $subs[] = $this->createContentElement('imageplus', $props);
  1656. break;
  1657. case "mrm_be_cm_interviewfrage":
  1658. $props['lang'] = $flex['lang'] ?? '';
  1659. $subs[] = $this->createContentElement("interviewfrage", $props, array("question" => trim($flex['question'])));
  1660. break;
  1661. case "mrm_be_cm_interviewantwort":
  1662. $props['lang'] = $flex['lang'] ?? '';
  1663. $subs[] = $this->createContentElement("interviewantwort", $props, array("interviewee" => trim($flex['interviewee']),"answer" => trim($flex['answer'])));
  1664. break;
  1665. case "mrm_be_cm_foldout_h3":
  1666. $sub = $this->createContentElement("typo3_foldout_h3", array("open" => $flex["isInitialyOpen"] == "1", "noAutoOpen" => $flex["noAutoOpen"] == "1"), array("headline" => $flex["headline"]), array());
  1667. if ($flex["image"] == "1") {
  1668. $props = $this->processImagesTTContent($dbReference, "mrm_be_cm_contentimage")[0];
  1669. $props["type"] = "typo3_content";
  1670. $sub["subElements"][] = $this->createContentElement("image", $props);
  1671. } else {
  1672. switch ($flex["icon"]) {
  1673. case "1":
  1674. $sub["attributes"]["icon"] = "stadtinfo_basics";
  1675. break;
  1676. case "2":
  1677. $sub["attributes"]["icon"] = "geschichte";
  1678. break;
  1679. case "3":
  1680. $sub["attributes"]["icon"] = "kultur_freizeit";
  1681. break;
  1682. case "4":
  1683. $sub["attributes"]["icon"] = "besonderheiten";
  1684. break;
  1685. case "5":
  1686. $sub["attributes"]["icon"] = "kosten_geld";
  1687. break;
  1688. case "6":
  1689. $sub["attributes"]["icon"] = "hochschulen";
  1690. break;
  1691. case "7":
  1692. $sub["attributes"]["icon"] = "studieren";
  1693. break;
  1694. }
  1695. }
  1696. if ($flex["dynamicComponents"] && sizeof($flex["dynamicComponents"]) > 0)
  1697. foreach ($flex["dynamicComponents"] as $comp) {
  1698. $stype = array_keys($comp['settings'])[0];
  1699. $elements = $this->checkText($comp['settings'][$stype][$stype], $dbReference, $processedData, $stype == "paragraph" ? "typo3_paragraph" : ($stype == "headline" ? "h4" : $stype));
  1700. $sub["subElements"] = array_merge($sub["subElements"], $elements);
  1701. }
  1702. $subs[] = $sub;
  1703. break;
  1704. case "mrm_be_cm_quiz_direct":
  1705. //print_r($flex); die();
  1706. $s = $this->createContentElement(
  1707. "quizdirect",
  1708. array(
  1709. "labels" => array(
  1710. "startbutton" => $flex["startbuttontext"],
  1711. "submitbutton" => $flex["submitbuttontext"],
  1712. "nextbutton" => $flex["nextbuttontext"],
  1713. "lastbutton" => $flex["lastbuttontext"],
  1714. "question" => $flex["question"],
  1715. "repeatbutton" => $flex["repeatbuttontext"],
  1716. "qsuccess" => $flex["questionsuccesstext"],
  1717. "qfail" => $flex["questionfailtext"],
  1718. ),
  1719. "resultscreen" => array(
  1720. "headingTop" => $flex["resultheadingtop"],
  1721. "headingSub" => $flex["resultheadingsub"],
  1722. "validation" => $flex["validationstr"],
  1723. "end" => $flex["thanks"]
  1724. ),
  1725. "isRestartAble" => $flex["isRestartAble"] == 1 || $flex["isRestartAble"] == "1",
  1726. ),
  1727. array(
  1728. "items" => array_values(array_map(function ($v) {
  1729. $questionType = null;
  1730. $quest = $v['settings']['question'];
  1731. if (!isset($quest)) {
  1732. $quest = $v['settings']['question_multi'];
  1733. $questionType = "multi";
  1734. }
  1735. if (isset($quest["additional_text"]) && $quest["additional_text"] != "") {
  1736. $quest["text"] = $quest["text"] . " (" . $quest["additional_text"] . ")";
  1737. unset($quest["additional_text"]);
  1738. }
  1739. if ($questionType) $quest["type"] = $questionType;
  1740. unset($quest["rightanswer"]);
  1741. if(isset($quest['solutionText'])) $solution = $quest['solutionText'];
  1742. unset($quest['solutionText']);
  1743. $i = 0;
  1744. $quest["answers"] = array();
  1745. while (1) {
  1746. $i++;
  1747. if (!isset($quest["answertext" . $i])) break;
  1748. if ($quest["answertext" . $i] === "") continue;
  1749. $quest["answers"][] = array("text" => $quest["answertext" . $i], "points" => (int)$quest["answerpoints" . $i]);
  1750. unset($quest["answertext" . $i]);
  1751. unset($quest["answerpoints" . $i]);
  1752. }
  1753. $quest["solution"] = $solution;
  1754. return $quest;
  1755. }, $flex["dynamicComponents"])),
  1756. "validation" => array(
  1757. "maxPoints" => (int)$flex["maxpoints"],
  1758. "averagePoints" => $this->createContentElement("injection", array("type" => "quiz-averagePoints")),
  1759. "alreadyReachedPoints" => $this->createContentElement("injection", array("type" => "quiz-alreadyReachedPoints")),
  1760. "items" => ($flex["dynamicComponents2"] == 0) ? [] : array_map(
  1761. function ($i) {
  1762. if(empty($i["validationText"])) $i["validationText"] = "";
  1763. else $i["validationText"] = $this->checkTextForInternalLinks($i["validationText"], $dbReference, $processedData);
  1764. return $i;
  1765. },
  1766. array_filter(array_values(array_map(function ($v) {
  1767. return $v['settings']['validation'];
  1768. }, $flex["dynamicComponents2"])), function ($x) {
  1769. return $x != null;
  1770. })
  1771. ),
  1772. ),
  1773. )
  1774. );
  1775. $processedData["injections"][] = "quiz-averagePoints";
  1776. $processedData["injections"][] = "quiz-alreadyReachedPoints";
  1777. $subs[] = $s;
  1778. $processedData["status"]["hasQuiz"] = true;
  1779. break;
  1780. default:
  1781. $this->log("MISSING PROCESSDATA 4 " . $dbReference['CType']);
  1782. $this->log($flex, false);
  1783. break;
  1784. }
  1785. }
  1786. private function checkText($txt, $dbReference, &$processedData, $defaultElementType = "typo3_paragraph")
  1787. {
  1788. $txt = $this->checkTextForInternalLinks($txt, $dbReference, $processedData);
  1789. $txt = $this->refactorTextElements($txt, $defaultElementType);
  1790. return $txt;
  1791. }
  1792. private function refactorTextElements($txt, $defaultElementType)
  1793. {
  1794. if (strpos($txt, "<table") === FALSE) return [$this->createContentElement($defaultElementType, array(), array("text" => $txt))];
  1795. $elements = [];
  1796. while (($tablepos = strpos($txt, "<table")) !== FALSE) {
  1797. if ($tablepos != 0) {
  1798. //$this->log(trim(substr($txt, 0, $tablepos)));
  1799. $elements[] = $this->createContentElement($defaultElementType, array(), array("text" => trim(substr($txt, 0, $tablepos))));
  1800. $txt = substr($txt, $tablepos);
  1801. }
  1802. $tablepos = strpos($txt, "</table>") + 8;
  1803. $dom = new \DOMDocument();
  1804. @$dom->loadHTML('<?xml encoding="utf-8" ?><div id="sexy">' . trim(substr($txt, 0, $tablepos)) . '</div>', LIBXML_HTML_NOIMPLIED | LIBXML_HTML_NODEFDTD);
  1805. $tab = $this->createContentElement("table", array("rows" => array(), "columnCount" => 0));
  1806. foreach ($dom->getElementsByTagName('tr') as $tr) {
  1807. $par = $tr->parentNode;
  1808. $row = [];
  1809. if ($tab["props"]["columnCount"] == 0) {
  1810. foreach ($tr->childNodes as $e) {
  1811. if ($e->tagName == "td" || $e->tagName == "th") {
  1812. $tab["props"]["columnCount"]++;
  1813. }
  1814. }
  1815. }
  1816. foreach ($tr->childNodes as $e) {
  1817. if ($e->tagName != "td" && $e->tagName != "th") continue;
  1818. $innerHTML = '';
  1819. foreach ($e->childNodes as $n) $innerHTML .= $dom->saveHtml($n);
  1820. $row[] = array(
  1821. "html" => "<p>" . $innerHTML . "</p>",
  1822. "isHeader" => $par->tagName == "thead",
  1823. "isRowHeader" => $e->tagName == "th" && $par->tagName != "thead",
  1824. );
  1825. }
  1826. $tab["props"]["rows"][] = $row;
  1827. }
  1828. $elements[] = $tab;
  1829. $txt = substr($txt, $tablepos);
  1830. }
  1831. $txt = trim($txt);
  1832. if ($txt != "")
  1833. $elements[] = $this->createContentElement($defaultElementType, array(), array("text" => $txt));
  1834. return $elements;
  1835. }
  1836. private function checkTextForInternalLinks($txt, $dbReference, &$processedData)
  1837. {
  1838. $dom = new \DOMDocument();
  1839. @$dom->loadHTML('<?xml encoding="utf-8" ?><div id="sexy">' . $txt . '</div>', LIBXML_HTML_NOIMPLIED | LIBXML_HTML_NODEFDTD);
  1840. foreach ($dom->getElementsByTagName('a') as $link) {
  1841. $emptyHref = false;
  1842. $title = null;
  1843. $alt = null;
  1844. $href = null;
  1845. for ($i = 0; $i < $link->attributes->length; ++$i) {
  1846. $node = $link->attributes->item($i);
  1847. if ($node->nodeName == "href" && strpos($node->nodeValue, 'smartadserver.com') === FALSE) {
  1848. $nv = $node->nodeValue;
  1849. $nv = str_replace('&amp;', '&', $nv);
  1850. $href = $this->replaceT3Link($nv, $dbReference, $processedData);
  1851. $node->nodeValue = htmlspecialchars($href);
  1852. if ($node->nodeValue == '') $emptyHref = true;
  1853. }
  1854. if ($node->nodeName == "title" && $node->nodeValue != '') $title = $node->nodeValue;
  1855. if ($node->nodeName == "alt" && $node->nodeValue != '') $alt = $node->nodeValue;
  1856. }
  1857. if ($emptyHref) $link->removeAttribute('href');
  1858. else {
  1859. if (!$alt) {
  1860. //check for pdf files (AS-337)
  1861. if (strtolower(pathinfo($href, PATHINFO_EXTENSION)) == "pdf") {
  1862. $alt = "PDF-Download (öffnet sich in neuem Fenster)";
  1863. $link->setAttribute('target', '_blank');
  1864. $link->setAttribute('alt', $alt);
  1865. }
  1866. }
  1867. }
  1868. if ($title && !$alt) $link->setAttribute('alt', $title);
  1869. if ($title) $link->removeAttribute('title');
  1870. }
  1871. $txt = $dom->saveHTML($dom->getElementById('sexy'));
  1872. $txt = str_replace('<div id="sexy">', '', $txt);
  1873. $txt = substr($txt, 0, -6);
  1874. return trim($txt);
  1875. }
  1876. private function parseFlexFormLink($link, $dbReference, &$processedData)
  1877. {
  1878. $link = implode("/", explode("\/", $link));
  1879. [$href, $target, $css] = explode(" ", $link);
  1880. $alt = substr($link, strlen($href . $target . $css) + 3);
  1881. $alt = preg_replace('/&quot;/', '', trim($alt, " \""));
  1882. if ($href == "-") return null;
  1883. $href = $this->replaceT3Link($href, $dbReference, $processedData, true);
  1884. $ret = array("href" => $href);
  1885. if (!$target || $target == "-") $ret["target"] = "_top";
  1886. else $ret["target"] = $target;
  1887. if ($alt && $alt != "-") $ret["alt"] = $alt;
  1888. return $ret;
  1889. }
  1890. private function replaceT3Link($link, $dbReference, &$processedData, $addToLinkedPosts = false)
  1891. {
  1892. $uid = $this->parseUIDFromT3Url($link);
  1893. if (!$uid || $uid == '') return $link;
  1894. if (strpos($link, 't3://page?') !== false) {
  1895. if ($uid == "current") {
  1896. $link = str_replace('t3://page?uid=current', '', $link);
  1897. } else {
  1898. if ($addToLinkedPosts) {
  1899. $processedData['linkedPosts'][] = (int)$uid;
  1900. $link = "#linkedPost#" . $uid . "#/linkedPost#";
  1901. } else {
  1902. $pageStatement = $this->pageQueryBuilder
  1903. ->select('*')
  1904. ->from('pages')
  1905. ->setMaxResults(1)
  1906. ->where(
  1907. $this->pageQueryBuilder->expr()->eq('uid', $this->pageQueryBuilder->createNamedParameter($uid))
  1908. )
  1909. ->execute();
  1910. $post = $pageStatement->fetchAll();
  1911. $post = $post[0];
  1912. $link = $post['slug'];
  1913. }
  1914. }
  1915. }
  1916. if (strpos($link, 't3://file?') !== false)
  1917. $link = $this->setStaticFile($dbReference, $uid);
  1918. return $link;
  1919. }
  1920. private function setStaticFile($dbReference, $uid, $publicUrl = null)
  1921. {
  1922. $fnNameRef = $dbReference['pid'] . "|" . $dbReference['uid'] . "|" . $dbReference['CType'] . "|file|" . $uid;
  1923. if (!$publicUrl) {
  1924. $file = $this->resourceFactory->getFileObject($uid);
  1925. $publicUrl = $file->getPublicUrl();
  1926. }
  1927. try {
  1928. $fnName = basename($publicUrl);
  1929. $fnName = explode(".", $fnName);
  1930. $extension = array_pop($fnName);
  1931. $fnName = implode(".", $fnName);
  1932. } catch (Exception $e) {
  1933. $fnName = null;
  1934. }
  1935. return "#cdnurl#/" . $this->copyAndRenameFile($fnNameRef, "/" . $publicUrl, $fnName);
  1936. }
  1937. private function parseUIDFromT3Url($t3url)
  1938. {
  1939. $uid = null;
  1940. if ($t3url && $t3url != '' && substr($t3url, 0, 2) == "t3")
  1941. try {
  1942. parse_str(parse_url($t3url)['query'], $query);
  1943. $uid = $query['uid'];
  1944. } catch (Exception $e) {
  1945. }
  1946. return $uid;
  1947. }
  1948. private function createContentElement($type, $props = null, $attributes = null, $subElements = null)
  1949. {
  1950. if (is_null($props)) $props = array();
  1951. if (is_null($attributes)) $attributes = (object) array();
  1952. $props["__hbs_uid"] = '_ab' . mt_rand(0, 0xffffff) . '_' . mt_rand(0, 0xffffff);
  1953. $ele = array(
  1954. 'type' => $type,
  1955. 'props' => $props,
  1956. 'attributes' => $attributes,
  1957. );
  1958. if (!is_null($subElements)) $ele['subElements'] = $subElements;
  1959. else $ele['subElements'] = [];
  1960. return $ele;
  1961. }
  1962. private function processVideo($dbReference)
  1963. {
  1964. $data = $this->resourceFactory->convertFlexFormDataToConfigurationArray($dbReference['pi_flexform']);
  1965. $vids = array();
  1966. foreach ($data['settings']['video'] as $value) {
  1967. if ($value['posterConfiguration'] && $value['posterConfiguration'] != '') $vids['poster'] = $value['posterConfiguration']['image'];
  1968. if ($value['mp4Configuration'] && $value['mp4Configuration'] != '') $vids['mp4'] = $value['mp4Configuration']['video'];
  1969. if ($value['ogvConfiguration'] && $value['ogvConfiguration'] != '') $vids['ogv'] = $value['ogvConfiguration']['video'];
  1970. if ($value['webmConfiguration'] && $value['webmConfiguration'] != '') $vids['webm'] = $value['webmConfiguration']['video'];
  1971. if ($value['threegpConfiguration'] && $value['threegpConfiguration'] != '') $vids['3gp'] = $value['threegpConfiguration']['video'];
  1972. }
  1973. foreach ($vids as $key => &$value) {
  1974. $value = "/" . $value;
  1975. $fnNameRef = $dbReference['pid'] . "|" . $dbReference['uid'] . "|" . $dbReference['CType'] . "|" . $key;
  1976. $value = $this->copyAndRenameFile($fnNameRef, $value);
  1977. }
  1978. return $vids;
  1979. }
  1980. private function processImagesTTContent($dbReference, $ctypeOverride = '', $table = 'tt_content', $tableColumn = 'image', $refField = 'uid', $useRelationFetch = true, $addCDNPrefix = false)
  1981. {
  1982. if ($useRelationFetch)
  1983. $fileObjects = $this->fileRepository->findByRelation($table, $tableColumn, $dbReference[$refField]);
  1984. else {
  1985. $sysfilerefQueryBuilder = $this->connection->getQueryBuilderForTable('sys_file_reference');
  1986. $sysfileStatement = $sysfilerefQueryBuilder
  1987. ->select('uid')
  1988. ->from('sys_file_reference')
  1989. ->andWhere(
  1990. $sysfilerefQueryBuilder->expr()->eq('uid_foreign', intval($dbReference[$refField])),
  1991. $sysfilerefQueryBuilder->expr()->eq('tablenames', $sysfilerefQueryBuilder->createNamedParameter($table)),
  1992. $sysfilerefQueryBuilder->expr()->eq('fieldname', $sysfilerefQueryBuilder->createNamedParameter($tableColumn)),
  1993. )
  1994. ->execute();
  1995. $frows = $sysfileStatement->fetchAll();
  1996. foreach ($frows as $fileuid) {
  1997. $fileObjects[] = $this->fileRepository->findFileReferenceByUid(intval($fileuid['uid']));
  1998. }
  1999. }
  2000. $processedImages = array();
  2001. $ctypeOverride = $ctypeOverride != '' ? $ctypeOverride : $dbReference['CType'];
  2002. foreach ($fileObjects as $key => $value) {
  2003. $img = array(
  2004. 'reference' => $value->getReferenceProperties(),
  2005. 'original' => $value->getOriginalFile()->getProperties(),
  2006. );
  2007. $imgfn = rtrim($img['original']['identifier'], "/");
  2008. $image = $this->imageService->getImage('fileadmin/' . $imgfn, null, false);
  2009. $cropvariantcollection = \TYPO3\CMS\Core\Imaging\ImageManipulation\CropVariantCollection::create($img['reference']['crop']);
  2010. $cropareas = $this->imageSizes[$ctypeOverride];
  2011. $processArray = array(
  2012. 'sources' => array()
  2013. );
  2014. $alt = $img['reference']['alternative'] != NULL ? $img['reference']['alternative'] : ($img['original']['alternative'] != NULL ? $img['original']['alternative'] : NULL);
  2015. $title = $img['reference']['title'] != NULL ? $img['reference']['title'] : ($img['original']['title'] != NULL ? $img['original']['title'] : NULL);
  2016. $caption = $img['reference']['description'] != NULL ? $img['reference']['description'] : ($img['original']['description'] != NULL ? $img['original']['description'] : NULL);
  2017. $copyright = $img['reference']['copyright'] != NULL ? $img['reference']['copyright'] : ($img['original']['copyright'] != NULL ? $img['original']['copyright'] : NULL);
  2018. if ($alt != NULL) $processArray['alt'] = $alt;
  2019. if ($title != NULL) $processArray['title'] = $title;
  2020. if ($caption != NULL) $processArray['caption'] = $caption;
  2021. if ($copyright != NULL) $processArray['copyright'] = $copyright;
  2022. if ($cropareas['passthru']) {
  2023. if (is_array($cropareas['passthru'])) {
  2024. foreach ($cropareas['passthru'] as $sizename => $size) {
  2025. $processingInstructions = array(
  2026. 'width' => $size['width'],
  2027. 'minWidth' => $size['width'],
  2028. 'maxWidth' => $size['width'],
  2029. 'crop' => null
  2030. );
  2031. if ($size['height']) {
  2032. $processingInstructions = array_merge(
  2033. $processingInstructions,
  2034. array(
  2035. 'height' => $size['height'],
  2036. 'minHeight' => $size['height'],
  2037. 'maxHeight' => $size['height']
  2038. )
  2039. );
  2040. }
  2041. if ($size['maxHeight'])
  2042. $processingInstructions['maxHeight'] = $size['maxHeight'];
  2043. if ($size['minHeight'])
  2044. $processingInstructions['minHeight'] = $size['minHeight'];
  2045. $processedImage = $this->imageService->applyProcessingInstructions($image, $processingInstructions);
  2046. $imageUri = $this->imageService->getImageUri($processedImage);
  2047. $fnNameRef = $dbReference['pid'] . "|" . $dbReference['uid'] . "|" . $ctypeOverride . "|" . $img['reference']['uid'] . "|passthru|" . $sizename;
  2048. $processArray['sources'][$sizename] = $this->copyAndRenameFile($fnNameRef, $imageUri, $processArray['alt']);
  2049. }
  2050. } else {
  2051. $fnNameRef = $dbReference['pid'] . "|" . $dbReference['uid'] . "|" . $ctypeOverride . "|" . $img['reference']['uid'] . "|passthru";
  2052. $imageUri = $this->imageService->getImageUri($image);
  2053. $processArray['sources']['passthru'] = ($addCDNPrefix ? "#cdnurl#/" : "") . $this->copyAndRenameFile($fnNameRef, $imageUri, $processArray['alt']);
  2054. }
  2055. } else
  2056. foreach ($cropareas as $cropareaname => $sizes) {
  2057. $croparea = $cropvariantcollection->getCropArea($cropareaname);
  2058. foreach ($sizes as $sizename => $size) {
  2059. if ($dbReference["doktype"] && $size['allowed_doktypes'] && !in_array($dbReference["doktype"], $size['allowed_doktypes'])) continue;
  2060. $processingInstructions = array(
  2061. 'width' => $size['width'],
  2062. 'minWidth' => $size['width'],
  2063. 'maxWidth' => $size['width'],
  2064. 'crop' => $croparea->isEmpty() ? null : $croparea->makeAbsoluteBasedOnFile($image)
  2065. );
  2066. if ($size['height']) {
  2067. $processingInstructions = array_merge(
  2068. $processingInstructions,
  2069. array(
  2070. 'height' => $size['height'],
  2071. 'minHeight' => $size['height'],
  2072. 'maxHeight' => $size['height']
  2073. )
  2074. );
  2075. }
  2076. if ($size['maxHeight'])
  2077. $processingInstructions['maxHeight'] = $size['maxHeight'];
  2078. if ($size['minHeight'])
  2079. $processingInstructions['minHeight'] = $size['minHeight'];
  2080. $processedImage = $this->imageService->applyProcessingInstructions($image, $processingInstructions);
  2081. $imageUri = $this->imageService->getImageUri($processedImage);
  2082. $fnNameRef = $dbReference['pid'] . "|" . $dbReference['uid'] . "|" . $ctypeOverride . "|" . $img['reference']['uid'] . "|" . $cropareaname . "|" . $sizename;
  2083. $processArray['sources'][$sizename] = ($addCDNPrefix ? "#cdnurl#/" : "") . $this->copyAndRenameFile($fnNameRef, $imageUri, $processArray['alt']);
  2084. }
  2085. }
  2086. $processedImages[] = $processArray;
  2087. }
  2088. return $processedImages;
  2089. }
  2090. private function processAudio($dbReference, $ctypeOverride = '', $table = 'tt_content', $tableColumn = 'media', $refField = 'uid', $useRelationFetch = true, $copyToCDN = false)
  2091. {
  2092. if ($useRelationFetch)
  2093. $fileObjects = $this->fileRepository->findByRelation($table, $tableColumn, $dbReference[$refField]);
  2094. else {
  2095. $sysfilerefQueryBuilder = $this->connection->getQueryBuilderForTable('sys_file_reference');
  2096. $sysfileStatement = $sysfilerefQueryBuilder
  2097. ->select('uid')
  2098. ->from('sys_file_reference')
  2099. ->andWhere(
  2100. $sysfilerefQueryBuilder->expr()->eq('uid_foreign', intval($dbReference[$refField])),
  2101. $sysfilerefQueryBuilder->expr()->eq('tablenames', $sysfilerefQueryBuilder->createNamedParameter($table)),
  2102. $sysfilerefQueryBuilder->expr()->eq('fieldname', $sysfilerefQueryBuilder->createNamedParameter($tableColumn)),
  2103. )
  2104. ->execute();
  2105. $frows = $sysfileStatement->fetchAll();
  2106. foreach ($frows as $fileuid) {
  2107. $fileObjects[] = $this->fileRepository->findFileReferenceByUid(intval($fileuid['uid']));
  2108. }
  2109. }
  2110. $processedAudio = array();
  2111. $audio = [];
  2112. $ctypeOverride = $ctypeOverride != '' ? $ctypeOverride : $dbReference['CType'];
  2113. foreach ($fileObjects as $key => $value) {
  2114. $processedAudio = array(
  2115. 'reference' => $value->getReferenceProperties(),
  2116. 'original' => $value->getOriginalFile()->getProperties(),
  2117. );
  2118. if ($copyToCDN) {
  2119. $oringalFile = $processedAudio['original']['identifier'];
  2120. $extension = pathinfo($processedAudio['original']['identifier'], PATHINFO_EXTENSION);
  2121. $targetFile = substr(sha1($processedAudio['original']['identifier']), 0, 5) . '_podcast.' . $extension;
  2122. $oringalFile = '/fileadmin' . $oringalFile;
  2123. $url = $this->copyPodcastAudioFileToCDN($oringalFile, $targetFile);
  2124. }
  2125. $audio['name'] = $processedAudio['original']['name'];
  2126. $audio['url'] = $url;
  2127. $audio['title'] = $processedAudio['reference']['title'];
  2128. $audio['description'] = $processedAudio['reference']['description'];
  2129. }
  2130. return $audio;
  2131. }
  2132. private function copyAndRenameFile($destinationFnRef, $sourceUri, $altText = null)
  2133. {
  2134. $shaFileRef = sha1($destinationFnRef);
  2135. $workPath = substr($shaFileRef, 0, 2) . "/" . substr($shaFileRef, 2, 2);
  2136. $workFnPrefix = $shaFileRef;
  2137. if ($altText) {
  2138. $altText = substr($altText, 0, 100);
  2139. $workFnPrefix = $this->sanitizeString($altText) . "-" . $shaFileRef;
  2140. }
  2141. $workFn = $workFnPrefix . "." . pathinfo($sourceUri, PATHINFO_EXTENSION);
  2142. if (!file_exists(\TYPO3\CMS\Core\Core\Environment::getPublicPath() . '/cdn/' . $workPath)) {
  2143. mkdir(\TYPO3\CMS\Core\Core\Environment::getPublicPath() . '/cdn/' . $workPath, 0777, true);
  2144. }
  2145. copy(\TYPO3\CMS\Core\Core\Environment::getPublicPath() . $sourceUri, \TYPO3\CMS\Core\Core\Environment::getPublicPath() . '/cdn/' . $workPath . '/' . $workFn);
  2146. return $workPath . '/' . $workFn;
  2147. }
  2148. private function copyPodcastAudioFileToCDN($sourceFile, $destinationFile)
  2149. {
  2150. $dir = 'podcast';
  2151. if (!file_exists(\TYPO3\CMS\Core\Core\Environment::getPublicPath() . '/cdn/' . $dir)) {
  2152. mkdir(\TYPO3\CMS\Core\Core\Environment::getPublicPath() . '/cdn/' . $dir, 0777, true);
  2153. }
  2154. copy(\TYPO3\CMS\Core\Core\Environment::getPublicPath() . $sourceFile, \TYPO3\CMS\Core\Core\Environment::getPublicPath() . '/cdn/' . $dir . '/' . $destinationFile);
  2155. return '#cdnurl#/' . $dir . '/' . $destinationFile;
  2156. }
  2157. public function processCmdmap_deleteAction($table, $id, $recordToDelete, $recordWasDeleted = NULL, \TYPO3\CMS\Core\DataHandling\DataHandler &$pObj)
  2158. {
  2159. //$this->log('processCmdmap_deleteAction');
  2160. if ($table == "pages") {
  2161. Mongoer::sendRequest("pages", "delete", array("pageuid" => $id));
  2162. Mongoer::sendRequest("abialtcache", "delete", array("pageuid" => $pid));
  2163. Mongoer::sendRequest("search", "delete", array("pageuid" => $id));
  2164. Mongoer::sendRequest("security", "delete", array("pageuid" => $id));
  2165. Mongoer::sendRequest("previews", "delete", array("pageuid" => $id));
  2166. }
  2167. }
  2168. /* PRIVATES */
  2169. private function log($msg, $isString = true)
  2170. {
  2171. if (!$isString) {
  2172. $msg = json_encode($msg, JSON_PRETTY_PRINT);
  2173. }
  2174. file_put_contents('/var/www/html/public/typo3temp/debug.log', $msg . PHP_EOL, FILE_APPEND);
  2175. }
  2176. }