mostly filebased Content Presentation System
Vous ne pouvez pas sélectionner plus de 25 sujets Les noms de sujets doivent commencer par une lettre ou un nombre, peuvent contenir des tirets ('-') et peuvent comporter jusqu'à 35 caractères.

423 lines
15KB

  1. <?php
  2. namespace Modules;
  3. class FilesInFolders {
  4. private $folder;
  5. public $content = array();
  6. public $extras = array();
  7. public $domains = array('default'=>'default');
  8. private $keyfiles = array();
  9. public $structs = array();
  10. public $EXT=array(
  11. 'txt'=>array( 'txt', 'text', 'md' ),
  12. 'pic'=>array( 'jpg', 'jpeg', 'png', 'svg' ),
  13. 'tpl'=>array( 'html', 'htm' ),
  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\"><a name=\"%s\"></a>%s</div>",
  124. '',
  125. $key,
  126. $key,
  127. $str
  128. );
  129. }
  130. $includeTemplates = array_key_exists('includeTemplates', $this->config)
  131. ? $this->config['includeTemplates']
  132. : ($f3->get('includeTemplates') ? : FALSE)
  133. ;
  134. if ($includeTemplates) {
  135. foreach($this->structs[$domain_key]['tpl'] as $key=>$file) {
  136. $str = \Template::instance()->render(substr($file,7));
  137. $str = self::linkify($str);
  138. $this->content[$domain][$key."00.tpl"] = sprintf(
  139. "<div class=\"item %s %s\">%s</div>",
  140. '',
  141. $key,
  142. $str
  143. );
  144. }
  145. }
  146. $bulkIncludePic = array_key_exists('bulkIncludePic',$this->config)
  147. ? $this->config['bulkIncludePic']
  148. : ($f3->get('bulkIncludePic') ? : FALSE)
  149. ;
  150. if ($bulkIncludePic) {
  151. foreach($this->structs[$domain_key]['pic'] as $key=>$file) {
  152. $image_include_version = 2;
  153. switch ($image_include_version) {
  154. case 1:
  155. $this->content[$domain][$key."10.image"] = sprintf(
  156. "<img class=\"bulkImportedImage $bulkIncludePic\" src=\"/$file\" />"
  157. );
  158. break;
  159. case 2:
  160. $module = new CEimage(['image',$file,$bulkIncludePic,'gallery']);
  161. $this->content[$domain][$key."10.image"] = $module->index();
  162. unset($module);
  163. break;
  164. case 3:
  165. //$this->content[$domain][] = "asdasd";
  166. break;
  167. }
  168. }
  169. }
  170. $bulkIncludeAudio = array_key_exists('bulkIncludeAudio',$this->config)
  171. ? $this->config['bulkIncludeAudio']
  172. : ($f3->get('bulkIncludeAudio') ? : FALSE)
  173. ;
  174. if ($bulkIncludeAudio) {
  175. foreach ($this->structs[$domain_key]['audio'] as $key=>$file) {
  176. $this->content[$domain][$key."20.audio"] = sprintf(
  177. '<a href="%s" class="audio">%s</a><br>',
  178. $file, $key
  179. );
  180. }
  181. }
  182. foreach($this->structs[$domain_key]['csv'] as $key=>$file) {
  183. $csv = new \Modules\Ography($file,TRUE);
  184. $str="<table>";
  185. foreach($csv->entries as $entry) {
  186. $tmp="";
  187. foreach($entry as $key=>$value) {
  188. $tmp .= sprintf("<td class=\"%s\">%s</td>", $key, $value);
  189. }
  190. $str .= sprintf("<tr>%s</tr>",$tmp);
  191. }
  192. $str.="</table>";
  193. $this->content[$domain][$key."30.csv"] = $str;
  194. }
  195. $content_order = 2;
  196. switch ($content_order) {
  197. case 0:
  198. // don't do any processing
  199. // content types appear together
  200. // but are not enclosed in a div
  201. break;
  202. case 1;
  203. // all content files appear in alphabetical order
  204. ksort($this->content[$domain]);
  205. break;
  206. case 2:
  207. // all content files appear in alphabetical order
  208. // groups of same content types are enclosed in a div
  209. ksort($this->content[$domain]);
  210. $prev = null;
  211. foreach ($this->content[$domain] as $key=>$value) {
  212. $html = "";
  213. $type = array_pop(explode('.',$key));
  214. if ($type == $prev) {
  215. continue;
  216. } elseif ($prev != null) {
  217. $html = "</div>";
  218. }
  219. $html .= "<div class=\"source-file-type-$type-container\">";
  220. $this->content[$domain][$key] = $html.$value;
  221. $prev = $type;
  222. }
  223. $this->content[$domain][] = "</div>";
  224. }
  225. }
  226. }
  227. //////////////////////
  228. // read config data //
  229. //////////////////////
  230. function read_config($domain=false) {
  231. foreach ($this->domains as $source=>$destination) {
  232. if (is_string($domain)) {
  233. if ($source != $domain) { continue; }
  234. } elseif (is_array($domain)) {
  235. if (!in_array($source,$domain)) { continue; }
  236. }
  237. foreach ($this->structs[$source]['txt'] as $key=>$file) {
  238. $this->read_textfile($file);
  239. }
  240. }
  241. return $this->config;
  242. }
  243. ////////////////
  244. // recursions //
  245. ////////////////
  246. function search_up($key,$paths,$ext) {
  247. $return = "";
  248. if(count($paths) == 2) {
  249. $current = $paths[0];
  250. $last_try = $paths[1];
  251. $ls=scandir($current);
  252. foreach($ls as $f) {
  253. if(!strncmp($f,'.',1)) continue; // ignore hidden files
  254. $ex=explode(".", $f);
  255. if(in_array(strtolower(end($ex)),$ext)) {
  256. if($ex[0]==$key) {
  257. $return = $current.$f;
  258. break;
  259. }
  260. }
  261. }
  262. }
  263. if ($return) {
  264. return $return;
  265. } elseif($current == $last_try) {
  266. return false;
  267. } else {
  268. $p = explode('/',$current);
  269. array_pop($p);
  270. array_pop($p);
  271. return self::search_up($key,array(implode("/",$p)."/",$last_try),$ext);
  272. }
  273. }
  274. ///////////////////////
  275. // Utility functions //
  276. ///////////////////////
  277. function read_textfile($file) {
  278. debug("about to read file: $file");
  279. $str = file_get_contents($file);
  280. debug("read file: $file");
  281. $str = self::linkify($str);
  282. $str = self::strip_comments($str);
  283. $str = self::get_config_from_content($str);
  284. debug("processed file: $file");
  285. return $str;
  286. }
  287. function strip_comments($str) {
  288. $single_line_comments = "/(^;.*\R)/m";
  289. $str = preg_replace($single_line_comments,"",$str);
  290. $multi_line_comments = "/\/\*.*?\*\//s";
  291. $str = preg_replace($multi_line_comments,"",$str);
  292. return $str;
  293. }
  294. function linkify($string) {
  295. $pattern = "/\s@(\w+)[=]([\w,]+)\s/";
  296. $count = 0;
  297. $new = preg_replace_callback
  298. ($pattern,
  299. function($m){
  300. $f3 = \Base::instance();
  301. return $f3->get('SITE_URL')
  302. .$f3->alias($m[1],self::$keyword."=".$m[2])
  303. ;},
  304. $string);
  305. return $new;
  306. }
  307. function get_config_from_content($string) {
  308. $f3 = \Base::instance();
  309. $f = 0;
  310. $tmp = null;
  311. $pattern = "/#\+(\w+):\s?(.*)/";
  312. $f = preg_match_all($pattern, $string,$matches,PREG_PATTERN_ORDER);
  313. for ($i=0;$i<$f;$i++) {
  314. $string = str_replace($matches[0][$i],"",$string);
  315. $key = $matches[1][$i];
  316. $value = trim($matches[2][$i]);
  317. if(strtolower($value) == "false") {
  318. $value = FALSE;
  319. }
  320. if(!strncmp(trim($value),'@',1)) {
  321. //var_dump($f3->get('DATA'));
  322. if (array_key_exists($key,$f3->get('DATA'))) {
  323. $DATA = $f3->get('DATA.'.$key);
  324. $conf = array($DATA['type'],$DATA['dir']);
  325. $relation = new \Modules\TOC($conf,$f3->get('CONTENT'),substr($value,1));
  326. $relation->dispatch();
  327. $this->config[$key]=array_shift($relation->entries);
  328. } else {
  329. $this->config[$key]=$value;
  330. }
  331. } else {
  332. if (array_key_exists($key, $this->config)) {
  333. if (is_array($this->config[$key])) {
  334. $this->config[$key][]=$value;
  335. } else {
  336. $tmp = $this->config[$key];
  337. $this->config[$key] = [$tmp,$value];
  338. $tmp=null;
  339. }
  340. } else {
  341. $this->config[$key]=$value;
  342. }
  343. }
  344. }
  345. $pattern = "/§>\s*(\w+):(.*?)\R[\011\040]*\R/s";
  346. $f = preg_match_all($pattern, $string,$matches,PREG_PATTERN_ORDER);
  347. for ($i=0;$i<$f;$i++) {
  348. $string = str_replace($matches[0][$i],"",$string);
  349. $key = $matches[1][$i];
  350. $value = trim($matches[2][$i]);
  351. if(strtolower($value) == "false") {
  352. $value = FALSE;
  353. }
  354. if (!strncmp($value,'@',1)) {
  355. # var_dump();
  356. if (array_key_exists($key,$f3->get('DATA'))) {
  357. $entries = explode("@",$value);
  358. array_shift($entries); // first entry is always empty
  359. $DATA = $f3->get('DATA.'.$key);
  360. $conf = array($DATA['type'],$DATA['dir']);
  361. $relation = new \Modules\TOC($conf,$f3->get('CONTENT'),$entries);
  362. $relation->dispatch();
  363. if(/*count($entries) >*/ 1) {
  364. $this->config[$key]= new CMultiple($relation->entries);
  365. } else {
  366. $this->config[$key]=array_shift($relation->entries);
  367. }
  368. } else {
  369. $this->config[$key]=$value;
  370. }
  371. } else {
  372. $this->config[$key]=$value;
  373. }
  374. }
  375. return $string;
  376. }
  377. function content_element_dispatcher($string) {
  378. $f3 = \Base::instance();
  379. $ED = new ElementDispatcher($this->folder,$this->config,$this->structs,$this->content,$this->domains);
  380. $string = $ED->dispatch($string);
  381. return $string;
  382. }
  383. static function warn($message) {
  384. return sprintf("<div class=\"warning\">%s</div>",$message);
  385. }
  386. }