mostly filebased Content Presentation System
Du kan inte välja fler än 25 ämnen Ämnen måste starta med en bokstav eller siffra, kan innehålla bindestreck ('-') och vara max 35 tecken långa.

659 lines
25KB

  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. $query = parse_url($dest,PHP_URL_QUERY);
  266. $fragment = parse_url($dest,PHP_URL_FRAGMENT);
  267. if (null !== $query) {
  268. parse_str($query,$data);
  269. }
  270. if ($f3->get('LANG') != $f3->get('default_lang')) {
  271. if (!array_key_exists('lang',$data)) {
  272. $data['lang'] = $f3->get('LANG');
  273. }
  274. }
  275. $new_dest = $base;
  276. if (count($data) > 0) {
  277. $new_dest .= "?" . http_build_query($data);
  278. }
  279. if ($fragment) {
  280. $new_dest .= "#" . $fragment;
  281. }
  282. //if ($f3->get('LANG') != $f3->get('default_lang')) {
  283. // $dest .= "?lang=".$f3->get('LANG');
  284. //}
  285. $link=sprintf('href="%s" ',$f3->get('SITE_URL')."/".$new_dest);
  286. break;
  287. case 'external':
  288. $dest=implode(":",$request);
  289. $target = $f3->get('external_links_open_in_new_window')
  290. ? 'target="_blank"'
  291. : ''
  292. ;
  293. $link=sprintf('href="%s" %s',$dest, $target);
  294. break;
  295. default:
  296. $link='href="#"';
  297. break;
  298. }
  299. $new=sprintf("<div class=\"brick %s\">\n<a class=\"content_element_box\" %s>\n<div class=\"content_element_box\">
  300. <div class=\"image\">
  301. <img class=\"standard\" src=\"%s\" /><img class=\"hover\" src=\"%s\" />
  302. </div>
  303. %s
  304. %s
  305. \n</div>\n</a>\n%s\n</div>",
  306. implode(" ",[$orientation,$class,$type]),
  307. $link,
  308. $pic->get_src(1600),
  309. $pic_hover->get_src(1600),
  310. ($has_caption ? "<div class=\"caption standard\">".implode("<br>",$caption_html['normal'])."</div>": " "),
  311. ($has_caption ? "<div class=\"caption hover\">".implode("<br>",$caption_html['hover'])."</div>" : " " ),
  312. $add
  313. );
  314. break;
  315. case 'brick':
  316. array_shift($request);
  317. $class = array_shift($request);
  318. $new = sprintf("<div class=\"content_element brick %s\">\n%s\n</div>",
  319. $class,
  320. $md->text(implode("\n",$body))
  321. );
  322. break;
  323. case 'calendar':
  324. array_shift($request);
  325. $conf = array('path', $this->folder);
  326. $v = $this->read_config();
  327. $cal = new \Modules\CCalendar($v,$conf);
  328. $new=sprintf("<div class=\"calendar\">\n%s\n</div>",
  329. $cal);
  330. break;
  331. case 'header':
  332. array_shift($request);
  333. $conf = array('path' => $this->folder);
  334. //$v = $this->read_config();
  335. switch (array_shift($request)) {
  336. case 'event':
  337. $el = new CEvent($this->config,$conf);
  338. $el->set_layout('archive');
  339. $new = $el;
  340. break;
  341. case 'concert':
  342. $el = new CConcert($this->config,$conf);
  343. $el->set_layout('header');
  344. $new = $el;
  345. break;
  346. }
  347. break;
  348. case 'data':
  349. $method = strtoupper($request[1]);
  350. //$keys = [];
  351. if (in_array($method,['POST','GET','SESSION'])) {
  352. foreach ($body as $line) {
  353. $key = explode("=",$line);
  354. $raw = $f3->get($method.'.'.$key[0]);
  355. if (count($key) >= 2) {
  356. $type=$key[1];
  357. } else {
  358. $type = false;
  359. }
  360. switch ($type) {
  361. case 'base64':
  362. $new = urlsafe_b64decode($raw);
  363. break;
  364. default:
  365. $new = $raw;
  366. }
  367. }
  368. //var_dump($new);
  369. }
  370. break;
  371. case 'buy':
  372. // synopsis:
  373. // buy:name:price
  374. // TODO: become currency aware (now EURO is hardcoded)
  375. $new = '';
  376. if (count($request)>=2) {
  377. $name=$request[1];
  378. } else {
  379. $name="item";
  380. }
  381. if (count($request)>=3) {
  382. $price=$request[2];
  383. } else {
  384. $price=1.0;
  385. }
  386. $fields = [
  387. 'caller' => $f3->get('page'),
  388. 'name'=>$name,
  389. 'price'=>$price,
  390. 'amount'=>1
  391. ];
  392. $hidden_inputs = [];
  393. foreach ($fields as $k=>$v) {
  394. $hidden_inputs[] = sprintf('<input type="hidden" name="%s" value="%s" />',$k,$v);
  395. }
  396. $new = sprintf('<form method="post" action="%s">%s<button action="submit" >BUY</button><span class="price"> %s</span></form>',
  397. '/api/cart/add',
  398. implode("\n",$hidden_inputs),
  399. $price ."€"
  400. );
  401. break;
  402. case 'checkout':
  403. //first argument, if present, is a path to folder containing order database
  404. $path = '';
  405. if (count($request) > 1) {
  406. $add_path = $request[1];
  407. if (strncmp($add_path,"/",1)) {
  408. $path = $this->folder.$add_path;
  409. } else {
  410. $path = $add_path;
  411. }
  412. } else {
  413. $path = $this->folder;
  414. }
  415. $checkout = new \Controller\Checkout($path);
  416. $new = $checkout->index();
  417. break;
  418. case 'only_cart':
  419. $checkout = new \Controller\Checkout($this->folder);
  420. $new = $checkout->html_cart();
  421. break;
  422. case 'image':
  423. $module = new CEimage($request, $body, $this->structs, $this->content, $this->domains);
  424. $new = $module->index();
  425. unset($module);
  426. break;
  427. case 'devide':
  428. $contents = explode($request[1],implode("\n",$body));
  429. $c=count($contents);
  430. $str="";
  431. for ($iiii=0;$iiii<$c;$iiii++) {
  432. $str .= sprintf(" %f%%",100/$c);
  433. }
  434. $template = sprintf('grid-template-columns:%s;',
  435. $str);
  436. $counter=0;
  437. $new = sprintf('<div class="content_element_devided" style="%s">',$template);
  438. foreach($contents as $part) {
  439. $counter++;
  440. if (count($request) >= 4) {
  441. $part=str_replace([$request[2],$request[3]],["{|","|}"],$part);
  442. $part=$this->dispatch($part);
  443. }
  444. $new .= sprintf("<div>\n%s\n</div>",
  445. $md->text($part)
  446. );
  447. }
  448. $new.="</div>";
  449. break;
  450. case 'page':
  451. array_shift($request);
  452. $target = array_shift($request);
  453. $class = array_shift($request);
  454. $folder = $this->folder.$target."/";
  455. $anchor_name=array_pop(explode("/",$target));
  456. $fff = new \Modules\FilesInFolders(
  457. $folder,
  458. ['content'=>[
  459. 'secondary'=>'secondary',
  460. 'zzz'=>'hidden',
  461. 'unpublish'=>'hidden'],
  462. 'keyfiles'=>[
  463. 'banner'=>[
  464. 'until'=>$folder,
  465. 'type'=>'pic']]]
  466. );
  467. $fff->prepare_files();
  468. foreach ($body as $line) {
  469. $ccc = explode(":",$line);
  470. if (count($ccc) == 2) {
  471. if ($ccc[1] == 'false') {
  472. $ccc[1] = false;
  473. }
  474. $fff->config[$ccc[0]] = $ccc[1];
  475. }
  476. }
  477. $fff->fill_content();
  478. //var_dump($fff->config);
  479. $banner = "";
  480. if ($fff->extras['banner']) {
  481. $banner=sprintf("<img class=\"banner\" src=\"%s\" alt=\"section banner\"/>",
  482. $fff->extras['banner']);
  483. }
  484. $new = sprintf("<div class=\"content_element_page %s\">"
  485. ."<a name=\"%s\">%s</a>\n%s\n</div>",
  486. $class,
  487. $anchor_name,
  488. $banner,
  489. implode("\n",$fff->content['default']));
  490. break;
  491. case 'audio':
  492. case 'video':
  493. $video = $request[1];
  494. $style = $request[2];
  495. $a = explode("/", $video);
  496. $full_name = array_pop($a);
  497. $b = explode('.',$full_name);
  498. $ext = array_pop($b);
  499. $name = implode('.', $b);
  500. foreach($this->structs as $domain=>$destination) {
  501. if(array_key_exists($name, $this->structs[$domain]['pic'])) {
  502. $image = $this->structs[$domain]['pic'][$name];
  503. unset($this->structs[$domain]['pic'][$name]);
  504. unset($this->content[$this->domains[$domain]][$name."10image"]);
  505. break;
  506. }
  507. }
  508. $image2 = "/".$image;
  509. foreach(['png','PNG','jpg','JPG','jpeg','JPEG'] as $picext) {
  510. $candidate=$this->folder.implode("/",$a)."/".$name.".".$picext;
  511. if (is_file($candidate)) {
  512. $image2 = $candidate;
  513. break;
  514. }
  515. }
  516. $cached = new CachedImage($image);
  517. $cached2 = new CachedImage($image2);
  518. foreach ($body as $k=>$line) {
  519. if (strpos($line,"©") !== FALSE
  520. || strpos($line,"&copy;") !== FALSE) {
  521. $body[$k] = sprintf("<span class=\"copyright\">%s</span>",$line);
  522. }
  523. }
  524. $ratio=false;
  525. if ($request[0] == 'audio') {
  526. $asd = new \Image($image2);
  527. if ($asd) {
  528. $ratio=sprintf("%s:%s",$asd->width(),$asd->height());
  529. unset($asd);
  530. }
  531. }
  532. $vid = new \Modules\CVideo([
  533. 'TARGET'=>$video,
  534. 'STILL'=>$cached,
  535. 'STILL2' => $cached2->get_src(1400),
  536. 'NAME' =>$name,
  537. 'CAPTION' => $md->text(implode("\n",$body)),
  538. 'STYLE' => $style,
  539. 'RATIO' => $ratio
  540. ],['path'=>"/".$this->folder]);
  541. if ($request[0] == 'audio') {
  542. $vid->set_layout('audio');
  543. } else {
  544. $vid->set_layout('lightbox');
  545. }
  546. $new = sprintf("%s",
  547. $vid
  548. );
  549. break;
  550. case 'youtube':
  551. array_shift($request);
  552. $vid=array_shift($request);
  553. $pos= array_shift($request);
  554. if( in_array($pos,array('left','right','full','center','auto'))) {
  555. $class = $pos;
  556. } else {
  557. $class = 'left';
  558. }
  559. $video=sprintf("<iframe width=\"700\" height=\"394\" class=\"ytvideo\" "
  560. ."src=\"https://www.youtube.com/embed/%s\"></iframe>",
  561. $vid);
  562. $thumbnail = sprintf("<div class=\"video-thumbnail\"><a href=\"%s\" data-featherlight=\"#%s\">"
  563. ."<img class=\"thumbnail\" src=\"https://img.youtube.com/vi/%s/mqdefault.jpg\" alt=\"video-preview\"/>"
  564. ."<img class=\"play-button\" src=\"%s\" alt=\"play-button\" />"
  565. ."</a></div><div class=\"lightbox\" id=\"%s\" >%s</div>",
  566. "https://www.youtube.com/watch?v=".$vid,
  567. $vid,
  568. $vid,
  569. "/rsc/img/play-button.png",
  570. $vid,
  571. $video
  572. );
  573. foreach ($body as $k=>$line) {
  574. if (strpos($line,"©") !== FALSE
  575. || strpos($line,"&copy;") !== FALSE) {
  576. $body[$k] = sprintf("<span class=\"copyright\">%s</span>",$line);
  577. }
  578. }
  579. $new=sprintf("<div class='video-container content_element_youtube %s'>"
  580. ."<div class=\"media\">%s</div>"
  581. ."<div class=\"caption\">%s</div>"
  582. ."</div>",
  583. $class,
  584. $thumbnail,
  585. $md->text(implode("\n",$body)));
  586. break;
  587. default:
  588. $new=FilesInFolders::warn("Content Module \"".$request[0]."\" unknown");
  589. break;
  590. }
  591. return $new;
  592. }
  593. }