mostly filebased Content Presentation System
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

elementdispatcher.php 23KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583
  1. <?php
  2. namespace Modules;
  3. class ElementDispatcher {
  4. private $folder = "";
  5. private $config = [];
  6. public $structs = null;
  7. public $content = null;
  8. public $domains = null;
  9. function __construct($folder = "",$config = [],$structs=false,$content=false,$domains=false) {
  10. if (is_string($folder)) {
  11. $this->folder = $folder;
  12. }
  13. if (is_array($config)) {
  14. $this->config = $config;
  15. }
  16. $this->structs = &$structs;
  17. $this->content = &$content;
  18. $this->domains = &$domains;
  19. }
  20. function dispatch($string) {
  21. // find occorances of {| keyword |}
  22. $pattern = "/\{\|(.+?)\|\}/s";
  23. $f = preg_match_all($pattern, $string,$matches,PREG_PATTERN_ORDER);
  24. for ($i=0;$i<$f;$i++) {
  25. $body = preg_split("/\R/",trim($matches[1][$i]));
  26. $request = explode(":", trim(array_shift($body)));
  27. $new = $this->content_element($request,$body);
  28. $string = str_replace($matches[0][$i],$new,$string);
  29. }
  30. return $string;
  31. }
  32. function content_element($request = [], $body = null) {
  33. $f3 = \Base::instance();
  34. $md = new \freaParsedown();
  35. $md->deactivate_ol();
  36. $new = "";
  37. switch($request[0]) {
  38. case 'test':
  39. $new="seems to work";
  40. break;
  41. case ';':
  42. $new="";
  43. break;
  44. case 'path':
  45. $new="/".$this->folder;
  46. break;
  47. case 'space':
  48. $new=sprintf("<div style=\"height:%s;\"></div>",
  49. $request[1]
  50. );
  51. break;
  52. case 'span':
  53. $new=sprintf("<span class=\"%s\">%s</span>",
  54. $request[1],
  55. $request[2] ? : implode("\n",$body)
  56. );
  57. break;
  58. case 'small-text':
  59. if(count($body)) {
  60. $new=sprintf("<div class=\"smalltext\">%s</div>",
  61. $md->text(implode("\n",$body))
  62. );
  63. } else {
  64. $new=sprintf("<span class=\"smalltext\">%s</span>",
  65. $request[1]
  66. );
  67. }
  68. break;
  69. case 'CE':
  70. switch($request[1]) {
  71. case 'publication':
  72. $CE = new \Modules\CPublication($this->config,['path'=>$this->folder]);
  73. if(count($request)>2) {
  74. $CE->set_layout($request[2]);
  75. }
  76. $new = $CE;
  77. break;
  78. }
  79. break;
  80. case 'TOC':
  81. // throw away TOC part of request, we don't need it
  82. array_shift($request);
  83. $toc = new \Modules\TOC($request,$this->folder,$body);
  84. $toc->dispatch();
  85. $new=sprintf("<div class=\"TOC %s\">%s</div>",
  86. array_shift($request),
  87. $toc);
  88. break;
  89. case 'sql':
  90. //array_shift($request);
  91. switch ($request[1]) {
  92. case 'sqlite':
  93. $array = [];
  94. $db = new \DB\SQL('sqlite:' . $this->folder . $request[2]);
  95. $sql = implode(" ", $body);
  96. if ( strpos($sql,'insert')===false &&
  97. strpos($sql,'update')===false &&
  98. strpos($sql,'drop')===false) {
  99. $rows = $db->exec($sql);
  100. foreach ($rows as $res) {
  101. switch (count($res)) {
  102. case 1:
  103. $keys=array_keys($res);
  104. $array[] = $res[$keys[0]];
  105. break;
  106. case 2:
  107. $keys=array_keys($res);
  108. $array[$res[$keys[0]]] = $res[$keys[1]];
  109. break;
  110. }
  111. }
  112. }
  113. $new = sprintf("<ul><li>%s</li></ul>",
  114. implode("</li><li>",$array));
  115. unset($array);
  116. break;
  117. }
  118. break;
  119. case 'form':
  120. $token_db = $f3->get('TEMP') . "CEform/";
  121. $form_config_file = sprintf("%s%s.cfg",
  122. ROOT.$this->folder,
  123. $request[1]);
  124. $db = new \DB\Jig($token_db,\DB\Jig::FORMAT_JSON);
  125. $formcall = new \DB\Jig\Mapper($db,'form_calls');
  126. $timestamp = time();
  127. $token = md5($timestamp . $form_config_file . rand(100,999));
  128. $f3->config($form_config_file);
  129. $fields = $f3->get('fields');
  130. foreach ($fields as $k => $v) {
  131. if ($v['type'] == 'custom') {
  132. $fields[$k]['template'] = sprintf(
  133. "%s%s",
  134. substr($this->folder,strlen($f3->get('CONTENT_BASE'))),
  135. $v['template']
  136. );
  137. }
  138. if (array_key_exists('db',$v)) {
  139. switch ($v['db']['type']) {
  140. case 'sqlite':
  141. $array = [];
  142. $db = new \DB\SQL('sqlite:' . $this->folder . $v['db']['file']);
  143. $sql = $v['db']['sql'];
  144. if ( strpos($sql,'insert')===false &&
  145. strpos($sql,'update')===false &&
  146. strpos($sql,'drop')===false) {
  147. $rows = $db->exec($sql);
  148. foreach ($rows as $res) {
  149. switch (count($res)) {
  150. case 2:
  151. $keys=array_keys($res);
  152. $array[$res[$keys[0]]] = $res[$keys[1]];
  153. break;
  154. }
  155. }
  156. }
  157. $fields[$k]['el'] = $array;
  158. unset($array);
  159. break;
  160. }
  161. }
  162. }
  163. $f3->set('fields',
  164. array_merge(
  165. $fields,
  166. ['xss-token'=>[
  167. 'type'=>'hidden',
  168. 'value'=>$token,
  169. 'length'=>strlen($token)
  170. ]]
  171. ));
  172. $formcall->token = $token;
  173. $formcall->timestamp = $timestamp;
  174. $formcall->form = $form_config_file;
  175. $formcall->path = ROOT.$this->folder;
  176. $formcall->save();
  177. $form_view = new \Template;
  178. $new=$form_view->render('form.htm');
  179. break;
  180. case 'box':
  181. array_shift($request); //get rid of identifier
  182. $type = array_shift($request);
  183. $pics = explode(":",array_shift($body));
  184. $pic = $pics[0];
  185. $pic_hover = count($pics) > 1 ? $pics[1] : $pic;
  186. if (count($body) >= 3) {
  187. $caption = ['normal'=>['cap1' => array_shift($body),
  188. 'cap2' => array_shift($body)],
  189. 'hover'=> ['cap1' => array_shift($body),
  190. 'cap2' => array_shift($body)]];
  191. $caption_html=[];
  192. foreach ($caption as $state => $set) {
  193. if(!$set['cap2']) {
  194. $caption_html[$state] = [
  195. sprintf('<span class="first">&nbsp;</span>'),
  196. sprintf('<span class="first">%s</span>',$set['cap1'])
  197. ];
  198. } else if (!$set['cap1'] && $set['cap2']) {
  199. $caption_html[$state] = [
  200. sprintf('<span class="second">%s</span>',$set['cap2'])
  201. ];
  202. } else {
  203. $caption_html[$state] = [
  204. sprintf('<span class="first">%s</span>',$set['cap1']?:"&nbsp;"),
  205. sprintf('<span class="second">%s</span>',$set['cap2'])
  206. ];
  207. }
  208. }
  209. $has_caption = TRUE;
  210. } else {
  211. $has_caption = FALSE;
  212. }
  213. if (file_exists($this->folder.$pic)) {
  214. $pic = $this->folder.$pic;
  215. } else {
  216. $pic = $f3->get('RESOURCES')."img/default_img.png";
  217. }
  218. if (file_exists($this->folder.$pic_hover)) {
  219. $pic_hover = $this->folder.$pic_hover;
  220. } else {
  221. $pic_hover = $pic;
  222. }
  223. if(0) {
  224. $PIC = new \Image($pic);
  225. $orientation = $PIC->width() > $PIC->height()
  226. ? 'landscape'
  227. : 'portrait'
  228. ;
  229. unset($PIC);
  230. } else {
  231. list($wwidth, $hheight) = getimagesize($pic);
  232. $orientation = $wwidth > $hheight ? 'landscape' : 'portrait';
  233. }
  234. $pic = new CachedImage($pic);
  235. $pic_hover = new CachedImage($pic_hover);
  236. $class="";
  237. $add="";
  238. switch($type) {
  239. case 'plain':
  240. $link=false;
  241. break;
  242. case 'download':
  243. $file = "/".$this->folder.implode(":",$request);
  244. $link='href="'.$file.'" download ';
  245. break;
  246. case 'lightbox':
  247. $body = implode("\n",$body);
  248. if (count($request) % 2) {
  249. $class = array_pop($request);
  250. }
  251. if (count($request) >= 2) {
  252. $body=str_replace([$request[0],$request[1]],["{|","|}"],$body);
  253. $body=$this->dispatch($body);
  254. }
  255. $hash=md5($body);
  256. $add=sprintf("<div id=\"%s\" class=\"content_elment_box_body\">\n%s\n</div>",
  257. $hash,
  258. $md->text($body));
  259. $link='href="#" data-featherlight="#'.$hash.'" ';
  260. break;
  261. case 'internal':
  262. $dest=implode(":",$request);
  263. $data = [];
  264. $base = substr($dest,0,strpos($dest,'?') ? : strlen($dest));
  265. parse_str(parse_url($dest,PHP_URL_QUERY),$data);
  266. $fragment = parse_url($dest,PHP_URL_FRAGMENT);
  267. if ($f3->get('LANG') != $f3->get('default_lang')) {
  268. if (!array_key_exists('lang',$data)) {
  269. $data['lang'] = $f3->get('LANG');
  270. }
  271. }
  272. $new_dest = $base;
  273. if (count($data) > 0) {
  274. $new_dest .= "?" . http_build_query($data);
  275. }
  276. if ($fragment) {
  277. $new_dest .= "#" . $fragment;
  278. }
  279. //if ($f3->get('LANG') != $f3->get('default_lang')) {
  280. // $dest .= "?lang=".$f3->get('LANG');
  281. //}
  282. $link=sprintf('href="%s" ',$f3->get('SITE_URL')."/".$new_dest);
  283. break;
  284. case 'external':
  285. $dest=implode(":",$request);
  286. $target = $f3->get('external_links_open_in_new_window')
  287. ? 'target="_blank"'
  288. : ''
  289. ;
  290. $link=sprintf('href="%s" %s',$dest, $target);
  291. break;
  292. default:
  293. $link='href="#"';
  294. break;
  295. }
  296. $new=sprintf("<div class=\"brick %s\">\n<a class=\"content_element_box\" %s>\n<div class=\"content_element_box\">
  297. <div class=\"image\">
  298. <img class=\"standard\" src=\"%s\" /><img class=\"hover\" src=\"%s\" />
  299. </div>
  300. %s
  301. %s
  302. \n</div>\n</a>\n%s\n</div>",
  303. implode(" ",[$orientation,$class,$type]),
  304. $link,
  305. $pic->get_src(1600),
  306. $pic_hover->get_src(1600),
  307. ($has_caption ? "<div class=\"caption standard\">".implode("<br>",$caption_html['normal'])."</div>": " "),
  308. ($has_caption ? "<div class=\"caption hover\">".implode("<br>",$caption_html['hover'])."</div>" : " " ),
  309. $add
  310. );
  311. break;
  312. case 'brick':
  313. array_shift($request);
  314. $class = array_shift($request);
  315. $new = sprintf("<div class=\"content_element brick %s\">\n%s\n</div>",
  316. $class,
  317. $md->text(implode("\n",$body))
  318. );
  319. break;
  320. case 'calendar':
  321. array_shift($request);
  322. $conf = array('path', $this->folder);
  323. $v = $this->read_config();
  324. $cal = new \Modules\CCalendar($v,$conf);
  325. $new=sprintf("<div class=\"calendar\">\n%s\n</div>",
  326. $cal);
  327. break;
  328. case 'header':
  329. array_shift($request);
  330. $conf = array('path', $this->folder);
  331. $v = $this->read_config();
  332. switch (array_shift($request)) {
  333. case 'event':
  334. $el = new CEvent($v,$conf);
  335. $el->set_layout('archive');
  336. $new = $el;
  337. break;
  338. case 'concert':
  339. $el = new CConcert($v,$conf);
  340. $el->set_layout('header');
  341. $new = $el;
  342. break;
  343. }
  344. break;
  345. case 'data':
  346. $method = strtoupper($request[1]);
  347. //$keys = [];
  348. if (in_array($method,['POST','GET','SESSION'])) {
  349. foreach ($body as $line) {
  350. $key = explode("=",$line);
  351. $raw = $f3->get($method.'.'.$key[0]);
  352. if (count($key) >= 2) {
  353. $type=$key[1];
  354. } else {
  355. $type = false;
  356. }
  357. switch ($type) {
  358. case 'base64':
  359. $new = urlsafe_b64decode($raw);
  360. break;
  361. default:
  362. $new = $raw;
  363. }
  364. }
  365. //var_dump($new);
  366. }
  367. break;
  368. case 'buy':
  369. // synopsis:
  370. // buy:name:price
  371. // TODO: become currency aware (now EURO is hardcoded)
  372. $new = '';
  373. if (count($request)>=2) {
  374. $name=$request[1];
  375. } else {
  376. $name="item";
  377. }
  378. if (count($request)>=3) {
  379. $price=$request[2];
  380. } else {
  381. $price=1.0;
  382. }
  383. $fields = [
  384. 'caller' => $f3->get('page'),
  385. 'name'=>$name,
  386. 'price'=>$price,
  387. 'amount'=>1
  388. ];
  389. $hidden_inputs = [];
  390. foreach ($fields as $k=>$v) {
  391. $hidden_inputs[] = sprintf('<input type="hidden" name="%s" value="%s" />',$k,$v);
  392. }
  393. $new = sprintf('<form method="post" action="%s">%s<button action="submit" >BUY</button><span class="price"> %s</span></form>',
  394. '/api/cart/add',
  395. implode("\n",$hidden_inputs),
  396. $price ."€"
  397. );
  398. break;
  399. case 'checkout':
  400. //first argument, if present, is a path to folder containing order database
  401. $path = '';
  402. if (count($request) > 1) {
  403. $add_path = $request[1];
  404. if (strncmp($add_path,"/",1)) {
  405. $path = $this->folder.$add_path;
  406. } else {
  407. $path = $add_path;
  408. }
  409. } else {
  410. $path = $this->folder;
  411. }
  412. $checkout = new \Controller\Checkout($path);
  413. $new = $checkout->index();
  414. break;
  415. case 'only_cart':
  416. $checkout = new \Controller\Checkout($this->folder);
  417. $new = $checkout->html_cart();
  418. break;
  419. case 'image':
  420. $module = new CEimage($request, $body, $this->structs, $this->content, $this->domains);
  421. $new = $module->index();
  422. unset($module);
  423. break;
  424. case 'devide':
  425. $contents = explode($request[1],implode("\n",$body));
  426. $c=count($contents);
  427. $str="";
  428. for ($iiii=0;$iiii<$c;$iiii++) {
  429. $str .= sprintf(" %f%%",100/$c);
  430. }
  431. $template = sprintf('grid-template-columns:%s;',
  432. $str);
  433. $counter=0;
  434. $new = sprintf('<div class="content_element_devided" style="%s">',$template);
  435. foreach($contents as $part) {
  436. $counter++;
  437. if (count($request) >= 4) {
  438. $part=str_replace([$request[2],$request[3]],["{|","|}"],$part);
  439. $part=$this->dispatch($part);
  440. }
  441. $new .= sprintf("<div>\n%s\n</div>",
  442. $md->text($part)
  443. );
  444. }
  445. $new.="</div>";
  446. break;
  447. case 'page':
  448. array_shift($request);
  449. $target = array_shift($request);
  450. $class = array_shift($request);
  451. $folder = $this->folder.$target."/";
  452. $anchor_name=array_pop(explode("/",$target));
  453. $fff = new \Modules\FilesInFolders(
  454. $folder,
  455. ['content'=>[
  456. 'secondary'=>'secondary',
  457. 'zzz'=>'hidden',
  458. 'unpublish'=>'hidden'],
  459. 'keyfiles'=>[
  460. 'banner'=>[
  461. 'until'=>$folder,
  462. 'type'=>'pic']]]
  463. );
  464. $fff->prepare_files();
  465. foreach ($body as $line) {
  466. $ccc = explode(":",$line);
  467. if (count($ccc) == 2) {
  468. if ($ccc[1] == 'false') {
  469. $ccc[1] = false;
  470. }
  471. $fff->config[$ccc[0]] = $ccc[1];
  472. }
  473. }
  474. $fff->fill_content();
  475. //var_dump($fff->config);
  476. $banner = "";
  477. if ($fff->extras['banner']) {
  478. $banner=sprintf("<img class=\"banner\" src=\"%s\" alt=\"section banner\"/>",
  479. $fff->extras['banner']);
  480. }
  481. $new = sprintf("<div class=\"content_element_page %s\">"
  482. ."<a name=\"%s\">%s</a>\n%s\n</div>",
  483. $class,
  484. $anchor_name,
  485. $banner,
  486. implode("\n",$fff->content['default']));
  487. break;
  488. case 'youtube':
  489. array_shift($request);
  490. $vid=array_shift($request);
  491. $pos= array_shift($request);
  492. if( in_array($pos,array('left','right','full','center','auto'))) {
  493. $class = $pos;
  494. } else {
  495. $class = 'left';
  496. }
  497. $video=sprintf("<iframe width=\"700\" height=\"394\" class=\"ytvideo\" "
  498. ."src=\"https://www.youtube.com/embed/%s\"></iframe>",
  499. $vid);
  500. $thumbnail = sprintf("<div class=\"video-thumbnail\"><a href=\"%s\" data-featherlight=\"#%s\">"
  501. ."<img class=\"thumbnail\" src=\"https://img.youtube.com/vi/%s/mqdefault.jpg\" alt=\"video-preview\"/>"
  502. ."<img class=\"play-button\" src=\"%s\" alt=\"play-button\" />"
  503. ."</a></div><div class=\"lightbox\" id=\"%s\" >%s</div>",
  504. "https://www.youtube.com/watch?v=".$vid,
  505. $vid,
  506. $vid,
  507. "/rsc/img/play-button.png",
  508. $vid,
  509. $video
  510. );
  511. foreach ($body as $k=>$line) {
  512. if (strpos($line,"©") !== FALSE
  513. || strpos($line,"&copy;") !== FALSE) {
  514. $body[$k] = sprintf("<span class=\"copyright\">%s</span>",$line);
  515. }
  516. }
  517. $new=sprintf("<div class='video-container content_element_youtube %s'>"
  518. ."<div class=\"media\">%s</div>"
  519. ."<div class=\"caption\">%s</div>"
  520. ."</div>",
  521. $class,
  522. $thumbnail,
  523. $md->text(implode("\n",$body)));
  524. break;
  525. default:
  526. $new=FilesInFolders::warn("Content Module \"".$request[0]."\" unknown");
  527. break;
  528. }
  529. return $new;
  530. }
  531. }