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.

816 line
32KB

  1. <?php
  2. namespace Modules;
  3. class FilesInFolders {
  4. private $folder;
  5. public $content = array();
  6. public $extras = array();
  7. private $domains = array('default'=>'default');
  8. private $keyfiles = array();
  9. public $structs = array();
  10. private $EXT=array(
  11. 'txt'=>array( 'txt', 'text', 'md' ),
  12. 'pic'=>array( 'jpg', 'jpeg', 'png', 'svg' ),
  13. 'tpl'=>array( 'html', 'htm', 'tpl' ),
  14. 'audio'=>array('mp3','wav','ogg'),
  15. 'csv'=>array( 'csv' )
  16. );
  17. public $config = array();
  18. private $state=array();
  19. function __construct($folder,$conf=array()) {
  20. debug("about to construct FIF: $folder");
  21. $f3 = \Base::instance();
  22. if(is_dir($folder)) { // are we given a valid path?
  23. $this->folder = $folder;
  24. } else { // and if not?
  25. $this->folder = $f3->get('CONTENT')."./";
  26. }
  27. if(is_array($conf)) {
  28. foreach($conf as $key=>$value) {
  29. switch($key) {
  30. case 'content':
  31. if(is_array($value)) {
  32. foreach($value as $k=>$v) {
  33. $this->domains[$k] = $v;
  34. }
  35. }
  36. break;
  37. case 'keyfiles':
  38. if(is_array($value)) {
  39. foreach($value as $k=>$v) {
  40. $this->keyfiles[$k] = $v;
  41. }
  42. }
  43. break;
  44. }
  45. }
  46. }
  47. foreach($this->domains as $domain) {
  48. $this->content[$domain] = array();
  49. }
  50. foreach($this->keyfiles as $keys=>$d) {
  51. $this->extras[$keys] = "";
  52. }
  53. debug("constructed files in folder: $folder");
  54. }
  55. /////////////////////////////
  56. // read folder into struct //
  57. /////////////////////////////
  58. function prepare_files() {
  59. foreach ($this->domains as $k=>$v) {
  60. foreach($this->EXT as $cat=>$endings) {
  61. $this->structs[$k][$cat]=array();
  62. }
  63. }
  64. $ls = scandir($this->folder);
  65. foreach ($ls as $k=>$f) {
  66. if (!strncmp($f,'.',1)) continue; // ignore hidden files
  67. $ex=explode(".", $f);
  68. $ext=strtolower(end($ex));
  69. if (array_key_exists($ex[0],$this->domains)) {
  70. $domain_key=$ex[0];
  71. $sort_key=1;
  72. } elseif (array_key_exists($ex[0], $this->keyfiles)) {
  73. if(in_array($ext,$this->EXT[$this->keyfiles[$ex[0]]['type']])) {
  74. $this->extras[$ex[0]]=$this->folder.$f;
  75. continue;
  76. }
  77. $domain_key='default';
  78. $sort_key=0;
  79. } else {
  80. $domain_key='default';
  81. $sort_key=0;
  82. }
  83. foreach ($this->EXT as $cat=>$endings) {
  84. if (in_array($ext, $endings)) {
  85. $this->structs[$domain_key][$cat][$ex[$sort_key]] = $this->folder.$f;
  86. break;
  87. }
  88. }
  89. }
  90. foreach($this->keyfiles as $key=>$param) {
  91. if(!$this->extras[$key]) {
  92. $this->extras[$key] = self::search_up(
  93. $key,
  94. array($this->folder,$param['until']),
  95. $this->EXT[$param['type']]
  96. );
  97. }
  98. if($this->extras[$key]) {
  99. if ($param['type'] == 'txt') {
  100. $this->read_textfile($this->extras[$key]);
  101. }
  102. }
  103. }
  104. }
  105. ///////////////////////////////////////
  106. // prepare content as per the struct //
  107. ///////////////////////////////////////
  108. function fill_content() {
  109. $f3 = \Base::instance();
  110. $md = new \freaParsedown();
  111. $md->deactivate_ol();
  112. //var_dump($md->get_BlockTypes());
  113. foreach($this->domains as $domain_key=>$domain) {
  114. // don't act on hidden files
  115. if ($domain == 'hidden') { continue; }
  116. $this->state['current_domain'] = $domain_key;
  117. foreach($this->structs[$domain_key]['txt'] as $key=>$file) {
  118. $str = $this->read_textfile($file);
  119. $str = self::content_element_dispatcher($str);
  120. $str = $md->text($str);
  121. //$str = sprintf("%s", $str);
  122. $this->content[$domain][$key."30text"] = sprintf(
  123. "<div class=\"item %s %s\">%s</div>",
  124. $page,
  125. $key,
  126. $str
  127. );
  128. }
  129. $includeTemplates = array_key_exists('includeTemplates', $this->config)
  130. ? $this->config['includeTemplates']
  131. : $f3->get('includeTemplates') ? : FALSE
  132. ;
  133. if ($includeTemplates) {
  134. foreach($this->structs[$domain_key]['tpl'] as $key=>$file) {
  135. $str = \Template::instance()->render(substr($file,7));
  136. $str = self::linkify($str);
  137. $this->content[$domain][$key."00tpl"] = sprintf(
  138. "<div class=\"item %s %s\">%s</div>",
  139. $page,
  140. $key,
  141. $str
  142. );
  143. }
  144. }
  145. $bulkIncludePic = array_key_exists('bulkIncludePic',$this->config)
  146. ? $this->config['bulkIncludePic']
  147. : $f3->get('bulkIncludePic') ? : FALSE
  148. ;
  149. if ($bulkIncludePic) {
  150. foreach($this->structs[$domain_key]['pic'] as $key=>$file) {
  151. $this->content[$domain][$key."10image"] = sprintf(
  152. "<img class=\"bulkImportedImage $bulkIncludePic\" src=\"/$file\" />"
  153. );
  154. }
  155. }
  156. $bulkIncludeAudio = array_key_exists('bulkIncludeAudio',$this->config)
  157. ? $this->config['bulkIncludeAudio']
  158. : $f3->get('bulkIncludeAudio') ? : FALSE
  159. ;
  160. if ($bulkIncludeAudio) {
  161. foreach ($this->structs[$domain_key]['audio'] as $key=>$file) {
  162. $this->content[$domain][$key."20audio"] = sprintf(
  163. '<a href="%s" class="audio">%s</a><br>',
  164. $file, $key
  165. );
  166. }
  167. }
  168. foreach($this->structs[$domain_key]['csv'] as $key=>$file) {
  169. $csv = new \Modules\Ography($file,TRUE);
  170. $str="<table>";
  171. foreach($csv->entries as $entry) {
  172. $tmp="";
  173. foreach($entry as $key=>$value) {
  174. $tmp .= sprintf("<td class=\"%s\">%s</td>", $key, $value);
  175. }
  176. $str .= sprintf("<tr>%s</tr>",$tmp);
  177. }
  178. $str.="</table>";
  179. $this->content[$domain][$key."30csv"] = $str;
  180. }
  181. }
  182. }
  183. //////////////////////
  184. // read config data //
  185. //////////////////////
  186. function read_config($domain=false) {
  187. foreach ($this->domains as $source=>$destination) {
  188. if (is_string($domain)) {
  189. if ($source != $domain) { continue; }
  190. } elseif (is_array($domain)) {
  191. if (!in_array($source,$domain)) { continue; }
  192. }
  193. foreach ($this->structs[$source]['txt'] as $key=>$file) {
  194. $this->read_textfile($file);
  195. }
  196. }
  197. return $this->config;
  198. }
  199. ////////////////
  200. // recursions //
  201. ////////////////
  202. function search_up($key,$paths,$ext) {
  203. $return = "";
  204. if(count($paths) == 2) {
  205. $current = $paths[0];
  206. $last_try = $paths[1];
  207. $ls=scandir($current);
  208. foreach($ls as $f) {
  209. if(!strncmp($f,'.',1)) continue; // ignore hidden files
  210. $ex=explode(".", $f);
  211. if(in_array(strtolower(end($ex)),$ext)) {
  212. if($ex[0]==$key) {
  213. $return = $current.$f;
  214. break;
  215. }
  216. }
  217. }
  218. }
  219. if ($return) {
  220. return $return;
  221. } elseif($current == $last_try) {
  222. return false;
  223. } else {
  224. $p = explode('/',$current);
  225. array_pop($p);
  226. array_pop($p);
  227. return self::search_up($key,array(implode("/",$p)."/",$last_try),$ext);
  228. }
  229. }
  230. ///////////////////////
  231. // Utility functions //
  232. ///////////////////////
  233. function read_textfile($file) {
  234. debug("about to read file: $file");
  235. $str = file_get_contents($file);
  236. debug("read file: $file");
  237. $str = self::linkify($str);
  238. $str = self::strip_comments($str);
  239. $str = self::get_config_from_content($str);
  240. debug("processed file: $file");
  241. return $str;
  242. }
  243. function strip_comments($str) {
  244. $single_line_comments = "/(^;.*\R)/m";
  245. $str = preg_replace($single_line_comments,"",$str);
  246. $multi_line_comments = "/\/\*.*?\*\//s";
  247. $str = preg_replace($multi_line_comments,"",$str);
  248. return $str;
  249. }
  250. function linkify($string) {
  251. $pattern = "/\s@(\w+)[=]([\w,]+)\s/";
  252. $count = 0;
  253. $new = preg_replace_callback
  254. ($pattern,
  255. function($m){
  256. $f3 = \Base::instance();
  257. return $f3->get('SITE_URL')
  258. .$f3->alias($m[1],self::$keyword."=".$m[2])
  259. ;},
  260. $string);
  261. return $new;
  262. }
  263. function get_config_from_content($string) {
  264. $f3 = \Base::instance();
  265. $f = 0;
  266. $pattern = "/#\+(\w+):\s?(.*)/";
  267. $f = preg_match_all($pattern, $string,$matches,PREG_PATTERN_ORDER);
  268. for ($i=0;$i<$f;$i++) {
  269. $string = str_replace($matches[0][$i],"",$string);
  270. $key = $matches[1][$i];
  271. $value = trim($matches[2][$i]);
  272. if(strtolower($value) == "false") {
  273. $value = FALSE;
  274. }
  275. if(!strncmp(trim($value),'@',1)) {
  276. //var_dump($f3->get('DATA'));
  277. if (array_key_exists($key,$f3->get('DATA'))) {
  278. $DATA = $f3->get('DATA.'.$key);
  279. $conf = array($DATA['type'],$DATA['dir']);
  280. $relation = new \Modules\TOC($conf,$f3->get('CONTENT'),substr($value,1));
  281. $relation->dispatch();
  282. $this->config[$key]=array_shift($relation->entries);
  283. } else {
  284. $this->config[$key]=$value;
  285. }
  286. } else {
  287. $this->config[$key]=$value;
  288. }
  289. }
  290. $pattern = "/§>\s*(\w+):(.*?)\R[\011\040]*\R/s";
  291. $f = preg_match_all($pattern, $string,$matches,PREG_PATTERN_ORDER);
  292. for ($i=0;$i<$f;$i++) {
  293. $string = str_replace($matches[0][$i],"",$string);
  294. $key = $matches[1][$i];
  295. $value = trim($matches[2][$i]);
  296. if(strtolower($value) == "false") {
  297. $value = FALSE;
  298. }
  299. if (!strncmp($value,'@',1)) {
  300. # var_dump();
  301. if (array_key_exists($key,$f3->get('DATA'))) {
  302. $entries = explode("@",$value);
  303. array_shift($entries); // first entry is always empty
  304. $DATA = $f3->get('DATA.'.$key);
  305. $conf = array($DATA['type'],$DATA['dir']);
  306. $relation = new \Modules\TOC($conf,$f3->get('CONTENT'),$entries);
  307. $relation->dispatch();
  308. if(/*count($entries) >*/ 1) {
  309. $this->config[$key]= new CMultiple($relation->entries);
  310. } else {
  311. $this->config[$key]=array_shift($relation->entries);
  312. }
  313. } else {
  314. $this->config[$key]=$value;
  315. }
  316. } else {
  317. $this->config[$key]=$value;
  318. }
  319. }
  320. return $string;
  321. }
  322. function content_element_dispatcher($string) {
  323. $f3 = \Base::instance();
  324. $md = new \freaParsedown();
  325. $md->deactivate_ol();
  326. $f0 = 0;
  327. // find occorances of {| keyword |}
  328. $pattern = "/\{\|(.+?)\|\}/s";
  329. $f = preg_match_all($pattern, $string,$matches,PREG_PATTERN_ORDER);
  330. for ($i=0;$i<$f;$i++) {
  331. $body = preg_split("/\R/",trim($matches[1][$i]));
  332. $request = explode(":", trim(array_shift($body)));
  333. $new="";
  334. switch($request[0]) {
  335. case 'test':
  336. $new="seems to work";
  337. break;
  338. case ';':
  339. $new="";
  340. break;
  341. case 'path':
  342. $new="/".$this->folder;
  343. break;
  344. case 'space':
  345. $new=sprintf("<div style=\"height:%s;\"></div>",
  346. $request[1]
  347. );
  348. break;
  349. case 'span':
  350. $new=sprintf("<span class=\"%s\">%s</span>",
  351. $request[1],
  352. $request[2] ? : implode("\n",$body)
  353. );
  354. break;
  355. case 'small-text':
  356. if(count($body)) {
  357. $new=sprintf("<div class=\"smalltext\">%s</div>",
  358. implode("\n",$body)
  359. );
  360. } else {
  361. $new=sprintf("<span class=\"smalltext\">%s</span>",
  362. $request[1]
  363. );
  364. }
  365. break;
  366. case 'TOC':
  367. // throw away TOC part of request, we don't need it
  368. array_shift($request);
  369. $toc = new \Modules\TOC($request,$this->folder,$body);
  370. $toc->dispatch();
  371. $new=sprintf("<div class=\"TOC %s\">%s</div>",
  372. array_shift($request),
  373. $toc);
  374. break;
  375. case 'form':
  376. $token_db = $f3->get('TEMP') . "CEform/";
  377. $form_config_file = sprintf("%s%s.cfg",
  378. ROOT.$this->folder,
  379. $request[1]);
  380. $db = new \DB\Jig($token_db,\DB\Jig::FORMAT_JSON);
  381. $formcall = new \DB\Jig\Mapper($db,'form_calls');
  382. $timestamp = time();
  383. $token = md5($timestamp . $form_config_file . rand(100,999));
  384. $f3->config($form_config_file);
  385. $fields = $f3->get('fields');
  386. foreach ($fields as $k => $v) {
  387. if ($v['type'] == 'custom') {
  388. $fields[$k]['template'] = sprintf(
  389. "%s%s",
  390. substr($this->folder,8), //assumens content folder is content
  391. $v['template']
  392. );
  393. }
  394. if (array_key_exists('db',$v)) {
  395. switch ($v['db']['type']) {
  396. case 'sqlite':
  397. $array = [];
  398. $db = new \DB\SQL('sqlite:' . $this->folder . $v['db']['file']);
  399. $sql = $v['db']['sql'];
  400. if ( strpos($sql,'insert')===false &&
  401. strpos($sql,'update')===false &&
  402. strpos($sql,'drop')===false) {
  403. $rows = $db->exec($sql);
  404. foreach ($rows as $res) {
  405. switch (count($res)) {
  406. case 2:
  407. $keys=array_keys($res);
  408. $array[$res[$keys[0]]] = $res[$keys[1]];
  409. break;
  410. }
  411. }
  412. }
  413. $fields[$k]['el'] = $array;
  414. unset($array);
  415. break;
  416. }
  417. }
  418. }
  419. $f3->set('fields',
  420. array_merge(
  421. $fields,
  422. ['xss-token'=>[
  423. 'type'=>'hidden',
  424. 'value'=>$token,
  425. 'length'=>strlen($token)
  426. ]]
  427. ));
  428. $formcall->token = $token;
  429. $formcall->timestamp = $timestamp;
  430. $formcall->form = $form_config_file;
  431. $formcall->save();
  432. $form_view = new \Template;
  433. $new=$form_view->render('form.htm');
  434. break;
  435. case 'box':
  436. array_shift($request); //get rid of identifier
  437. $type = array_shift($request);
  438. $pics = explode(":",array_shift($body));
  439. $pic = $pics[0];
  440. $pic_hover = count($pics) > 1 ? $pics[1] : $pic;
  441. if (count($body) >= 3) {
  442. $caption = ['normal'=>['cap1' => array_shift($body),
  443. 'cap2' => array_shift($body)],
  444. 'hover'=> ['cap1' => array_shift($body),
  445. 'cap2' => array_shift($body)]];
  446. $caption_html=[];
  447. foreach ($caption as $state => $set) {
  448. if(!$set['cap2']) {
  449. $caption_html[$state] = [
  450. sprintf('<span class="first">&nbsp;</span>'),
  451. sprintf('<span class="first">%s</span>',$set['cap1'])
  452. ];
  453. } else if (!$set['cap1'] && $set['cap2']) {
  454. $caption_html[$state] = [
  455. sprintf('<span class="second">%s</span>',$set['cap2'])
  456. ];
  457. } else {
  458. $caption_html[$state] = [
  459. sprintf('<span class="first">%s</span>',$set['cap1']?:"&nbsp;"),
  460. sprintf('<span class="second">%s</span>',$set['cap2'])
  461. ];
  462. }
  463. }
  464. $has_caption = TRUE;
  465. } else {
  466. $has_caption = FALSE;
  467. }
  468. if (file_exists($this->folder.$pic)) {
  469. $pic = $this->folder.$pic;
  470. } else {
  471. $pic = $f3->get('RESOURCES')."img/default_img.png";
  472. }
  473. if (file_exists($this->folder.$pic_hover)) {
  474. $pic_hover = $this->folder.$pic_hover;
  475. } else {
  476. $pic_hover = $pic;
  477. }
  478. if(0) {
  479. $PIC = new \Image($pic);
  480. $orientation = $PIC->width() > $PIC->height()
  481. ? 'landscape'
  482. : 'portrait'
  483. ;
  484. unset($PIC);
  485. } else {
  486. list($wwidth, $hheight) = getimagesize($pic);
  487. $orientation = $wwidth > $hheight ? 'landscape' : 'portrait';
  488. }
  489. $pic = new CachedImage($pic);
  490. $pic_hover = new CachedImage($pic_hover);
  491. $class="";
  492. $add="";
  493. switch($type) {
  494. case 'plain':
  495. $link=false;
  496. break;
  497. case 'download':
  498. $file = "/".$this->folder.implode(":",$request);
  499. $link='href="'.$file.'" download ';
  500. break;
  501. case 'lightbox':
  502. $body = implode("\n",$body);
  503. if (count($request) % 2) {
  504. $class = array_pop($request);
  505. }
  506. if (count($request) >= 2) {
  507. $body=str_replace([$request[0],$request[1]],["{|","|}"],$body);
  508. $body=$this->content_element_dispatcher($body);
  509. }
  510. $hash=md5($body);
  511. $add=sprintf("<div id=\"%s\" class=\"content_elment_box_body\">\n%s\n</div>",
  512. $hash,
  513. $md->text($body));
  514. $link='href="#" data-featherlight="#'.$hash.'" ';
  515. break;
  516. case 'internal':
  517. $dest=implode(":",$request);
  518. $data = [];
  519. $base = substr($dest,0,strpos($dest,'?') ? : strlen($dest));
  520. parse_str(parse_url($dest,PHP_URL_QUERY),$data);
  521. $fragment = parse_url($dest,PHP_URL_FRAGMENT);
  522. if ($f3->get('LANG') != $f3->get('default_lang')) {
  523. if (!array_key_exists('lang',$data)) {
  524. $data['lang'] = $f3->get('LANG');
  525. }
  526. }
  527. $new_dest = $base;
  528. if (count($data) > 0) {
  529. $new_dest .= "?" . http_build_query($data);
  530. }
  531. if ($fragment) {
  532. $new_dest .= "#" . $fragment;
  533. }
  534. //if ($f3->get('LANG') != $f3->get('default_lang')) {
  535. // $dest .= "?lang=".$f3->get('LANG');
  536. //}
  537. $link=sprintf('href="%s" ',$f3->get('SITE_URL')."/".$new_dest);
  538. break;
  539. case 'external':
  540. $dest=implode(":",$request);
  541. $target = $f3->get('external_links_open_in_new_window')
  542. ? 'target="_blank"'
  543. : ''
  544. ;
  545. $link=sprintf('href="%s" %s',$dest, $target);
  546. break;
  547. default:
  548. $link='href="#"';
  549. break;
  550. }
  551. $new=sprintf("<div class=\"brick %s\">\n<a class=\"content_element_box\" %s>\n<div class=\"content_element_box\">
  552. <div class=\"image\">
  553. <img class=\"standard\" src=\"%s\" /><img class=\"hover\" src=\"%s\" />
  554. </div>
  555. %s
  556. %s
  557. \n</div>\n</a>\n%s\n</div>",
  558. implode(" ",[$orientation,$class,$type]),
  559. $link,
  560. $pic->get_src(1600),
  561. $pic_hover->get_src(1600),
  562. ($has_caption ? "<div class=\"caption standard\">".implode("<br>",$caption_html['normal'])."</div>": " "),
  563. ($has_caption ? "<div class=\"caption hover\">".implode("<br>",$caption_html['hover'])."</div>" : " " ),
  564. $add
  565. );
  566. break;
  567. case 'brick':
  568. array_shift($request);
  569. $class = array_shift($request);
  570. $new = sprintf("<div class=\"content_element brick %s\">\n%s\n</div>",
  571. $class,
  572. $md->text(implode("\n",$body))
  573. );
  574. break;
  575. case 'calendar':
  576. array_shift($request);
  577. $conf = array('path', $this->folder);
  578. $v = $this->read_config();
  579. $cal = new \Modules\CCalendar($v,$conf);
  580. $new=sprintf("<div class=\"calendar\">\n%s\n</div>",
  581. $cal);
  582. break;
  583. case 'header':
  584. array_shift($request);
  585. $conf = array('path', $this->folder);
  586. $v = $this->read_config();
  587. switch (array_shift($request)) {
  588. case 'event':
  589. $el = new CEvent($v,$conf);
  590. $el->set_layout('archive');
  591. $new = $el;
  592. break;
  593. case 'concert':
  594. $el = new CConcert($v,$conf);
  595. $el->set_layout('header');
  596. $new = $el;
  597. break;
  598. }
  599. break;
  600. case 'image':
  601. $key=$request[1];
  602. $image="";
  603. // if(!$key) {
  604. // $new=self::warn("Content Module \"Image\" needs name of a file (without extension)");
  605. // break;
  606. //}
  607. foreach($this->structs as $domain=>$destination) {
  608. if(array_key_exists($key, $this->structs[$domain]['pic'])) {
  609. $image = $this->structs[$domain]['pic'][$key];
  610. unset($this->structs[$domain]['pic'][$key]);
  611. unset($this->content[$this->domains[$domain]][$key]);
  612. break;
  613. }
  614. }
  615. if ($image) {
  616. if( in_array($request[2],array('left','right','full'))) {
  617. $class = $request[2];
  618. } else {
  619. $class = 'full';
  620. }
  621. $img = new \Image($image);
  622. $ratio = ($img->width() >= $img->height())
  623. ? "landscape"
  624. : "portrait"
  625. ;
  626. $cached = new CachedImage($image);
  627. foreach ($body as $k=>$line) {
  628. if (strpos($line,"©") !== FALSE
  629. || strpos($line,"&copy;") !== FALSE) {
  630. $body[$k] = sprintf("<span class=\"copyright\">%s</span>",$line);
  631. }
  632. }
  633. $new=sprintf("<div class='content_element_image %s'>"
  634. ."<div class=\"media %s\"><a href=\"%s\" data-featherlight=\"image\"><img src=\"%s\" alt=\"user supplied image\" /></a></div>"
  635. ."<img src=\"%s\" style=\"display:none;\" alt=\"user supplied image\" />"
  636. ."<div class=\"caption\">%s</div>"
  637. ."</div>",
  638. $class,
  639. $ratio,
  640. $cached->get_src(1600),
  641. $cached->get_src(1600),
  642. $cached->get_src(1600),
  643. $md->text(implode("\n",$body))
  644. );
  645. } else {
  646. $new=sprintf("<div class='content_element_image %s'>\n"
  647. ."<div class=\"media %s\">\n"
  648. ."<div class=\"caption\">\n%s\n</div>\n"
  649. ."</div>\n",
  650. $class,
  651. $ratio,
  652. $md->text(implode("\n",$body))
  653. );
  654. }
  655. break;
  656. case 'devide':
  657. $contents = explode($request[1],implode("\n",$body));
  658. $c=count($contents);
  659. $str="";
  660. for ($iiii=0;$iiii<$c;$iiii++) {
  661. $str .= sprintf(" %f%%",100/$c);
  662. }
  663. $template = sprintf('grid-template-columns:%s;',
  664. $str);
  665. $counter=0;
  666. $new = sprintf('<div class="content_element_devided" style="%s">',$template);
  667. foreach($contents as $part) {
  668. $counter++;
  669. if (count($request) >= 4) {
  670. $part=str_replace([$request[2],$request[3]],["{|","|}"],$part);
  671. $part=$this->content_element_dispatcher($part);
  672. }
  673. $new .= sprintf("<div>\n%s\n</div>",
  674. $md->text($part)
  675. );
  676. }
  677. $new.="</div>";
  678. break;
  679. case 'page':
  680. array_shift($request);
  681. $target = array_shift($request);
  682. $class = array_shift($request);
  683. $folder = $this->folder.$target."/";
  684. $anchor_name=array_pop(explode("/",$target));
  685. $fff = new \Modules\FilesInFolders(
  686. $folder,
  687. array(
  688. 'content'=>array(
  689. 'secondary'=>'secondary',
  690. 'zzz'=>'hidden',
  691. 'unpublish'=>'hidden'
  692. ))
  693. );
  694. $fff->prepare_files();
  695. $fff->fill_content();
  696. $new = sprintf("<div class=\"content_element_page %s\"><a name=\"%s\"></a>\n%s\n</div>",
  697. $class,
  698. $anchor_name,
  699. implode("\n",$fff->content['default']));
  700. break;
  701. case 'youtube':
  702. $vid=array_shift($request);
  703. $pos= array_shift($request);
  704. if( in_array($pos,array('left','right','full'))) {
  705. $class = $pos;
  706. } else {
  707. $class = 'left';
  708. }
  709. $video=sprintf("<iframe width=\"700\" height=\"394\" class=\"ytvideo\" "
  710. ."src=\"https://www.youtube.com/embed/%s\"></iframe>",
  711. $vid);
  712. $thumbnail = sprintf("<div class=\"video-thumbnail\"><a href=\"%s\" data-featherlight=\"#%s\">"
  713. ."<img class=\"thumbnail\" src=\"https://img.youtube.com/vi/%s/mqdefault.jpg\" alt=\"video-preview\"/>"
  714. ."<img class=\"play-button\" src=\"%s\" alt=\"play-button\" />"
  715. ."</a></div><div class=\"lightbox\" id=\"%s\" >%s</div>",
  716. "https://www.youtube.com/watch?v=".$vid,
  717. $vid,
  718. $vid,
  719. "/rsc/img/play-button.png",
  720. $vid,
  721. $video
  722. );
  723. foreach ($body as $k=>$line) {
  724. if (strpos($line,"©") !== FALSE
  725. || strpos($line,"&copy;") !== FALSE) {
  726. $body[$k] = sprintf("<span class=\"copyright\">%s</span>",$line);
  727. }
  728. }
  729. $new=sprintf("<div class='video-container %s'>"
  730. ."<div class=\"media\">%s</div>"
  731. ."<div class=\"caption\">%s</div>"
  732. ."</div>",
  733. $class,
  734. $thumbnail,
  735. $md->text(implode("\n",$body)));
  736. break;
  737. default:
  738. $new=self::warn("Content Module \"".$request[0]."\" unknown");
  739. break;
  740. }
  741. $string = str_replace($matches[0][$i],$new,$string);
  742. }
  743. return $string;
  744. }
  745. function warn($message) {
  746. return sprintf("<div class=\"warning\">%s</div>",$message);
  747. }
  748. }