mostly filebased Content Presentation System
Ви не можете вибрати більше 25 тем Теми мають розпочинатися з літери або цифри, можуть містити дефіси (-) і не повинні перевищувати 35 символів.

2 роки тому
4 роки тому
4 роки тому
4 роки тому
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422
  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. }