pico.php 5.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213
  1. <?php
  2. /**
  3. * Pico
  4. *
  5. * @author Gilbert Pellegrom
  6. * @link http://pico.dev7studios.com/
  7. * @license http://opensource.org/licenses/MIT
  8. * @version 0.4.1
  9. */
  10. class Pico {
  11. /**
  12. * The constructor carries out all the processing in Pico.
  13. * Does URL routing, Markdown processing and Twig processing.
  14. */
  15. function __construct()
  16. {
  17. // Get request url and script url
  18. $url = '';
  19. $request_url = (isset($_SERVER['REQUEST_URI'])) ? $_SERVER['REQUEST_URI'] : '';
  20. $script_url = (isset($_SERVER['PHP_SELF'])) ? $_SERVER['PHP_SELF'] : '';
  21. // Get our url path and trim the / of the left and the right
  22. if($request_url != $script_url) $url = trim(preg_replace('/'. str_replace('/', '\/', str_replace('index.php', '', $script_url)) .'/', '', $request_url, 1), '/');
  23. // Get the file path
  24. if($url) $file = CONTENT_DIR . $url;
  25. else $file = CONTENT_DIR .'index';
  26. // Load the file
  27. if(is_dir($file)) $file = CONTENT_DIR . $url .'/index'. CONTENT_EXT;
  28. else $file .= CONTENT_EXT;
  29. if(file_exists($file)) $content = file_get_contents($file);
  30. else {
  31. $content = file_get_contents(CONTENT_DIR .'404'. CONTENT_EXT);
  32. header($_SERVER['SERVER_PROTOCOL'].' 404 Not Found');
  33. }
  34. $meta = $this->read_file_meta($content);
  35. $content = preg_replace('#/\*.+?\*/#s', '', $content); // Remove comments and meta
  36. $content = $this->parse_content($content);
  37. // Load the settings
  38. $settings = $this->get_config();
  39. $env = array('autoescape' => false);
  40. if($settings['enable_cache']) $env['cache'] = CACHE_DIR;
  41. // Get all the pages
  42. $pages = $this->get_pages($settings['base_url']);
  43. // Load the theme
  44. Twig_Autoloader::register();
  45. $loader = new Twig_Loader_Filesystem(THEMES_DIR . $settings['theme']);
  46. $twig = new Twig_Environment($loader, $env);
  47. echo $twig->render('index.html', array(
  48. 'config' => $settings,
  49. 'base_dir' => rtrim(ROOT_DIR, '/'),
  50. 'base_url' => $settings['base_url'],
  51. 'theme_dir' => THEMES_DIR . $settings['theme'],
  52. 'theme_url' => $settings['base_url'] .'/'. basename(THEMES_DIR) .'/'. $settings['theme'],
  53. 'site_title' => $settings['site_title'],
  54. 'meta' => $meta,
  55. 'content' => $content,
  56. 'pages' => $pages
  57. ));
  58. }
  59. /**
  60. * Parses the content using Markdown
  61. *
  62. * @param string $content the raw txt content
  63. * @return string $content the Markdown formatted content
  64. */
  65. function parse_content($content)
  66. {
  67. $content = str_replace('%base_url%', $this->base_url(), $content);
  68. $content = Markdown($content);
  69. return $content;
  70. }
  71. /**
  72. * Parses the file meta from the txt file header
  73. *
  74. * @param string $content the raw txt content
  75. * @return array $headers an array of meta values
  76. */
  77. function read_file_meta($content)
  78. {
  79. $headers = array(
  80. 'title' => 'Title',
  81. 'description' => 'Description',
  82. 'robots' => 'Robots'
  83. );
  84. foreach ($headers as $field => $regex){
  85. if (preg_match('/^[ \t\/*#@]*' . preg_quote($regex, '/') . ':(.*)$/mi', $content, $match) && $match[1]){
  86. $headers[ $field ] = trim(preg_replace("/\s*(?:\*\/|\?>).*/", '', $match[1]));
  87. } else {
  88. $headers[ $field ] = '';
  89. }
  90. }
  91. return $headers;
  92. }
  93. /**
  94. * Loads the config
  95. *
  96. * @return array $config an array of config values
  97. */
  98. function get_config()
  99. {
  100. if(!file_exists(ROOT_DIR .'config.php')) return array();
  101. global $config;
  102. require_once(ROOT_DIR .'config.php');
  103. $defaults = array(
  104. 'site_title' => 'Pico',
  105. 'base_url' => $this->base_url(),
  106. 'theme' => 'default',
  107. 'enable_cache' => false
  108. );
  109. if(is_array($config)) $config = array_merge($defaults, $config);
  110. else $config = $defaults;
  111. return $config;
  112. }
  113. /**
  114. * Get a list of pages
  115. *
  116. * @param string $base_url the base URL of the site
  117. * @return array $pages an array of pages
  118. */
  119. function get_pages($base_url)
  120. {
  121. $pages = $this->glob_recursive(CONTENT_DIR .'*'. CONTENT_EXT);
  122. foreach($pages as $key=>$page){
  123. // Skip 404
  124. if(basename($page) == '404'. CONTENT_EXT){
  125. unset($pages[$key]);
  126. continue;
  127. }
  128. // Get title and format $page
  129. $page_content = file_get_contents($page);
  130. $page_meta = $this->read_file_meta($page_content);
  131. $url = str_replace(CONTENT_DIR, $base_url .'/', $page);
  132. $url = str_replace('index'. CONTENT_EXT, '', $url);
  133. $url = str_replace(CONTENT_EXT, '', $url);
  134. $pages[$key] = array(
  135. 'title' => $page_meta['title'],
  136. 'url' => $url
  137. );
  138. }
  139. return $pages;
  140. }
  141. /**
  142. * Helper function to work out the base URL
  143. *
  144. * @return string the base url
  145. */
  146. function base_url()
  147. {
  148. global $config;
  149. if(isset($config['base_url']) && $config['base_url']) return $config['base_url'];
  150. $url = '';
  151. $request_url = (isset($_SERVER['REQUEST_URI'])) ? $_SERVER['REQUEST_URI'] : '';
  152. $script_url = (isset($_SERVER['PHP_SELF'])) ? $_SERVER['PHP_SELF'] : '';
  153. if($request_url != $script_url) $url = trim(preg_replace('/'. str_replace('/', '\/', str_replace('index.php', '', $script_url)) .'/', '', $request_url, 1), '/');
  154. $protocol = $this->get_protocol();
  155. return rtrim(str_replace($url, '', $protocol . "://" . $_SERVER['HTTP_HOST'] . $_SERVER['REQUEST_URI']), '/');
  156. }
  157. /**
  158. * Tries to guess the server protocol. Used in base_url()
  159. *
  160. * @return string the current protocol
  161. */
  162. function get_protocol()
  163. {
  164. preg_match("|^HTTP[S]?|is",$_SERVER['SERVER_PROTOCOL'],$m);
  165. return strtolower($m[0]);
  166. }
  167. /**
  168. * Helper function to make glob recursive
  169. *
  170. * @param string $pattern glob pattern
  171. * @param int $flags glob flags
  172. * @return array the matched files/directories
  173. */
  174. function glob_recursive($pattern, $flags = 0)
  175. {
  176. $files = glob($pattern, $flags);
  177. foreach(glob(dirname($pattern).'/*', GLOB_ONLYDIR|GLOB_NOSORT) as $dir){
  178. $files = array_merge($files, $this->glob_recursive($dir.'/'.basename($pattern), $flags));
  179. }
  180. return $files;
  181. }
  182. }
  183. ?>