TCEMainHook.php 99 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380
  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. 'orderStatus' => $post['orderStatus'],
  703. 'date-updated' => ($post['orderStatus'] === 'neu') ? $post['starttime'] : (($post['orderStatus'] === 'aktualisiert') ? $post['red_end'] : ''),
  704. 'seo' => array(
  705. 'sitemap_changefreq' => $post['sitemap_changefreq'],
  706. 'sitemap_priority' => $post['sitemap_priority'],
  707. 'sitemap_lastmod' => time(),
  708. ),
  709. );
  710. if ($post['starttime'] != 0) {
  711. $status['isLiveFrom'] = $this->startOfDay($post['starttime']);
  712. }
  713. if ($post['endtime'] != 0) {
  714. $status['isLiveTill'] = $this->endOfDay($post['endtime']);
  715. }
  716. if ($post['doktype'] == '101') {
  717. $status['blog_author'] = $post['blog_author'];
  718. $status['blog_category'] = $post['blog_category'];
  719. }
  720. if ($post['doktype'] == '100') {
  721. $status['event_state'] = $post['event_state'];
  722. $status['event_category'] = $post['event_category'];
  723. }
  724. if ($post['doktype'] == '104') {
  725. $status['video_category'] = $post['event_category'];
  726. }
  727. //$this->log($status, false);
  728. return $status;
  729. }
  730. private function constructRedirects($pageData)
  731. {
  732. $redirects = array(
  733. '/?id=' . $pageData['uid']
  734. );
  735. //TODO: Add a single \r to match old Macs line breaks?
  736. foreach (preg_split('/\n|\r\n?/', $pageData['redirects']) as $redir) {
  737. $redir = trim($redir);
  738. if ($redir == '') continue;
  739. $redirects[] = $redir;
  740. }
  741. return $redirects;
  742. }
  743. private function convertStringToTechnicalName($string)
  744. {
  745. $string = $this->sanitizeString($string);
  746. $string = preg_replace('/-/', '', $string);
  747. return strtoupper($string);
  748. }
  749. private function sanitizeString($string)
  750. {
  751. $table = array(
  752. 'Š' => 'S', 'š' => 's', 'Đ' => 'Dj', 'đ' => 'dj', 'Ž' => 'Z', 'ž' => 'z', 'Č' => 'C', 'č' => 'c', 'Ć' => 'C', 'ć' => 'c',
  753. 'À' => 'A', 'Á' => 'A', 'Â' => 'A', 'Ã' => 'A', 'Ä' => 'AE', 'Å' => 'A', 'Æ' => 'A', 'Ç' => 'C', 'È' => 'E', 'É' => 'E',
  754. 'Ê' => 'E', 'Ë' => 'E', 'Ì' => 'I', 'Í' => 'I', 'Î' => 'I', 'Ï' => 'I', 'Ñ' => 'N', 'Ò' => 'O', 'Ó' => 'O', 'Ô' => 'O',
  755. 'Õ' => 'O', 'Ö' => 'OE', 'Ø' => 'O', 'Ù' => 'U', 'Ú' => 'U', 'Û' => 'U', 'Ü' => 'UE', 'Ý' => 'Y', 'Þ' => 'B', 'ß' => 'Ss',
  756. 'à' => 'a', 'á' => 'a', 'â' => 'a', 'ã' => 'a', 'ä' => 'ae', 'å' => 'a', 'æ' => 'a', 'ç' => 'c', 'è' => 'e', 'é' => 'e',
  757. 'ê' => 'e', 'ë' => 'e', 'ì' => 'i', 'í' => 'i', 'î' => 'i', 'ï' => 'i', 'ð' => 'o', 'ñ' => 'n', 'ò' => 'o', 'ó' => 'o',
  758. 'ô' => 'o', 'õ' => 'o', 'ö' => 'oe', 'ø' => 'o', 'ü' => 'ue', 'ù' => 'u', 'ú' => 'u', 'û' => 'u', 'ý' => 'y', 'ý' => 'y',
  759. 'þ' => 'b', 'ÿ' => 'y', 'Ŕ' => 'R', 'ŕ' => 'r', '/' => ''
  760. );
  761. $x = preg_replace(array('/\s{2,}/', '/[\t\n]/'), ' ', $string);
  762. $x = trim(strtr($x, $table));
  763. $x = preg_replace('/[^A-Za-z0-9]+/', ' ', $x);
  764. $x = trim($x);
  765. $x = preg_replace('/ {1,}/', '-', $x);
  766. $x = trim($x, "-");
  767. return $x;
  768. }
  769. private function constructSlug($pid)
  770. {
  771. $postStatement = $this->pageQueryBuilder
  772. ->select('slug')
  773. ->from('pages')
  774. ->setMaxResults(1)
  775. ->where(
  776. $this->pageQueryBuilder->expr()->eq('uid', $this->pageQueryBuilder->createNamedParameter($pid))
  777. )
  778. ->execute();
  779. $postSlug = $postStatement->fetchAll();
  780. $postSlug = $postSlug[0];
  781. return $postSlug ? $postSlug["slug"] : null;
  782. }
  783. private function constructBreadCrumb($rootline, $page, $pageType)
  784. {
  785. $breadCrumb = $this->createContentElement('breadcrumbs');
  786. foreach ($rootline as $post) {
  787. if ($post['doktype'] == 254) continue;
  788. if ($post['is_siteroot'] == 1) continue;
  789. if ($page['uid'] == $post['uid'] && ($pageType == "blogger-page" || $pageType == "video-page"))
  790. $tit = $post['title'];
  791. else
  792. if ($post['use_roof_as_breadcrumb_text'] == 0)
  793. $tit = $post['title'];
  794. else
  795. $tit = $post['roof'] && $post['roof'] != '' ? $post['roof'] : $post['title'];
  796. $breadCrumb['subElements'][] = $this->createContentElement(
  797. 'breadcrumblink',
  798. array(
  799. 'title' => $tit,
  800. 'alt' => $tit,
  801. 'text' => $tit,
  802. 'href' => $this->constructSlug($post['uid'])
  803. )
  804. );
  805. }
  806. return $breadCrumb;
  807. }
  808. private function processData($dbReference, &$processedData, &$processedImages)
  809. {
  810. $isSidebar = $dbReference['colPos'] == 1;
  811. if ($isSidebar)
  812. $subs = &$processedData['pageData']['sidebar']['subElements'];
  813. else
  814. $subs = &$processedData['pageData']['content']['subElements'];
  815. $ffs = GeneralUtility::makeInstance(FlexFormService::class);
  816. $flex = $ffs->convertFlexFormContentToArray($dbReference['pi_flexform']);
  817. // print_r($flex);
  818. // die();
  819. switch ($dbReference['CType']) {
  820. case "mrm_be_cm_postimage":
  821. break;
  822. case "mrm_be_cm_voting":
  823. $s = $this->createContentElement(
  824. "voting",
  825. array(
  826. "labels" => array(
  827. "startbutton" => $flex["startbuttontext"],
  828. ),
  829. "resultscreen" => array(
  830. "headingTop" => $flex["resultheadingtop"],
  831. ),
  832. ),
  833. array(
  834. "items" => array(array(
  835. "text" => $flex["questiontext"],
  836. "type" => $flex["questiontype"] == "1" || $flex["questiontype"] == 1 ? "multi" : "single",
  837. "answers" => array_values(array_map(function ($x) {
  838. return array("text" => $x["settings"]["answer"]["text"], "value" => null);
  839. }, $flex["dynamicComponents"]))
  840. )),
  841. "validation" => array(
  842. "alreadyVoted" => $this->createContentElement("injection", array("type" => "voting-alreadyVoted")),
  843. "chartData" => $this->createContentElement("injection", array("type" => "voting-chartData|")),
  844. ),
  845. )
  846. );
  847. $cntr = 0;
  848. foreach ($s["attributes"]["items"][0]["answers"] as &$a) {
  849. $a["value"] = $cntr;
  850. $cntr++;
  851. }
  852. $s["attributes"]["validation"]["chartData"]["props"]["type"] .= $cntr;
  853. $processedData["injections"][] = "voting-alreadyVoted";
  854. $processedData["injections"][] = "voting-chartData|" . $cntr;
  855. $subs[] = $s;
  856. $processedData["status"]["hasVoting"] = true;
  857. break;
  858. case "mrm_be_cm_checklist-todo":
  859. $elements = $this->createContentElement(
  860. "checklist-todo",
  861. array(
  862. "headlines" => array(
  863. "main" => $flex["headline_main"],
  864. "done" => $flex["headline_done"],
  865. "not_done" => $flex["headline_not_done"],
  866. ),
  867. "controls" => array(
  868. "print" => $flex["enable_print"] == "1",
  869. "pdf" => $flex["enable_pdf"] == "1",
  870. ),
  871. "labels" => array(
  872. "submit" => $flex["label_submit"],
  873. "print" => $flex["label_print"],
  874. "pdf" => $flex["label_pdf"],
  875. ),
  876. "items" => (function ($flex, $dbReference) {
  877. $itms = array();
  878. $imgs = array();
  879. if ($flex["images"] != "0" && $flex["images"] != 0) {
  880. $imgs = $this->processImagesTTContent($dbReference, 'mrm_be_cm_contentimage', 'tt_content', 'image', 'uid', true, true);
  881. }
  882. foreach ($flex["items"] as $itm) {
  883. $i = $itm["item"];
  884. $a = array();
  885. if ($i["text"] != "") $a["text"] = $i["text"];
  886. if ($i["contains_image"] == "1" || $i["contains_image"] == 1) {
  887. $im = array_shift($imgs);
  888. if (isset($im)) $a["img"] = $im;
  889. }
  890. $itms[] = $a;
  891. }
  892. return $itms;
  893. })($flex, $dbReference),
  894. )
  895. );
  896. $subs[] = $elements;
  897. $processedData["status"]["hasChecklist"] = true;
  898. break;
  899. case "mrm_be_cm_checklist_todo_multi":
  900. $elements = $this->createContentElement(
  901. 'checklist-todo-multi',
  902. array(
  903. "texts" => array(
  904. "mainhead" => $flex['mainhead'],
  905. "description" => $flex['description'],
  906. ),
  907. "controls" => array(
  908. "print" => $flex["enable_print"] == "1",
  909. "pdf" => $flex["enable_pdf"] == "1",
  910. ),
  911. "labels" => array(
  912. "print" => $flex["label_print"],
  913. "pdf" => $flex["label_pdf"],
  914. ),
  915. "items" => (function ($flex) {
  916. $itms = [];
  917. $a = array();
  918. foreach ($flex['items'] as $itm) {
  919. if (is_array($itm)) {
  920. $a['head'] = $itm['item']['head'];
  921. $list = $itm['item']['list'];
  922. $doc = new \DOMDocument('1.0', 'utf-8');
  923. $doc->loadHTML('<?xml encoding="UTF-8">' . $list);
  924. $listitems = $doc->getElementsByTagName('li');
  925. $list = [];
  926. foreach ($listitems as $node) {
  927. foreach ($node->childNodes as $child) {
  928. $list[] = array('text' => $child->nodeValue);
  929. }
  930. $a['items'] = $list;
  931. }
  932. }
  933. $itms[] = $a;
  934. }
  935. return $itms;
  936. })($flex),
  937. ),
  938. );
  939. $subs[] = $elements;
  940. break;
  941. case "mrm_be_cm_checklist-input":
  942. $items = array();
  943. $dynContentCounter = 0;
  944. while (true) {
  945. $dynContentCounter++;
  946. if (!isset($flex["label" . $dynContentCounter])) break;
  947. if ($flex["label" . $dynContentCounter] === "") continue;
  948. $label = array(
  949. "label" => $flex["label" . $dynContentCounter]
  950. );
  951. $items[] = $label;
  952. }
  953. $elements = $this->createContentElement(
  954. "checklist-input",
  955. array(
  956. "headlines" => array(
  957. "main" => $flex["headline_main"],
  958. "results" => $flex["headline_result"],
  959. ),
  960. "intro" => $flex["intro"],
  961. "controls" => array(
  962. "print" => $flex["enable_print"] == "1",
  963. "pdf" => $flex["enable_pdf"] == "1",
  964. ),
  965. "labels" => array(
  966. "submit" => $flex["label_submit"],
  967. "print" => $flex["label_print"],
  968. "pdf" => $flex["label_pdf"],
  969. ),
  970. "items" => $items,
  971. )
  972. );
  973. $subs[] = $elements;
  974. $processedData["status"]["hasChecklist"] = true;
  975. break;
  976. case "mrm_be_cm_checklist-scale":
  977. $items = array();
  978. $dynContentCounter = 0;
  979. while (true) {
  980. $dynContentCounter++;
  981. if (!isset($flex["label" . $dynContentCounter])) break;
  982. if ($flex["label" . $dynContentCounter] === "") continue;
  983. $label = array(
  984. "label" => $flex["label" . $dynContentCounter]
  985. );
  986. $items[] = $label;
  987. }
  988. $elements = $this->createContentElement(
  989. "checklist-scale",
  990. array(
  991. "headlines" => array(
  992. "main" => $flex["headline_main"],
  993. "results" => $flex["headline_result"],
  994. ),
  995. "intro" => $flex["intro"],
  996. "maxPoints" => (int)$flex["maxpoints"],
  997. "controls" => array(
  998. "print" => $flex["enable_print"] == "1",
  999. "pdf" => $flex["enable_pdf"] == "1",
  1000. ),
  1001. "labels" => array(
  1002. "nextbutton" => $flex["label_nextbutton"],
  1003. "lastbutton" => $flex["label_lastbutton"],
  1004. "print" => $flex["label_print"],
  1005. "pdf" => $flex["label_pdf"],
  1006. ),
  1007. "items" => $items,
  1008. )
  1009. );
  1010. $subs[] = $elements;
  1011. $processedData["status"]["hasChecklist"] = true;
  1012. break;
  1013. case "mrm_be_cm_checklist-radiorange":
  1014. $items = array();
  1015. $dynContentCounter = 0;
  1016. while (true) {
  1017. $dynContentCounter++;
  1018. if (!isset($flex["pointsFrom" . $dynContentCounter])) break;
  1019. if ($flex["pointsFrom" . $dynContentCounter] === "") continue;
  1020. $item = array(
  1021. "pointsFrom" => (int)$flex["pointsFrom" . $dynContentCounter],
  1022. "pointsTo" => (int)$flex["pointsTo" . $dynContentCounter],
  1023. "validationText" => $flex["validationText" . $dynContentCounter]
  1024. );
  1025. if ($flex["image" . $dynContentCounter] == 1) {
  1026. $images = $this->processImagesTTContent($dbReference, 'mrm_be_cm_checklist-radiorange', 'tt_content', 'flex_image_' . $dynContentCounter, 'uid', false, true);
  1027. $images = $images[0];
  1028. $images["src"] = $images["sources"]["img"];
  1029. unset($images["sources"]);
  1030. $item["img"] = $images;
  1031. }
  1032. $items[] = $item;
  1033. }
  1034. $elements = $this->createContentElement(
  1035. "checklist-radiorange",
  1036. array(
  1037. "headlines" => array(
  1038. "main" => $flex["headline_main"],
  1039. ),
  1040. "intro" => $flex["intro"],
  1041. "validation" => array(
  1042. "maxPoints" => (int)$flex["maxpoints"],
  1043. "items" => $items,
  1044. )
  1045. )
  1046. );
  1047. $subs[] = $elements;
  1048. $processedData["status"]["hasChecklist"] = true;
  1049. break;
  1050. case "mrm_be_cm_checklist-yesmaybeno":
  1051. $items = array();
  1052. foreach ($flex["dynamicComponents"] as $component) {
  1053. foreach ($component as $key => $value) {
  1054. $item = array(
  1055. "heading" => $value["headline"],
  1056. "text" => $value["text"]
  1057. );
  1058. }
  1059. if ($item) {
  1060. $items[] = $item;
  1061. }
  1062. unset($value);
  1063. }
  1064. $choices = array();
  1065. $choice_yes = array(
  1066. "label" => $flex["choice_value_yes"],
  1067. "value" => "yes"
  1068. );
  1069. $choice_maybe = array(
  1070. "label" => $flex["choice_value_maybe"],
  1071. "value" => "maybe"
  1072. );
  1073. $choice_no = array(
  1074. "label" => $flex["choice_value_no"],
  1075. "value" => "no"
  1076. );
  1077. $choices[] = $choice_yes;
  1078. $choices[] = $choice_maybe;
  1079. $choices[] = $choice_no;
  1080. $elements = $this->createContentElement(
  1081. "checklist-yesmaybeno",
  1082. array(
  1083. "headlines" => array(
  1084. "main" => $flex["headline_main"],
  1085. "results" => $flex["headline_result"],
  1086. ),
  1087. "intro" => $flex["intro"],
  1088. "controls" => array(
  1089. "print" => $flex["enable_print"] == "1",
  1090. "pdf" => $flex["enable_pdf"] == "1",
  1091. ),
  1092. "labels" => array(
  1093. "nextbutton" => $flex["label_nextbutton"],
  1094. "lastbutton" => $flex["label_lastbutton"],
  1095. "print" => $flex["label_print"],
  1096. "pdf" => $flex["label_pdf"],
  1097. ),
  1098. "choices" => $choices,
  1099. "items" => $items,
  1100. )
  1101. );
  1102. $subs[] = $elements;
  1103. $processedData["status"]["hasChecklist"] = true;
  1104. break;
  1105. case "mrm_be_cm_picturechoice":
  1106. $s = $this->createContentElement(
  1107. "picturechoice",
  1108. array(
  1109. "labels" => array(
  1110. "startbutton" => $flex["startbuttontext"],
  1111. "nextbutton" => $flex["nextbuttontext"],
  1112. "lastbutton" => $flex["lastbuttontext"],
  1113. "question" => $flex["question"],
  1114. "repeatbutton" => $flex["repeatbuttontext"],
  1115. ),
  1116. "resultscreen" => array(
  1117. "headingTop" => $flex["resultheadingtop"],
  1118. "end" => $flex["thanks"]
  1119. ),
  1120. "isRestartAble" => $flex["isRestartAble"] == 1 || $flex["isRestartAble"] == "1",
  1121. ),
  1122. array(
  1123. "items" => (function ($flex, $dbReference) {
  1124. $ret = array();
  1125. for ($i = 1; $i <= 3; $i++) {
  1126. $item = array();
  1127. for ($j = 1; $j <= 5; $j++) {
  1128. if ($flex["image" . $i . "_" . $j] == "1") {
  1129. $img = $this->processImagesTTContent($dbReference, 'mrm_be_cm_picturechoice', 'tt_content', 'flex_image_' . $i . "_" . $j, 'uid', false, true);
  1130. $img = $img[0];
  1131. $item[] = array(
  1132. "image" => $img,
  1133. "points" => (int) $flex["pointsOfImage" . $i . "_" . $j]
  1134. );
  1135. }
  1136. }
  1137. if (sizeof($item) > 0)
  1138. $ret[] = $item;
  1139. }
  1140. return $ret;
  1141. })($flex, $dbReference),
  1142. "validation" => array(
  1143. "maxPoints" => (int)$flex["maxpoints"],
  1144. "alreadyReachedPoints" => $this->createContentElement("injection", array("type" => "picturechoice-alreadyReachedPoints")),
  1145. "items" => array_map(
  1146. function ($i) {
  1147. $i["validationText"] = $this->checkTextForInternalLinks($i["validationText"], $dbReference, $processedData);
  1148. $i["pointsFrom"] = (int)$i["pointsFrom"];
  1149. $i["pointsTo"] = (int)$i["pointsTo"];
  1150. return $i;
  1151. },
  1152. array_filter(array_values(array_map(function ($v) {
  1153. return $v['settings']['validation'];
  1154. }, $flex["validations"])), function ($x) {
  1155. return $x != null;
  1156. })
  1157. //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
  1158. ),
  1159. ),
  1160. )
  1161. );
  1162. $processedData["injections"][] = "picturechoice-alreadyReachedPoints";
  1163. $subs[] = $s;
  1164. $processedData["status"]["hasPicturechoice"] = true;
  1165. break;
  1166. case "mrm_be_cm_quiz":
  1167. $s = $this->createContentElement(
  1168. "quiz",
  1169. array(
  1170. "labels" => array(
  1171. "startbutton" => $flex["startbuttontext"],
  1172. "nextbutton" => $flex["nextbuttontext"],
  1173. "lastbutton" => $flex["lastbuttontext"],
  1174. "question" => $flex["question"],
  1175. "repeatbutton" => $flex["repeatbuttontext"],
  1176. ),
  1177. "resultscreen" => array(
  1178. "headingTop" => $flex["resultheadingtop"],
  1179. "headingSub" => $flex["resultheadingsub"],
  1180. "validation" => $flex["validationstr"],
  1181. "end" => $flex["thanks"]
  1182. ),
  1183. "isRestartAble" => $flex["isRestartAble"] == 1 || $flex["isRestartAble"] == "1",
  1184. ),
  1185. array(
  1186. "items" => array_values(array_map(function ($v) {
  1187. $questionType = null;
  1188. $quest = $v['settings']['question'];
  1189. if (!isset($quest)) {
  1190. $quest = $v['settings']['question_multi'];
  1191. $questionType = "multi";
  1192. }
  1193. if (isset($quest["additional_text"]) && $quest["additional_text"] != "") {
  1194. $quest["text"] = $quest["text"] . " (" . $quest["additional_text"] . ")";
  1195. unset($quest["additional_text"]);
  1196. }
  1197. if ($questionType) $quest["type"] = $questionType;
  1198. unset($quest["rightanswer"]);
  1199. $i = 0;
  1200. $quest["answers"] = array();
  1201. while (1) {
  1202. $i++;
  1203. if (!isset($quest["answertext" . $i])) break;
  1204. if ($quest["answertext" . $i] === "") continue;
  1205. $quest["answers"][] = array("text" => $quest["answertext" . $i], "points" => (int)$quest["answerpoints" . $i]);
  1206. unset($quest["answertext" . $i]);
  1207. unset($quest["answerpoints" . $i]);
  1208. }
  1209. /* NOTE: DEPRECATED BY SINGLE INPUTS
  1210. $quest["answers"] = array_map(function($x) {
  1211. $x = explode("|", $x);
  1212. $x = array("text" => $x[0], "points" => (int)$x[1]);
  1213. return $x;
  1214. }, explode("\n", $quest["answers"]));
  1215. */
  1216. return $quest;
  1217. }, $flex["dynamicComponents"])),
  1218. "validation" => array(
  1219. "maxPoints" => (int)$flex["maxpoints"],
  1220. "averagePoints" => $this->createContentElement("injection", array("type" => "quiz-averagePoints")),
  1221. "alreadyReachedPoints" => $this->createContentElement("injection", array("type" => "quiz-alreadyReachedPoints")),
  1222. "items" => array_map(
  1223. function ($i) {
  1224. $i["validationText"] = $this->checkTextForInternalLinks($i["validationText"], $dbReference, $processedData);
  1225. return $i;
  1226. },
  1227. array_filter(array_values(array_map(function ($v) {
  1228. return $v['settings']['validation'];
  1229. }, $flex["dynamicComponents2"])), function ($x) {
  1230. return $x != null;
  1231. })
  1232. ),
  1233. ),
  1234. )
  1235. );
  1236. $processedData["injections"][] = "quiz-averagePoints";
  1237. $processedData["injections"][] = "quiz-alreadyReachedPoints";
  1238. $subs[] = $s;
  1239. $processedData["status"]["hasQuiz"] = true;
  1240. break;
  1241. case "mrm_be_cm_animation":
  1242. $script = $flex["script"];
  1243. if ($flex["staticfiles"] != "0" && $flex["staticfiles"] != 0) {
  1244. $imgs = $this->processImagesTTContent($dbReference);
  1245. foreach ($imgs as $idx => $v) {
  1246. $script = implode("#cdnurl#/" . $v["sources"]["passthru"], explode("%ASSET_" . ($idx + 1) . "%", $script));
  1247. }
  1248. }
  1249. $subs[] = $this->createContentElement("animation", array("addJQuery" => $flex["addJQuery"] == 1 || $flex["addJQuery"] == "1"), array("script" => $script));
  1250. $processedData["status"]["hasAnimation"] = true;
  1251. break;
  1252. case "mrm_be_cm_injection":
  1253. $subs[] = $this->createContentElement("injection", array("type" => $flex["text"]));
  1254. $processedData["injections"][] = $flex["text"];
  1255. break;
  1256. case "mrm_be_cm_roof":
  1257. $subs[] = $this->createContentElement("roof", array(), array("text" => $flex["text"]));
  1258. break;
  1259. case "mrm_be_cm_h1":
  1260. $subs[] = $this->createContentElement("h1", array(), array("text" => $flex["text"]));
  1261. break;
  1262. case "mrm_be_cm_h2":
  1263. $subs[] = $this->createContentElement("h2", array(), array("text" => $flex["text"]));
  1264. break;
  1265. case "mrm_be_cm_h3":
  1266. $subs[] = $this->createContentElement("h3", array(), array("text" => $flex["text"]));
  1267. break;
  1268. case "mrm_be_cm_introtext":
  1269. $text = preg_replace("/\n/", "<br />", $flex["text"]);
  1270. $subs[] = $this->createContentElement("introtext", array(), array("text" => $text));
  1271. break;
  1272. case "mrm_be_cm_button":
  1273. $href = $this->parseFlexFormLink($flex["button"], $dbReference, $processedData);
  1274. $buttonType = ($flex['buttonType'] == "0") ? 'button-link' : 'button-scream';
  1275. $button = $this->createContentElement("button", array('buttonType' => $buttonType), array("text" => $flex["text"], "href" => $href["href"], "target" => $href["target"]));
  1276. $subs[] = $button;
  1277. break;
  1278. case "mrm_be_cm_html":
  1279. $subs[] = $this->createContentElement("html", array(), array("text" => $flex["html"]));
  1280. break;
  1281. case "mrm_be_cm_heroimage":
  1282. $props = $this->processImagesTTContent($dbReference)[0];
  1283. $props["type"] = "typo3_hero";
  1284. $subs[] = $this->createContentElement("image", $props);
  1285. break;
  1286. case "mrm_be_cm_contentimage":
  1287. $props = $this->processImagesTTContent($dbReference)[0];
  1288. $props["type"] = "typo3_content";
  1289. $subs[] = $this->createContentElement("image", $props);
  1290. break;
  1291. case "mrm_be_cm_publication":
  1292. $imgprops = $this->processImagesTTContent($dbReference, 'mrm_be_cm_publication')[0];
  1293. $imgprops["type"] = "typo3_publication";
  1294. $publication = $this->createContentElement(
  1295. "publication",
  1296. array(
  1297. "starttime" => $this->startOfDay($flex['starttime']),
  1298. "endtime" => $this->endOfDay($flex['endtime']),
  1299. "issuekey" => $flex['issuekey'],
  1300. ),
  1301. array(
  1302. "image" => $imgprops,
  1303. "number" => $flex["issuenumber"],
  1304. "title" => $flex["issuetitle"],
  1305. "headline" => $flex["issueheadline"],
  1306. "link" => $this->parseFlexFormLink($flex["htmllink"], $dbReference, $processedData),
  1307. "pdf" => $this->parseFlexFormLink($flex["pdflink"], $dbReference, $processedData),
  1308. )
  1309. );
  1310. $subs[] = $publication;
  1311. break;
  1312. case "mrm_be_cm_rawimage":
  1313. $props = $this->processImagesTTContent($dbReference)[0];
  1314. $props["type"] = "typo3_raw";
  1315. $subs[] = $this->createContentElement("image", $props);
  1316. break;
  1317. case "mrm_be_cm_movingimagesvideo":
  1318. $subs[] = $this->createContentElement(
  1319. "movingimagesvideo",
  1320. array(
  1321. "hasNoticeForCrossPromotion" => $flex["hasNoticeForCrossPromotion"] == 1,
  1322. "hasNoticeForAccessibility" => $flex["hasNoticeForAccessibility"] == 1
  1323. ),
  1324. array("vid" => $flex["vid"])
  1325. );
  1326. break;
  1327. case "mrm_be_cm_paragraph":
  1328. $elements = $this->checkText($flex["text"], $dbReference, $processedData, "typo3_paragraph");
  1329. $subs = array_merge($subs, $elements);
  1330. break;
  1331. case "mrm_be_cm_additionalinfobox":
  1332. case "mrm_be_cm_infobox":
  1333. case "mrm_be_cm_extra_infosbox":
  1334. $type = null;
  1335. $open = null;
  1336. $noAutoOpen = null;
  1337. if ($dbReference['CType'] == "mrm_be_cm_additionalinfobox") $type = "typo3_additionalinfobox";
  1338. elseif ($dbReference['CType'] == "mrm_be_cm_infobox") $type = "typo3_infobox";
  1339. else $type = "typo3_extrainfosbox";
  1340. if ($dbReference['CType'] == "mrm_be_cm_additionalinfobox" || $dbReference['CType'] == "mrm_me_cm_extra_infosbox") $open = true;
  1341. else $open = $flex["isInitialyOpen"] == "1";
  1342. if ($dbReference['CType'] == "mrm_be_cm_additionalinfobox" || $dbReference['CType'] == "mrm_be_cm_infobox") $headline = $flex["headline"];
  1343. elseif ($dbReference['CType'] == "mrm_be_cm_extra_infosbox") $headline = '';
  1344. $this->log('Headline: ' . $headline, true);
  1345. $sub = $this->createContentElement(
  1346. $type,
  1347. array("open" => $open, "noAutoOpen" => $flex["noAutoOpen"] == 1),
  1348. array("headline" => $flex["headline"])
  1349. );
  1350. if ($flex["image"] == "1") {
  1351. $props = $this->processImagesTTContent($dbReference, "mrm_be_cm_contentimage")[0];
  1352. $props["type"] = "typo3_content";
  1353. $sub["subElements"][] = $this->createContentElement("image", $props);
  1354. } else {
  1355. switch ($flex["icon"]) {
  1356. case "1":
  1357. $sub["attributes"]["icon"] = "stadtinfo_basics";
  1358. break;
  1359. case "2":
  1360. $sub["attributes"]["icon"] = "geschichte";
  1361. break;
  1362. case "3":
  1363. $sub["attributes"]["icon"] = "kultur_freizeit";
  1364. break;
  1365. case "4":
  1366. $sub["attributes"]["icon"] = "besonderheiten";
  1367. break;
  1368. case "5":
  1369. $sub["attributes"]["icon"] = "kosten_geld";
  1370. break;
  1371. case "6":
  1372. $sub["attributes"]["icon"] = "hochschulen";
  1373. break;
  1374. case "7":
  1375. $sub["attributes"]["icon"] = "studieren";
  1376. break;
  1377. }
  1378. }
  1379. if ($flex["dynamicComponents"] && sizeof($flex["dynamicComponents"]) > 0)
  1380. foreach ($flex["dynamicComponents"] as $comp) {
  1381. $stype = array_keys($comp['settings'])[0];
  1382. $elements = [];
  1383. switch ($stype) {
  1384. case "box":
  1385. $box = $this->createContentElement("boxwrapper");
  1386. $box["subElements"] = array_merge($box["subElements"], $this->checkText($comp['settings']['box']['boxheadline'], $dbReference, $processedData, "h3"));
  1387. $box["subElements"] = array_merge($box["subElements"], $this->checkText($comp['settings']['box']['boxtext'], $dbReference, $processedData, "typo3_paragraph"));
  1388. $elements = [$box];
  1389. break;
  1390. case "boxheadline":
  1391. $elements = $this->checkText($comp['settings'][$stype][$stype], $dbReference, $processedData, "h3");
  1392. //$this->log($elements, false);
  1393. break;
  1394. case "boxtext":
  1395. $elements = $this->checkText($comp['settings'][$stype][$stype], $dbReference, $processedData, "typo3_paragraph");
  1396. break;
  1397. case "html":
  1398. $elements = $this->checkText($comp['settings'][$stype][$stype], $dbReference, $processedData, "html");
  1399. break;
  1400. }
  1401. $sub["subElements"] = array_merge($sub["subElements"], $elements);
  1402. $this->log($sub["subElements"], false);
  1403. }
  1404. $subs[] = $sub;
  1405. break;
  1406. case "mrm_be_cm_foldout":
  1407. $sub = $this->createContentElement("typo3_foldout", array("open" => $flex["isInitialyOpen"] == "1", "noAutoOpen" => $flex["noAutoOpen"] == "1"), array("headline" => $flex["headline"]), array());
  1408. if ($flex["image"] == "1") {
  1409. $props = $this->processImagesTTContent($dbReference, "mrm_be_cm_contentimage")[0];
  1410. $props["type"] = "typo3_content";
  1411. $sub["subElements"][] = $this->createContentElement("image", $props);
  1412. } else {
  1413. switch ($flex["icon"]) {
  1414. case "1":
  1415. $sub["attributes"]["icon"] = "stadtinfo_basics";
  1416. break;
  1417. case "2":
  1418. $sub["attributes"]["icon"] = "geschichte";
  1419. break;
  1420. case "3":
  1421. $sub["attributes"]["icon"] = "kultur_freizeit";
  1422. break;
  1423. case "4":
  1424. $sub["attributes"]["icon"] = "besonderheiten";
  1425. break;
  1426. case "5":
  1427. $sub["attributes"]["icon"] = "kosten_geld";
  1428. break;
  1429. case "6":
  1430. $sub["attributes"]["icon"] = "hochschulen";
  1431. break;
  1432. case "7":
  1433. $sub["attributes"]["icon"] = "studieren";
  1434. break;
  1435. }
  1436. }
  1437. if ($flex["dynamicComponents"] && sizeof($flex["dynamicComponents"]) > 0)
  1438. foreach ($flex["dynamicComponents"] as $comp) {
  1439. $stype = array_keys($comp['settings'])[0];
  1440. $elements = $this->checkText($comp['settings'][$stype][$stype], $dbReference, $processedData, $stype == "paragraph" ? "typo3_paragraph" : ($stype == "headline" ? "h3" : $stype));
  1441. $sub["subElements"] = array_merge($sub["subElements"], $elements);
  1442. }
  1443. $subs[] = $sub;
  1444. break;
  1445. case "mrm_be_cm_newsletterabo":
  1446. $newsletterabo = $this->createContentElement("newsletterabo", array("cr_url" => $flex["cr_url"], "cr_url_BIZ" => $flex["cr_url_BIZ"]));
  1447. $subs[] = $newsletterabo;
  1448. break;
  1449. case "mrm_be_cm_linkage":
  1450. $subs[] = $this->createContentElement("sidebarheadline", array(), array("text" => $flex['headline']));
  1451. $banners = $this->createContentElement("sidebarbanners");
  1452. if ($flex['dynamicComponents'] && sizeof($flex['dynamicComponents']) > 0)
  1453. foreach ($flex['dynamicComponents'] as $banner) {
  1454. $banners["subElements"][] = $this->createContentElement("banner", $this->parseFlexFormLink($banner["settings"]["link"]["link"], $dbReference, $processedData));
  1455. }
  1456. $subs[] = $banners;
  1457. $subs[] = $this->createContentElement("injection", array("type" => "rubrik_content"));
  1458. $processedData["injections"][] = "rubrik_content";
  1459. $berufenet = $this->createContentElement("sidebarexternallinks", array("type" => "berufenet"), array("items" => []));
  1460. if ($flex['dynamicComponentsBerufeNet'] && sizeof($flex['dynamicComponentsBerufeNet']) != 0)
  1461. foreach ($flex['dynamicComponentsBerufeNet'] as $itm) {
  1462. $link = $this->parseFlexFormLink($itm["settings"]["link"]["link"], $dbReference, $processedData);
  1463. $link = '<a href="' . $link['href'] . '" target="' . $link['target'] . '" aria-label="Externer Link">' . $link['alt'] . '</a>';
  1464. $berufenet["attributes"]["items"][] = $link;
  1465. }
  1466. if (sizeof($berufenet["attributes"]["items"]) > 0) $subs[] = $berufenet;
  1467. $berufetv = $this->createContentElement("sidebarexternallinks", array("type" => "berufetv"), array("items" => []));
  1468. if ($flex['dynamicComponentsBerufeTV'] && sizeof($flex['dynamicComponentsBerufeTV']) != 0)
  1469. foreach ($flex['dynamicComponentsBerufeTV'] as $itm) {
  1470. $link = $this->parseFlexFormLink($itm["settings"]["link"]["link"], $dbReference, $processedData);
  1471. $link = '<a href="' . $link['href'] . '" target="' . $link['target'] . '" aria-label="Externer Link">' . $link['alt'] . '</a>';
  1472. $berufetv["attributes"]["items"][] = $link;
  1473. }
  1474. if (sizeof($berufetv["attributes"]["items"]) > 0) $subs[] = $berufetv;
  1475. $berufsausbildung = $this->createContentElement("sidebarexternallinks", array("type" => "berufsausbildung"), array("items" => []));
  1476. if ($flex['dynamicComponentsBerufsausbildung'] && sizeof($flex['dynamicComponentsBerufsausbildung']) != 0)
  1477. foreach ($flex['dynamicComponentsBerufsausbildung'] as $itm) {
  1478. $link = $this->parseFlexFormLink($itm["settings"]["link"]["link"], $dbReference, $processedData);
  1479. $link = '<a href="' . $link['href'] . '" target="' . $link['target'] . '" aria-label="Externer Link">' . $link['alt'] . '</a>';
  1480. $berufsausbildung["attributes"]["items"][] = $link;
  1481. }
  1482. if (sizeof($berufsausbildung["attributes"]["items"]) > 0) $subs[] = $berufsausbildung;
  1483. $ba_search = $this->createContentElement("sidebarexternallinks", array("type" => "ba_search"), array("items" => []));
  1484. if ($flex['dynamicComponentsBASearch'] && sizeof($flex['dynamicComponentsBASearch']) != 0)
  1485. foreach ($flex['dynamicComponentsBASearch'] as $itm) {
  1486. $link = $this->parseFlexFormLink($itm["settings"]["link"]["link"], $dbReference, $processedData);
  1487. $link = '<a href="' . $link['href'] . '" target="' . $link['target'] . '" aria-label="Externer Link">' . $link['alt'] . '</a>';
  1488. $ba_search["attributes"]["items"][] = $link;
  1489. }
  1490. if (sizeof($ba_search["attributes"]["items"]) > 0) $subs[] = $ba_search;
  1491. $studienwahl = $this->createContentElement("sidebarexternallinks", array("type" => "studienwahl"), array("items" => []));
  1492. if ($flex['dynamicComponentsStudienwahl'] && sizeof($flex['dynamicComponentsStudienwahl']) != 0)
  1493. foreach ($flex['dynamicComponentsStudienwahl'] as $itm) {
  1494. $link = $this->parseFlexFormLink($itm["settings"]["link"]["link"], $dbReference, $processedData);
  1495. $link = '<a href="' . $link['href'] . '" target="' . $link['target'] . '" aria-label="Externer Link">' . $link['alt'] . '</a>';
  1496. $studienwahl["attributes"]["items"][] = $link;
  1497. }
  1498. if (sizeof($studienwahl["attributes"]["items"]) > 0) $subs[] = $studienwahl;
  1499. if ($flex['enable_check_u']) {
  1500. $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"));
  1501. $subs[] = $check_u;
  1502. }
  1503. if ($flex['enable_studiencheck']) {
  1504. $studiencheck = $this->createContentElement("extimgbutton", array("ariaLabel" => "Zur Studiencheck-Website", "href" => "https://studiencheck.de/", "target" => "_blank"), array("imgsrc" => "/public/media/ext-link_studiencheck.png"));
  1505. $subs[] = $studiencheck;
  1506. }
  1507. break;
  1508. case "mrm_be_cm_homeheaderinfo":
  1509. $items = array();
  1510. for ($i = 1; $i <= 3; $i++) {
  1511. if ($flex["headline" . $i] != "" && $flex["text" . $i] != "") {
  1512. $item = array("heading" => $flex["headline" . $i], "text" => $flex["text" . $i]);
  1513. if ($flex["link" . $i] != "") {
  1514. $link = $this->parseFlexFormLink($flex["link" . $i], $dbReference, $processedData);
  1515. $item["href"] = $link["href"];
  1516. $item["linkTarget"] = $link["target"];
  1517. }
  1518. if ($flex["image" . $i] == "1") {
  1519. $imgs = $this->processImagesTTContent($dbReference, 'mrm_be_cm_homeheaderinfo', 'tt_content', 'flex_image_' . $i, 'uid', false);
  1520. $item["image"] = "#cdnurl#/" . $imgs[0]["sources"][$flex["imagesize" . $i]];
  1521. }
  1522. $items[] = $item;
  1523. }
  1524. }
  1525. $subs[] = $this->createContentElement("abimessages", array("data" => $items));
  1526. break;
  1527. case "mrm_be_cm_tileoverview":
  1528. $items = array();
  1529. for ($i = 1; $i <= 8; $i++) {
  1530. if ($flex["link" . $i] == "") continue;
  1531. $item = array();
  1532. $link = $this->parseFlexFormLink($flex["link" . $i], $dbReference, $processedData);
  1533. $item["href"] = $link["href"];
  1534. $item["linkTarget"] = $link["target"];
  1535. $item["text"] = $link["alt"];
  1536. if ($flex["image" . $i] == "1") {
  1537. $imgs = $this->processImagesTTContent($dbReference, 'mrm_be_cm_tileoverview', 'tt_content', 'flex_image_' . $i, 'uid', false);
  1538. $item["image"] = "#cdnurl#/" . $imgs[0]["sources"]["default_hero_lte600"];
  1539. }
  1540. $items[] = $item;
  1541. }
  1542. $subs[] = $this->createContentElement("tileoverview", array("items" => $items));
  1543. break;
  1544. case "mrm_be_cm_highlightbox":
  1545. $elements = $this->checkText($flex["text"], $dbReference, $processedData, "typo3_paragraph");
  1546. $subs[] = $this->createContentElement("highlightbox", array("icon" => $flex["icon"]), array(), $elements);
  1547. break;
  1548. case "mrm_be_cm_statementbox":
  1549. $items = array();
  1550. $dynContentCounter = 0;
  1551. while (1) {
  1552. $dynContentCounter++;
  1553. if (!isset($flex['text' . $dynContentCounter])) break;
  1554. if ($flex['text' . $dynContentCounter] === '' || $flex['name' . $dynContentCounter] === '') continue;
  1555. $item = array(
  1556. 'quote' => $flex['text' . $dynContentCounter],
  1557. 'cite' => $flex['name' . $dynContentCounter]
  1558. );
  1559. if ($flex['image' . $dynContentCounter] == 1) {
  1560. $imgs = $this->processImagesTTContent($dbReference, 'mrm_be_cm_statementbox', 'tt_content', 'flex_image_' . $dynContentCounter, 'uid', false);
  1561. $imgs = $imgs[0];
  1562. $imgs['src'] = "#cdnurl#/" . $imgs['sources']['img'];
  1563. unset($imgs['sources']);
  1564. $item['img'] = $imgs;
  1565. }
  1566. $items[] = $item;
  1567. }
  1568. $subs[] = $this->createContentElement('statementbox', array('items' => $items));
  1569. break;
  1570. case "mrm_be_cm_explorerbox":
  1571. $items = array();
  1572. $dynContentCounter = 0;
  1573. while (1) {
  1574. $dynContentCounter++;
  1575. if (!isset($flex['head' . $dynContentCounter])) break;
  1576. if ($flex['head' . $dynContentCounter] === '' || $flex['claim' . $dynContentCounter] === '' || $flex['image' . $dynContentCounter] == 0) continue;
  1577. $item = array(
  1578. 'heading' => $flex['head' . $dynContentCounter],
  1579. 'subheading' => $flex['claim' . $dynContentCounter],
  1580. 'text' => $flex['text' . $dynContentCounter]
  1581. );
  1582. if ($flex['image' . $dynContentCounter] == 1) {
  1583. $imgs = $this->processImagesTTContent($dbReference, 'mrm_be_cm_explorerbox', 'tt_content', 'flex_image_' . $dynContentCounter, 'uid', false);
  1584. $imgs = $imgs[0];
  1585. $imgs['src'] = "#cdnurl#/" . $imgs['sources']['img'];
  1586. unset($imgs['sources']);
  1587. $item['img'] = $imgs;
  1588. }
  1589. if ($flex['link' . $dynContentCounter] !== '') {
  1590. $button = $this->parseFlexFormLink($flex['link' . $dynContentCounter], $dbReference, $processedData);
  1591. $item['button'] = $button;
  1592. }
  1593. $items[] = $item;
  1594. }
  1595. $subs[] = $this->createContentElement('explorerbox', array('items' => $items));
  1596. break;
  1597. case "mrm_be_cm_dynamic_tileoverview":
  1598. $items = array();
  1599. foreach ($flex["dynamicComponents"] as $comp) {
  1600. foreach ($comp as $k => $v) {
  1601. $itm = null;
  1602. switch ($k) {
  1603. case "links":
  1604. $lnk = $this->parseFlexFormLink($v["link"], $dbReference, $processedData);
  1605. $itm = $this->createContentElement("tile_default", array("link" => $lnk, "coloured" => $v["coloured"] == 1, "allowed" => preg_split('/\+/', $v["type"]), "format" => $v["format"]));
  1606. if ($lnk["alt"]) $itm["props"]["headline"] = $lnk["alt"];
  1607. break;
  1608. case "buttons":
  1609. $itm = $this->createContentElement(
  1610. "tile_content",
  1611. array(
  1612. "headline" => $v["headline"],
  1613. "content" => $this->checkTextForInternalLinks($v["buttons"], $dbReference, $processedData)
  1614. )
  1615. );
  1616. break;
  1617. case "icons":
  1618. $lnk = $this->parseFlexFormLink($v["link"], $dbReference, $processedData);
  1619. $itm = $this->createContentElement("tile_icon", array("link" => $lnk, "icon" => $v["icon"]), array());
  1620. if ($lnk["alt"]) $itm["props"]["headline"] = $lnk["alt"];
  1621. break;
  1622. case "flat":
  1623. $lnk = $this->parseFlexFormLink($v["link"], $dbReference, $processedData);
  1624. $itm = $this->createContentElement("tile_flat", array("link" => $lnk));
  1625. if ($lnk["alt"]) $itm["props"]["headline"] = $lnk["alt"];
  1626. break;
  1627. case "injections":
  1628. $itm = $this->createContentElement("injection", array("type" => $v["text"]));
  1629. $processedData["injections"][] = $v["text"];
  1630. break;
  1631. }
  1632. if ($itm)
  1633. $items[] = $itm;
  1634. }
  1635. }
  1636. $dto = $this->createContentElement('dynamic_tileoverview', array(), array(), $items);
  1637. if ($flex["cssClass"] && $flex["cssClass"] !== "")
  1638. $dto["attributes"]["cssClassName"] = $flex["cssClass"];
  1639. $subs[] = $dto;
  1640. $processedData["status"]["hasDynamicTileOverview"] = true;
  1641. break;
  1642. case "mrm_be_cm_podcast":
  1643. //$items = array();
  1644. if ($flex['media'] == "1")
  1645. $media = $this->processAudio($dbReference, 'mrm_be_cm_podcast', 'tt_content', 'media', 'uid', true, true);
  1646. if ($flex['transcript'])
  1647. $transcript = $flex['transcript'];
  1648. $subs[] = $this->createContentElement('podcast', array(), array('media' => $media, 'transcript' => $transcript));
  1649. break;
  1650. case "mrm_be_cm_imageplus":
  1651. $props = $this->processImagesTTContent($dbReference)[0];
  1652. $props["type"] = "imageplus";
  1653. $props["headline"] = $flex['headline'] ?? '';
  1654. $props["description"] = $flex['description'] ?? '';
  1655. $props["link"] = $this->parseFlexFormLink($flex["link"], $dbReference, $processedData);
  1656. $props["customcss"] = $flex['customcss'] ?? '';
  1657. $subs[] = $this->createContentElement('imageplus', $props);
  1658. break;
  1659. case "mrm_be_cm_interviewfrage":
  1660. $props['lang'] = $flex['lang'] ?? '';
  1661. $subs[] = $this->createContentElement("interviewfrage", $props, array("question" => trim($flex['question'])));
  1662. break;
  1663. case "mrm_be_cm_interviewantwort":
  1664. $props['lang'] = $flex['lang'] ?? '';
  1665. $subs[] = $this->createContentElement("interviewantwort", $props, array("interviewee" => trim($flex['interviewee']),"answer" => trim($flex['answer'])));
  1666. break;
  1667. case "mrm_be_cm_foldout_h3":
  1668. $sub = $this->createContentElement("typo3_foldout_h3", array("open" => $flex["isInitialyOpen"] == "1", "noAutoOpen" => $flex["noAutoOpen"] == "1"), array("headline" => $flex["headline"]), array());
  1669. if ($flex["image"] == "1") {
  1670. $props = $this->processImagesTTContent($dbReference, "mrm_be_cm_contentimage")[0];
  1671. $props["type"] = "typo3_content";
  1672. $sub["subElements"][] = $this->createContentElement("image", $props);
  1673. } else {
  1674. switch ($flex["icon"]) {
  1675. case "1":
  1676. $sub["attributes"]["icon"] = "stadtinfo_basics";
  1677. break;
  1678. case "2":
  1679. $sub["attributes"]["icon"] = "geschichte";
  1680. break;
  1681. case "3":
  1682. $sub["attributes"]["icon"] = "kultur_freizeit";
  1683. break;
  1684. case "4":
  1685. $sub["attributes"]["icon"] = "besonderheiten";
  1686. break;
  1687. case "5":
  1688. $sub["attributes"]["icon"] = "kosten_geld";
  1689. break;
  1690. case "6":
  1691. $sub["attributes"]["icon"] = "hochschulen";
  1692. break;
  1693. case "7":
  1694. $sub["attributes"]["icon"] = "studieren";
  1695. break;
  1696. }
  1697. }
  1698. if ($flex["dynamicComponents"] && sizeof($flex["dynamicComponents"]) > 0)
  1699. foreach ($flex["dynamicComponents"] as $comp) {
  1700. $stype = array_keys($comp['settings'])[0];
  1701. $elements = $this->checkText($comp['settings'][$stype][$stype], $dbReference, $processedData, $stype == "paragraph" ? "typo3_paragraph" : ($stype == "headline" ? "h4" : $stype));
  1702. $sub["subElements"] = array_merge($sub["subElements"], $elements);
  1703. }
  1704. $subs[] = $sub;
  1705. break;
  1706. case "mrm_be_cm_quiz_direct":
  1707. //print_r($flex); die();
  1708. $s = $this->createContentElement(
  1709. "quizdirect",
  1710. array(
  1711. "labels" => array(
  1712. "startbutton" => $flex["startbuttontext"],
  1713. "submitbutton" => $flex["submitbuttontext"],
  1714. "nextbutton" => $flex["nextbuttontext"],
  1715. "lastbutton" => $flex["lastbuttontext"],
  1716. "question" => $flex["question"],
  1717. "repeatbutton" => $flex["repeatbuttontext"],
  1718. "qsuccess" => $flex["questionsuccesstext"],
  1719. "qfail" => $flex["questionfailtext"],
  1720. ),
  1721. "resultscreen" => array(
  1722. "headingTop" => $flex["resultheadingtop"],
  1723. "headingSub" => $flex["resultheadingsub"],
  1724. "validation" => $flex["validationstr"],
  1725. "end" => $flex["thanks"]
  1726. ),
  1727. "isRestartAble" => $flex["isRestartAble"] == 1 || $flex["isRestartAble"] == "1",
  1728. ),
  1729. array(
  1730. "items" => array_values(array_map(function ($v) {
  1731. $questionType = null;
  1732. $quest = $v['settings']['question'];
  1733. if (!isset($quest)) {
  1734. $quest = $v['settings']['question_multi'];
  1735. $questionType = "multi";
  1736. }
  1737. if (isset($quest["additional_text"]) && $quest["additional_text"] != "") {
  1738. $quest["text"] = $quest["text"] . " (" . $quest["additional_text"] . ")";
  1739. unset($quest["additional_text"]);
  1740. }
  1741. if ($questionType) $quest["type"] = $questionType;
  1742. unset($quest["rightanswer"]);
  1743. if(isset($quest['solutionText'])) $solution = $quest['solutionText'];
  1744. unset($quest['solutionText']);
  1745. $i = 0;
  1746. $quest["answers"] = array();
  1747. while (1) {
  1748. $i++;
  1749. if (!isset($quest["answertext" . $i])) break;
  1750. if ($quest["answertext" . $i] === "") continue;
  1751. $quest["answers"][] = array("text" => $quest["answertext" . $i], "points" => (int)$quest["answerpoints" . $i]);
  1752. unset($quest["answertext" . $i]);
  1753. unset($quest["answerpoints" . $i]);
  1754. }
  1755. $quest["solution"] = $solution;
  1756. return $quest;
  1757. }, $flex["dynamicComponents"])),
  1758. "validation" => array(
  1759. "maxPoints" => (int)$flex["maxpoints"],
  1760. "averagePoints" => $this->createContentElement("injection", array("type" => "quiz-averagePoints")),
  1761. "alreadyReachedPoints" => $this->createContentElement("injection", array("type" => "quiz-alreadyReachedPoints")),
  1762. "items" => ($flex["dynamicComponents2"] == 0) ? [] : array_map(
  1763. function ($i) {
  1764. if(empty($i["validationText"])) $i["validationText"] = "";
  1765. else $i["validationText"] = $this->checkTextForInternalLinks($i["validationText"], $dbReference, $processedData);
  1766. return $i;
  1767. },
  1768. array_filter(array_values(array_map(function ($v) {
  1769. return $v['settings']['validation'];
  1770. }, $flex["dynamicComponents2"])), function ($x) {
  1771. return $x != null;
  1772. })
  1773. ),
  1774. ),
  1775. )
  1776. );
  1777. $processedData["injections"][] = "quiz-averagePoints";
  1778. $processedData["injections"][] = "quiz-alreadyReachedPoints";
  1779. $subs[] = $s;
  1780. $processedData["status"]["hasQuiz"] = true;
  1781. break;
  1782. default:
  1783. $this->log("MISSING PROCESSDATA 4 " . $dbReference['CType']);
  1784. $this->log($flex, false);
  1785. break;
  1786. }
  1787. }
  1788. private function checkText($txt, $dbReference, &$processedData, $defaultElementType = "typo3_paragraph")
  1789. {
  1790. $txt = $this->checkTextForInternalLinks($txt, $dbReference, $processedData);
  1791. $txt = $this->refactorTextElements($txt, $defaultElementType);
  1792. return $txt;
  1793. }
  1794. private function refactorTextElements($txt, $defaultElementType)
  1795. {
  1796. if (strpos($txt, "<table") === FALSE) return [$this->createContentElement($defaultElementType, array(), array("text" => $txt))];
  1797. $elements = [];
  1798. while (($tablepos = strpos($txt, "<table")) !== FALSE) {
  1799. if ($tablepos != 0) {
  1800. //$this->log(trim(substr($txt, 0, $tablepos)));
  1801. $elements[] = $this->createContentElement($defaultElementType, array(), array("text" => trim(substr($txt, 0, $tablepos))));
  1802. $txt = substr($txt, $tablepos);
  1803. }
  1804. $tablepos = strpos($txt, "</table>") + 8;
  1805. $dom = new \DOMDocument();
  1806. @$dom->loadHTML('<?xml encoding="utf-8" ?><div id="sexy">' . trim(substr($txt, 0, $tablepos)) . '</div>', LIBXML_HTML_NOIMPLIED | LIBXML_HTML_NODEFDTD);
  1807. $tab = $this->createContentElement("table", array("rows" => array(), "columnCount" => 0));
  1808. foreach ($dom->getElementsByTagName('tr') as $tr) {
  1809. $par = $tr->parentNode;
  1810. $row = [];
  1811. if ($tab["props"]["columnCount"] == 0) {
  1812. foreach ($tr->childNodes as $e) {
  1813. if ($e->tagName == "td" || $e->tagName == "th") {
  1814. $tab["props"]["columnCount"]++;
  1815. }
  1816. }
  1817. }
  1818. foreach ($tr->childNodes as $e) {
  1819. if ($e->tagName != "td" && $e->tagName != "th") continue;
  1820. $innerHTML = '';
  1821. foreach ($e->childNodes as $n) $innerHTML .= $dom->saveHtml($n);
  1822. $row[] = array(
  1823. "html" => "<p>" . $innerHTML . "</p>",
  1824. "isHeader" => $par->tagName == "thead",
  1825. "isRowHeader" => $e->tagName == "th" && $par->tagName != "thead",
  1826. );
  1827. }
  1828. $tab["props"]["rows"][] = $row;
  1829. }
  1830. $elements[] = $tab;
  1831. $txt = substr($txt, $tablepos);
  1832. }
  1833. $txt = trim($txt);
  1834. if ($txt != "")
  1835. $elements[] = $this->createContentElement($defaultElementType, array(), array("text" => $txt));
  1836. return $elements;
  1837. }
  1838. private function checkTextForInternalLinks($txt, $dbReference, &$processedData)
  1839. {
  1840. $dom = new \DOMDocument();
  1841. @$dom->loadHTML('<?xml encoding="utf-8" ?><div id="sexy">' . $txt . '</div>', LIBXML_HTML_NOIMPLIED | LIBXML_HTML_NODEFDTD);
  1842. foreach ($dom->getElementsByTagName('a') as $link) {
  1843. $emptyHref = false;
  1844. $title = null;
  1845. $alt = null;
  1846. $href = null;
  1847. for ($i = 0; $i < $link->attributes->length; ++$i) {
  1848. $node = $link->attributes->item($i);
  1849. if ($node->nodeName == "href" && strpos($node->nodeValue, 'smartadserver.com') === FALSE) {
  1850. $nv = $node->nodeValue;
  1851. $nv = str_replace('&amp;', '&', $nv);
  1852. $href = $this->replaceT3Link($nv, $dbReference, $processedData);
  1853. $node->nodeValue = htmlspecialchars($href);
  1854. if ($node->nodeValue == '') $emptyHref = true;
  1855. }
  1856. if ($node->nodeName == "title" && $node->nodeValue != '') $title = $node->nodeValue;
  1857. if ($node->nodeName == "alt" && $node->nodeValue != '') $alt = $node->nodeValue;
  1858. }
  1859. if ($emptyHref) $link->removeAttribute('href');
  1860. else {
  1861. if (!$alt) {
  1862. //check for pdf files (AS-337)
  1863. if (strtolower(pathinfo($href, PATHINFO_EXTENSION)) == "pdf") {
  1864. $alt = "PDF-Download (öffnet sich in neuem Fenster)";
  1865. $link->setAttribute('target', '_blank');
  1866. $link->setAttribute('alt', $alt);
  1867. }
  1868. }
  1869. }
  1870. if ($title && !$alt) $link->setAttribute('alt', $title);
  1871. if ($title) $link->removeAttribute('title');
  1872. }
  1873. $txt = $dom->saveHTML($dom->getElementById('sexy'));
  1874. $txt = str_replace('<div id="sexy">', '', $txt);
  1875. $txt = substr($txt, 0, -6);
  1876. return trim($txt);
  1877. }
  1878. private function parseFlexFormLink($link, $dbReference, &$processedData)
  1879. {
  1880. $link = implode("/", explode("\/", $link));
  1881. [$href, $target, $css] = explode(" ", $link);
  1882. $alt = substr($link, strlen($href . $target . $css) + 3);
  1883. $alt = preg_replace('/&quot;/', '', trim($alt, " \""));
  1884. if ($href == "-") return null;
  1885. $href = $this->replaceT3Link($href, $dbReference, $processedData, true);
  1886. $ret = array("href" => $href);
  1887. if (!$target || $target == "-") $ret["target"] = "_top";
  1888. else $ret["target"] = $target;
  1889. if ($alt && $alt != "-") $ret["alt"] = $alt;
  1890. return $ret;
  1891. }
  1892. private function replaceT3Link($link, $dbReference, &$processedData, $addToLinkedPosts = false)
  1893. {
  1894. $uid = $this->parseUIDFromT3Url($link);
  1895. if (!$uid || $uid == '') return $link;
  1896. if (strpos($link, 't3://page?') !== false) {
  1897. if ($uid == "current") {
  1898. $link = str_replace('t3://page?uid=current', '', $link);
  1899. } else {
  1900. if ($addToLinkedPosts) {
  1901. $processedData['linkedPosts'][] = (int)$uid;
  1902. $link = "#linkedPost#" . $uid . "#/linkedPost#";
  1903. } else {
  1904. $pageStatement = $this->pageQueryBuilder
  1905. ->select('*')
  1906. ->from('pages')
  1907. ->setMaxResults(1)
  1908. ->where(
  1909. $this->pageQueryBuilder->expr()->eq('uid', $this->pageQueryBuilder->createNamedParameter($uid))
  1910. )
  1911. ->execute();
  1912. $post = $pageStatement->fetchAll();
  1913. $post = $post[0];
  1914. $link = $post['slug'];
  1915. }
  1916. }
  1917. }
  1918. if (strpos($link, 't3://file?') !== false)
  1919. $link = $this->setStaticFile($dbReference, $uid);
  1920. return $link;
  1921. }
  1922. private function setStaticFile($dbReference, $uid, $publicUrl = null)
  1923. {
  1924. $fnNameRef = $dbReference['pid'] . "|" . $dbReference['uid'] . "|" . $dbReference['CType'] . "|file|" . $uid;
  1925. if (!$publicUrl) {
  1926. $file = $this->resourceFactory->getFileObject($uid);
  1927. $publicUrl = $file->getPublicUrl();
  1928. }
  1929. try {
  1930. $fnName = basename($publicUrl);
  1931. $fnName = explode(".", $fnName);
  1932. $extension = array_pop($fnName);
  1933. $fnName = implode(".", $fnName);
  1934. } catch (Exception $e) {
  1935. $fnName = null;
  1936. }
  1937. return "#cdnurl#/" . $this->copyAndRenameFile($fnNameRef, "/" . $publicUrl, $fnName);
  1938. }
  1939. private function parseUIDFromT3Url($t3url)
  1940. {
  1941. $uid = null;
  1942. if ($t3url && $t3url != '' && substr($t3url, 0, 2) == "t3")
  1943. try {
  1944. parse_str(parse_url($t3url)['query'], $query);
  1945. $uid = $query['uid'];
  1946. } catch (Exception $e) {
  1947. }
  1948. return $uid;
  1949. }
  1950. private function createContentElement($type, $props = null, $attributes = null, $subElements = null)
  1951. {
  1952. if (is_null($props)) $props = array();
  1953. if (is_null($attributes)) $attributes = (object) array();
  1954. $props["__hbs_uid"] = '_ab' . mt_rand(0, 0xffffff) . '_' . mt_rand(0, 0xffffff);
  1955. $ele = array(
  1956. 'type' => $type,
  1957. 'props' => $props,
  1958. 'attributes' => $attributes,
  1959. );
  1960. if (!is_null($subElements)) $ele['subElements'] = $subElements;
  1961. else $ele['subElements'] = [];
  1962. return $ele;
  1963. }
  1964. private function processVideo($dbReference)
  1965. {
  1966. $data = $this->resourceFactory->convertFlexFormDataToConfigurationArray($dbReference['pi_flexform']);
  1967. $vids = array();
  1968. foreach ($data['settings']['video'] as $value) {
  1969. if ($value['posterConfiguration'] && $value['posterConfiguration'] != '') $vids['poster'] = $value['posterConfiguration']['image'];
  1970. if ($value['mp4Configuration'] && $value['mp4Configuration'] != '') $vids['mp4'] = $value['mp4Configuration']['video'];
  1971. if ($value['ogvConfiguration'] && $value['ogvConfiguration'] != '') $vids['ogv'] = $value['ogvConfiguration']['video'];
  1972. if ($value['webmConfiguration'] && $value['webmConfiguration'] != '') $vids['webm'] = $value['webmConfiguration']['video'];
  1973. if ($value['threegpConfiguration'] && $value['threegpConfiguration'] != '') $vids['3gp'] = $value['threegpConfiguration']['video'];
  1974. }
  1975. foreach ($vids as $key => &$value) {
  1976. $value = "/" . $value;
  1977. $fnNameRef = $dbReference['pid'] . "|" . $dbReference['uid'] . "|" . $dbReference['CType'] . "|" . $key;
  1978. $value = $this->copyAndRenameFile($fnNameRef, $value);
  1979. }
  1980. return $vids;
  1981. }
  1982. private function processImagesTTContent($dbReference, $ctypeOverride = '', $table = 'tt_content', $tableColumn = 'image', $refField = 'uid', $useRelationFetch = true, $addCDNPrefix = false)
  1983. {
  1984. if ($useRelationFetch)
  1985. $fileObjects = $this->fileRepository->findByRelation($table, $tableColumn, $dbReference[$refField]);
  1986. else {
  1987. $sysfilerefQueryBuilder = $this->connection->getQueryBuilderForTable('sys_file_reference');
  1988. $sysfileStatement = $sysfilerefQueryBuilder
  1989. ->select('uid')
  1990. ->from('sys_file_reference')
  1991. ->andWhere(
  1992. $sysfilerefQueryBuilder->expr()->eq('uid_foreign', intval($dbReference[$refField])),
  1993. $sysfilerefQueryBuilder->expr()->eq('tablenames', $sysfilerefQueryBuilder->createNamedParameter($table)),
  1994. $sysfilerefQueryBuilder->expr()->eq('fieldname', $sysfilerefQueryBuilder->createNamedParameter($tableColumn)),
  1995. )
  1996. ->execute();
  1997. $frows = $sysfileStatement->fetchAll();
  1998. foreach ($frows as $fileuid) {
  1999. $fileObjects[] = $this->fileRepository->findFileReferenceByUid(intval($fileuid['uid']));
  2000. }
  2001. }
  2002. $processedImages = array();
  2003. $ctypeOverride = $ctypeOverride != '' ? $ctypeOverride : $dbReference['CType'];
  2004. foreach ($fileObjects as $key => $value) {
  2005. $img = array(
  2006. 'reference' => $value->getReferenceProperties(),
  2007. 'original' => $value->getOriginalFile()->getProperties(),
  2008. );
  2009. $imgfn = rtrim($img['original']['identifier'], "/");
  2010. $image = $this->imageService->getImage('fileadmin/' . $imgfn, null, false);
  2011. $cropvariantcollection = \TYPO3\CMS\Core\Imaging\ImageManipulation\CropVariantCollection::create($img['reference']['crop']);
  2012. $cropareas = $this->imageSizes[$ctypeOverride];
  2013. $processArray = array(
  2014. 'sources' => array()
  2015. );
  2016. $alt = $img['reference']['alternative'] != NULL ? $img['reference']['alternative'] : ($img['original']['alternative'] != NULL ? $img['original']['alternative'] : NULL);
  2017. $title = $img['reference']['title'] != NULL ? $img['reference']['title'] : ($img['original']['title'] != NULL ? $img['original']['title'] : NULL);
  2018. $caption = $img['reference']['description'] != NULL ? $img['reference']['description'] : ($img['original']['description'] != NULL ? $img['original']['description'] : NULL);
  2019. $copyright = $img['reference']['copyright'] != NULL ? $img['reference']['copyright'] : ($img['original']['copyright'] != NULL ? $img['original']['copyright'] : NULL);
  2020. if ($alt != NULL) $processArray['alt'] = $alt;
  2021. if ($title != NULL) $processArray['title'] = $title;
  2022. if ($caption != NULL) $processArray['caption'] = $caption;
  2023. if ($copyright != NULL) $processArray['copyright'] = $copyright;
  2024. if ($cropareas['passthru']) {
  2025. if (is_array($cropareas['passthru'])) {
  2026. foreach ($cropareas['passthru'] as $sizename => $size) {
  2027. $processingInstructions = array(
  2028. 'width' => $size['width'],
  2029. 'minWidth' => $size['width'],
  2030. 'maxWidth' => $size['width'],
  2031. 'crop' => null
  2032. );
  2033. if ($size['height']) {
  2034. $processingInstructions = array_merge(
  2035. $processingInstructions,
  2036. array(
  2037. 'height' => $size['height'],
  2038. 'minHeight' => $size['height'],
  2039. 'maxHeight' => $size['height']
  2040. )
  2041. );
  2042. }
  2043. if ($size['maxHeight'])
  2044. $processingInstructions['maxHeight'] = $size['maxHeight'];
  2045. if ($size['minHeight'])
  2046. $processingInstructions['minHeight'] = $size['minHeight'];
  2047. $processedImage = $this->imageService->applyProcessingInstructions($image, $processingInstructions);
  2048. $imageUri = $this->imageService->getImageUri($processedImage);
  2049. $fnNameRef = $dbReference['pid'] . "|" . $dbReference['uid'] . "|" . $ctypeOverride . "|" . $img['reference']['uid'] . "|passthru|" . $sizename;
  2050. $processArray['sources'][$sizename] = $this->copyAndRenameFile($fnNameRef, $imageUri, $processArray['alt']);
  2051. }
  2052. } else {
  2053. $fnNameRef = $dbReference['pid'] . "|" . $dbReference['uid'] . "|" . $ctypeOverride . "|" . $img['reference']['uid'] . "|passthru";
  2054. $imageUri = $this->imageService->getImageUri($image);
  2055. $processArray['sources']['passthru'] = ($addCDNPrefix ? "#cdnurl#/" : "") . $this->copyAndRenameFile($fnNameRef, $imageUri, $processArray['alt']);
  2056. }
  2057. } else
  2058. foreach ($cropareas as $cropareaname => $sizes) {
  2059. $croparea = $cropvariantcollection->getCropArea($cropareaname);
  2060. foreach ($sizes as $sizename => $size) {
  2061. if ($dbReference["doktype"] && $size['allowed_doktypes'] && !in_array($dbReference["doktype"], $size['allowed_doktypes'])) continue;
  2062. $processingInstructions = array(
  2063. 'width' => $size['width'],
  2064. 'minWidth' => $size['width'],
  2065. 'maxWidth' => $size['width'],
  2066. 'crop' => $croparea->isEmpty() ? null : $croparea->makeAbsoluteBasedOnFile($image)
  2067. );
  2068. if ($size['height']) {
  2069. $processingInstructions = array_merge(
  2070. $processingInstructions,
  2071. array(
  2072. 'height' => $size['height'],
  2073. 'minHeight' => $size['height'],
  2074. 'maxHeight' => $size['height']
  2075. )
  2076. );
  2077. }
  2078. if ($size['maxHeight'])
  2079. $processingInstructions['maxHeight'] = $size['maxHeight'];
  2080. if ($size['minHeight'])
  2081. $processingInstructions['minHeight'] = $size['minHeight'];
  2082. $processedImage = $this->imageService->applyProcessingInstructions($image, $processingInstructions);
  2083. $imageUri = $this->imageService->getImageUri($processedImage);
  2084. $fnNameRef = $dbReference['pid'] . "|" . $dbReference['uid'] . "|" . $ctypeOverride . "|" . $img['reference']['uid'] . "|" . $cropareaname . "|" . $sizename;
  2085. $processArray['sources'][$sizename] = ($addCDNPrefix ? "#cdnurl#/" : "") . $this->copyAndRenameFile($fnNameRef, $imageUri, $processArray['alt']);
  2086. }
  2087. }
  2088. $processedImages[] = $processArray;
  2089. }
  2090. return $processedImages;
  2091. }
  2092. private function processAudio($dbReference, $ctypeOverride = '', $table = 'tt_content', $tableColumn = 'media', $refField = 'uid', $useRelationFetch = true, $copyToCDN = false)
  2093. {
  2094. if ($useRelationFetch)
  2095. $fileObjects = $this->fileRepository->findByRelation($table, $tableColumn, $dbReference[$refField]);
  2096. else {
  2097. $sysfilerefQueryBuilder = $this->connection->getQueryBuilderForTable('sys_file_reference');
  2098. $sysfileStatement = $sysfilerefQueryBuilder
  2099. ->select('uid')
  2100. ->from('sys_file_reference')
  2101. ->andWhere(
  2102. $sysfilerefQueryBuilder->expr()->eq('uid_foreign', intval($dbReference[$refField])),
  2103. $sysfilerefQueryBuilder->expr()->eq('tablenames', $sysfilerefQueryBuilder->createNamedParameter($table)),
  2104. $sysfilerefQueryBuilder->expr()->eq('fieldname', $sysfilerefQueryBuilder->createNamedParameter($tableColumn)),
  2105. )
  2106. ->execute();
  2107. $frows = $sysfileStatement->fetchAll();
  2108. foreach ($frows as $fileuid) {
  2109. $fileObjects[] = $this->fileRepository->findFileReferenceByUid(intval($fileuid['uid']));
  2110. }
  2111. }
  2112. $processedAudio = array();
  2113. $audio = [];
  2114. $ctypeOverride = $ctypeOverride != '' ? $ctypeOverride : $dbReference['CType'];
  2115. foreach ($fileObjects as $key => $value) {
  2116. $processedAudio = array(
  2117. 'reference' => $value->getReferenceProperties(),
  2118. 'original' => $value->getOriginalFile()->getProperties(),
  2119. );
  2120. if ($copyToCDN) {
  2121. $oringalFile = $processedAudio['original']['identifier'];
  2122. $extension = pathinfo($processedAudio['original']['identifier'], PATHINFO_EXTENSION);
  2123. $targetFile = substr(sha1($processedAudio['original']['identifier']), 0, 5) . '_podcast.' . $extension;
  2124. $oringalFile = '/fileadmin' . $oringalFile;
  2125. $url = $this->copyPodcastAudioFileToCDN($oringalFile, $targetFile);
  2126. }
  2127. $audio['name'] = $processedAudio['original']['name'];
  2128. $audio['url'] = $url;
  2129. $audio['title'] = $processedAudio['reference']['title'];
  2130. $audio['description'] = $processedAudio['reference']['description'];
  2131. }
  2132. return $audio;
  2133. }
  2134. private function copyAndRenameFile($destinationFnRef, $sourceUri, $altText = null)
  2135. {
  2136. $shaFileRef = sha1($destinationFnRef);
  2137. $workPath = substr($shaFileRef, 0, 2) . "/" . substr($shaFileRef, 2, 2);
  2138. $workFnPrefix = $shaFileRef;
  2139. if ($altText) {
  2140. $altText = substr($altText, 0, 100);
  2141. $workFnPrefix = $this->sanitizeString($altText) . "-" . $shaFileRef;
  2142. }
  2143. $workFn = $workFnPrefix . "." . pathinfo($sourceUri, PATHINFO_EXTENSION);
  2144. if (!file_exists(\TYPO3\CMS\Core\Core\Environment::getPublicPath() . '/cdn/' . $workPath)) {
  2145. mkdir(\TYPO3\CMS\Core\Core\Environment::getPublicPath() . '/cdn/' . $workPath, 0777, true);
  2146. }
  2147. copy(\TYPO3\CMS\Core\Core\Environment::getPublicPath() . $sourceUri, \TYPO3\CMS\Core\Core\Environment::getPublicPath() . '/cdn/' . $workPath . '/' . $workFn);
  2148. return $workPath . '/' . $workFn;
  2149. }
  2150. private function copyPodcastAudioFileToCDN($sourceFile, $destinationFile)
  2151. {
  2152. $dir = 'podcast';
  2153. if (!file_exists(\TYPO3\CMS\Core\Core\Environment::getPublicPath() . '/cdn/' . $dir)) {
  2154. mkdir(\TYPO3\CMS\Core\Core\Environment::getPublicPath() . '/cdn/' . $dir, 0777, true);
  2155. }
  2156. copy(\TYPO3\CMS\Core\Core\Environment::getPublicPath() . $sourceFile, \TYPO3\CMS\Core\Core\Environment::getPublicPath() . '/cdn/' . $dir . '/' . $destinationFile);
  2157. return '#cdnurl#/' . $dir . '/' . $destinationFile;
  2158. }
  2159. public function processCmdmap_deleteAction($table, $id, $recordToDelete, $recordWasDeleted = NULL, \TYPO3\CMS\Core\DataHandling\DataHandler &$pObj)
  2160. {
  2161. //$this->log('processCmdmap_deleteAction');
  2162. if ($table == "pages") {
  2163. Mongoer::sendRequest("pages", "delete", array("pageuid" => $id));
  2164. Mongoer::sendRequest("abialtcache", "delete", array("pageuid" => $pid));
  2165. Mongoer::sendRequest("search", "delete", array("pageuid" => $id));
  2166. Mongoer::sendRequest("security", "delete", array("pageuid" => $id));
  2167. Mongoer::sendRequest("previews", "delete", array("pageuid" => $id));
  2168. }
  2169. }
  2170. /* PRIVATES */
  2171. private function log($msg, $isString = true)
  2172. {
  2173. if (!$isString) {
  2174. $msg = json_encode($msg, JSON_PRETTY_PRINT);
  2175. }
  2176. file_put_contents('/var/www/html/public/typo3temp/debug.log', $msg . PHP_EOL, FILE_APPEND);
  2177. }
  2178. }