/_app/statamic/statamic.php

https://bitbucket.org/andymoogaloo/beamarshall · PHP · 1126 lines · 120 code · 32 blank · 974 comment · 49 complexity · 5112780a0cd6f44a5d7848c4b85edc85 MD5 · raw file

  1. <?php
  2. /**
  3. * Statamic
  4. *
  5. * @author Mubashar Iqbal
  6. * @author Jack McDade
  7. * @copyright 2012 Statamic
  8. * @link http://www.statamic.com
  9. * @license http://www.statamic.com
  10. *
  11. */
  12. if ( ! defined('STATAMIC_VERSION')) define('STATAMIC_VERSION', '1.3');
  13. class Statamic {
  14. protected static $_yaml_cache = array();
  15. public static $publication_states = array('live' => 'Live', 'draft' => 'Draft', 'hidden' => 'Hidden');
  16. public static $numerical_regex = "/\d+(\.|\-|\_)/";
  17. public static $date_regex = "/\d{4}(-|_|\.)\d{2}(-|_|\.)\d{2}(-|_|\.)/";
  18. public static $datetime_regex = "/\d{4}(-|_|\.)\d{2}(-|_|\.)\d{2}(-|_|\.)\d{4}(-|_|\.)/";
  19. public static function loadYamlCached($content) {
  20. $yaml = array();
  21. $hash = md5($content);
  22. if (isset(self::$_yaml_cache[$hash])) {
  23. $yaml = self::$_yaml_cache[$hash];
  24. } else {
  25. $yaml = Spyc::YAMLLoad($content);
  26. self::$_yaml_cache[$hash] = $yaml;
  27. }
  28. return $yaml;
  29. }
  30. public static function load_all_configs() {
  31. // do all the other files then do the settings
  32. $pattern = "_config/*.yaml";
  33. $list = glob($pattern);
  34. $config = array();
  35. $file_config = Spyc::YAMLLoad('_config/settings.yaml');
  36. $config += $file_config;
  37. $routes = array();
  38. if (file_exists('_config/routes.yaml')) {
  39. $routes['_routes'] = Spyc::YAMLLoad('_config/routes.yaml');
  40. }
  41. if ($list) {
  42. foreach ($list as $name) {
  43. if ( ! Statamic_Helper::ends_with($name, "_config/settings.yaml")
  44. && ! Statamic_Helper::ends_with($name, "_config/routes.yaml") ) {
  45. $file_config = Spyc::YAMLLoad($name);
  46. $config = array_merge($config, $file_config, $routes);
  47. }
  48. }
  49. }
  50. return $config;
  51. }
  52. public static function get_site_root() {
  53. // default: default
  54. $app = \Slim\Slim::getInstance();
  55. if (isset($app->config['_site_root'])) {
  56. return $app->config['_site_root'];
  57. }
  58. return "/";
  59. }
  60. public static function get_site_url() {
  61. // default: default
  62. $app = \Slim\Slim::getInstance();
  63. if (isset($app->config['_site_url'])) {
  64. return $app->config['_site_url'];
  65. }
  66. return "";
  67. }
  68. public static function get_site_name() {
  69. // default: default
  70. $app = \Slim\Slim::getInstance();
  71. if (isset($app->config['_site_name'])) {
  72. return $app->config['_site_name'];
  73. }
  74. return "";
  75. }
  76. public static function get_license_key() {
  77. $app = \Slim\Slim::getInstance();
  78. if (isset($app->config['_license_key'])) {
  79. return $app->config['_license_key'];
  80. }
  81. return '';
  82. }
  83. public static function get_theme_name() {
  84. // default: default
  85. $app = \Slim\Slim::getInstance();
  86. if (isset($app->config['_theme'])) {
  87. return $app->config['_theme'];
  88. }
  89. return "default";
  90. }
  91. public static function get_theme_type() {
  92. // default: lex
  93. $app = \Slim\Slim::getInstance();
  94. if (isset($app->config['theme_type'])) {
  95. return $app->config['theme_type'];
  96. }
  97. return "lex";
  98. }
  99. public static function get_theme() {
  100. // default: default
  101. $app = \Slim\Slim::getInstance();
  102. if (isset($app->config['_theme'])) {
  103. return $app->config['_theme'];
  104. }
  105. return "default";
  106. }
  107. public static function get_theme_assets_path() {
  108. // default: default
  109. $app = \Slim\Slim::getInstance();
  110. if (isset($app->config['_theme_assets_path'])) {
  111. return $app->config['_theme_assets_path'];
  112. }
  113. return "";
  114. }
  115. public static function get_theme_path() {
  116. // default: default
  117. $app = \Slim\Slim::getInstance();
  118. if (isset($app->config['theme_path'])) {
  119. return $app->config['theme_path'];
  120. }
  121. return "_themes/".self::get_theme_name()."/";
  122. }
  123. public static function get_templates_path() {
  124. // default: default
  125. $app = \Slim\Slim::getInstance();
  126. if (isset($app->config['templates.path'])) {
  127. return $app->config['templates.path'];
  128. }
  129. return "./_themes/".self::get_theme_name()."/";
  130. }
  131. public static function get_admin_path() {
  132. $app = \Slim\Slim::getInstance();
  133. if (isset($app->config['_admin_path'])) {
  134. return Statamic_helper::reduce_double_slashes(ltrim($app->config['_admin_path'], '/').'/');
  135. }
  136. return "admin/";
  137. }
  138. public static function get_addon_path($addon=null) {
  139. $addon_path = Statamic_helper::reduce_double_slashes(self::get_site_root()."_add-ons/".$addon."/");
  140. return $addon_path;
  141. }
  142. public static function get_content_root() {
  143. // default: content
  144. $app = \Slim\Slim::getInstance();
  145. if (isset($app->config['_content_root'])) {
  146. return $app->config['_content_root'];
  147. }
  148. return "_content";
  149. }
  150. public static function get_content_type() {
  151. $app = \Slim\Slim::getInstance();
  152. $content_type = 'md'; # default: markdown
  153. if (isset($app->config['_content_type']) && $app->config['_content_type'] != 'markdown') {
  154. $content_type = $app->config['_content_type'] == "markdown_edge" ? "md" : $app->config['_content_type'];
  155. }
  156. return $content_type;
  157. }
  158. public static function get_date_format() {
  159. // default: Ymd
  160. $app = \Slim\Slim::getInstance();
  161. if (isset($app->config['_date_format'])) {
  162. return $app->config['_date_format'];
  163. }
  164. return "Y-m-d";
  165. }
  166. public static function get_time_format() {
  167. // default: Ymd
  168. $app = \Slim\Slim::getInstance();
  169. if (isset($app->config['_time_format'])) {
  170. return $app->config['_time_format'];
  171. }
  172. return "h:ia";
  173. }
  174. public static function get_entry_timestamps() {
  175. $app = \Slim\Slim::getInstance();
  176. if (isset($app->config['_entry_timestamps'])) {
  177. return (bool) $app->config['_entry_timestamps'];
  178. }
  179. return false;
  180. }
  181. public static function get_setting($setting, $default = false){
  182. $app = \Slim\Slim::getInstance();
  183. if (isset($app->config[$setting])) {
  184. return $app->config[$setting];
  185. }
  186. return $default;
  187. }
  188. public static function get_entry_type($path) {
  189. $type = 'none';
  190. $content_root = Statamic::get_content_root();
  191. if (file_exists("{$content_root}/{$path}/fields.yaml")) {
  192. $fields_raw = file_get_contents("{$content_root}/{$path}/fields.yaml");
  193. $fields_data = Spyc::YAMLLoad($fields_raw);
  194. if (isset($fields_data['type']['prefix'])) {
  195. $type = $fields_data['type']['prefix'];
  196. }
  197. }
  198. return $type;
  199. }
  200. # @todo: make recursive/helper
  201. public static function get_templates_list() {
  202. $templates = array();
  203. $folder = "_themes/".self::get_theme_name()."/templates/*";
  204. $list = glob($folder);
  205. if ($list) {
  206. foreach ($list as $name) {
  207. if (is_dir($name)) {
  208. $folder_array = explode('/',rtrim($name,'/'));
  209. $folder_name = end($folder_array);
  210. $sub_list = glob($name.'/*');
  211. foreach ($sub_list as $sub_name) {
  212. $start = strrpos($sub_name, "/")+1;
  213. $end = strrpos($sub_name, ".");
  214. $templates[] = $folder_name.'/'.substr($sub_name, $start, $end-$start);
  215. }
  216. } else {
  217. $start = strrpos($name, "/")+1;
  218. $end = strrpos($name, ".");
  219. $templates[] = substr($name, $start, $end-$start);
  220. }
  221. }
  222. }
  223. return $templates;
  224. }
  225. public static function get_layouts_list() {
  226. $templates = array();
  227. $folder = "_themes/".self::get_theme_name()."/layouts/*";
  228. $list = glob($folder);
  229. if ($list) {
  230. foreach ($list as $name) {
  231. $start = strrpos($name, "/")+1;
  232. $end = strrpos($name, ".");
  233. $templates[] = substr($name, $start, $end-$start);
  234. }
  235. }
  236. return $templates;
  237. }
  238. public static function get_pagination_variable() {
  239. $app = \Slim\Slim::getInstance();
  240. $var = 'page'; # default: page
  241. if (isset($app->config['_pagination_variable'])) {
  242. $var = $app->config['_pagination_variable'];
  243. }
  244. return $var;
  245. }
  246. public static function get_pagination_style() {
  247. $app = \Slim\Slim::getInstance();
  248. $var = 'prev_next'; # default: prev_next
  249. if (isset($app->config['_pagination_style'])) {
  250. $var = $app->config['_pagination_style'];
  251. }
  252. return $var;
  253. }
  254. public static function get_parse_order() {
  255. // default: default
  256. $app = \Slim\Slim::getInstance();
  257. if (isset($app->config['_parse_order'])) {
  258. return $app->config['_parse_order'];
  259. }
  260. return array('tags', 'content');
  261. }
  262. public static function is_content_writable() {
  263. $content_root = self::get_content_root();
  264. if (is_writable($content_root)) {
  265. return true;
  266. }
  267. return false;
  268. }
  269. public static function are_users_writable() {
  270. if (is_writable('_config/users/')) {
  271. return true;
  272. }
  273. return false;
  274. }
  275. public static function content_exists($slug, $folder=null) {
  276. $app = \Slim\Slim::getInstance();
  277. $initialize = $app->config;
  278. $site_root = self::get_site_root();
  279. $content_root = self::get_content_root();
  280. $content_type = self::get_content_type();
  281. $meta_raw = "";
  282. if ($folder) {
  283. if (file_exists("{$content_root}/{$folder}/{$slug}.{$content_type}")) {
  284. return true;
  285. }
  286. } else {
  287. if (file_exists("{$content_root}/{$slug}.{$content_type}")) {
  288. return true;
  289. }
  290. }
  291. return false;
  292. }
  293. public static function get_content_meta($slug, $folder=null, $raw=false, $parse=true) {
  294. $app = \Slim\Slim::getInstance();
  295. $initialize = $app->config;
  296. $site_root = self::get_site_root();
  297. $content_root = self::get_content_root();
  298. $content_type = self::get_content_type();
  299. $file = $folder ? "{$content_root}/{$folder}/{$slug}.{$content_type}" : "{$content_root}/{$slug}.{$content_type}";
  300. $file = Statamic_Helper::reduce_double_slashes($file);
  301. $meta_raw = file_exists($file) ? file_get_contents($file) : '';
  302. if (Statamic_Helper::ends_with($meta_raw, "---")) {
  303. $meta_raw .= "\n"; # prevent parse failure
  304. }
  305. # Parse YAML Front Matter
  306. if (stripos($meta_raw, "---") === FALSE) {
  307. //$meta = Spyc::YAMLLoad($meta_raw);
  308. $meta = self::loadYamlCached($meta_raw);
  309. $meta['content'] = "";
  310. if ($raw) {
  311. $meta['content_raw'] = "";
  312. }
  313. } else {
  314. list($yaml, $content) = preg_split("/---/", $meta_raw, 2, PREG_SPLIT_NO_EMPTY);
  315. $meta = self::loadYamlCached($yaml);
  316. if ($raw) {
  317. $meta['content_raw'] = $content;
  318. }
  319. // Parse the content if necessary
  320. $meta['content'] = $parse ? self::parse_content($content, $meta) : $content;
  321. }
  322. if (file_exists($file)) {
  323. $meta['last_modified'] = filemtime($file);
  324. }
  325. if ( ! $raw) {
  326. $meta['homepage'] = self::get_site_root();
  327. $meta['raw_url'] = $app->request()->getResourceUri();
  328. $meta['page_url'] = $app->request()->getResourceUri();
  329. # Is date formatted correctly?
  330. if (self::get_entry_timestamps() && Statamic_helper::is_datetime_slug($slug)) {
  331. $datetimestamp = Statamic_helper::get_datetimestamp($slug);
  332. $datestamp = Statamic_helper::get_datestamp($slug);
  333. $meta['datetimestamp'] = $datetimestamp;
  334. $meta['datestamp'] = $datestamp;
  335. $meta['date'] = date(self::get_date_format(), $datestamp);
  336. $meta['time'] = date(self::get_time_format(), $datetimestamp);
  337. $meta['page_url'] = preg_replace(self::$datetime_regex, '', $meta['page_url']); # clean url override
  338. } else if (Statamic_helper::is_date_slug($slug)) {
  339. $datestamp = Statamic_helper::get_datestamp($slug);
  340. $meta['datestamp'] = $datestamp;
  341. $meta['date'] = date(self::get_date_format(), $datestamp);
  342. $meta['page_url'] = preg_replace(self::$date_regex, '', $meta['page_url']); # clean url override
  343. } else if (Statamic_helper::is_numeric_slug($slug)) {
  344. $meta['numeric'] = Statamic_helper::get_numeric($slug);
  345. }
  346. $meta['permalink'] = Statamic_helper::reduce_double_slashes(Statamic::get_site_url().'/'.$meta['page_url']);
  347. $taxonomy_slugify = false;
  348. if (isset($app->config['_taxonomy_slugify'])) {
  349. if ($app->config['_taxonomy_slugify']) {
  350. $taxonomy_slugify = true;
  351. }
  352. }
  353. # Jam it all together, brother.
  354. # @todo: functionize/abstract this method for more flexibility and readability
  355. foreach($meta as $key => $value) {
  356. if (! is_array($value) && self::is_taxonomy($key)) {
  357. $value = array($value);
  358. $meta[$key] = $value;
  359. }
  360. if (is_array($value)) {
  361. $list = array();
  362. $url_list = array();
  363. $i = 1;
  364. $total_results = count($meta[$key]);
  365. foreach ($meta[$key] as $k => $v) {
  366. $url = null;
  367. if (self::is_taxonomy($key)) {
  368. if($taxonomy_slugify) {
  369. $url = Statamic_helper::reduce_double_slashes(strtolower($site_root.'/'.$folder.'/'.$key.'/'.Statamic_Helper::slugify($v)));
  370. } else {
  371. $url = Statamic_helper::reduce_double_slashes(strtolower($site_root.'/'.$folder.'/'.$key.'/'.$v));
  372. }
  373. $url = preg_replace(self::$numerical_regex, '', $url);
  374. $list[] = array(
  375. 'name' => $v,
  376. 'count' => $i,
  377. 'url' => $url,
  378. 'total_results' => $total_results,
  379. 'first' => $i == 1 ? TRUE : FALSE,
  380. 'last' => $i == $total_results ? TRUE : FALSE
  381. );
  382. $url_list[] = '<a href="'.$url.'">'.$v.'</a>';
  383. } elseif ( ! is_array($v)) {
  384. $list[] = array(
  385. 'name' => $v,
  386. 'count' => $i,
  387. 'url' => $url,
  388. 'total_results' => $total_results,
  389. 'first' => $i == 1 ? TRUE : FALSE,
  390. 'last' => $i == $total_results ? TRUE : FALSE
  391. );
  392. }
  393. $i++;
  394. }
  395. if ($url) {
  396. $meta[$key.'_url_list'] = implode(', ', $url_list);
  397. }
  398. if ( isset($meta[$key][0]) && ! is_array($meta[$key][0])) {
  399. $meta[$key.'_list'] = implode(', ', $meta[$key]);
  400. $meta[$key.'_option_list'] = implode('|', $meta[$key]);
  401. $meta[$key] = $list;
  402. }
  403. }
  404. }
  405. }
  406. return $meta;
  407. }
  408. public static function get_content_list($folder=null,$limit=null,$offset=0,$future=false,$past=true,$sort_by='date',$sort_dir='desc',$conditions=null,$switch=null,$skip_status=false,$parse=true,$since=null,$until=null) {
  409. $app = \Slim\Slim::getInstance();
  410. $content_type = self::get_content_type();
  411. $list = self::get_content_all($folder, $future, $past, $conditions, $skip_status, $parse, $since, $until);
  412. // default sort is by date
  413. if ($sort_by == 'title') {
  414. usort($list, "statamic_sort_by_title");
  415. } else if ($sort_by == 'random') {
  416. shuffle($list);
  417. }
  418. // default sort is asc
  419. if ($sort_dir == 'desc') {
  420. $list = array_reverse($list);
  421. }
  422. // handle offset/limit
  423. if ($offset > 0) {
  424. $list = array_splice($list, $offset);
  425. }
  426. if ($limit) {
  427. $list = array_splice($list, 0, $limit);
  428. }
  429. if ($switch) {
  430. $switch_vars = explode('|',$switch);
  431. $switch_count = count($switch_vars);
  432. $count = 1;
  433. foreach ($list as $key => $post) {
  434. $list[$key]['switch'] = $switch_vars[($count -1) % $switch_count];
  435. $count++;
  436. }
  437. }
  438. return $list;
  439. }
  440. public static function fetch_content_by_url($path) {
  441. $data = null;
  442. $content_root = Statamic::get_content_root();
  443. $content_type = Statamic::get_content_type();
  444. if (file_exists("{$content_root}/{$path}.{$content_type}") || is_dir("{$content_root}/{$path}")) {
  445. // endpoint or folder exists!
  446. } else {
  447. $path = Statamic_Helper::resolve_path($path);
  448. }
  449. if (file_exists("{$content_root}/{$path}.{$content_type}")) {
  450. $page = basename($path);
  451. $folder = substr($path, 0, (-1*strlen($page))-1);
  452. $data = Statamic::get_content_meta($page, $folder);
  453. } else if (is_dir("{$content_root}/{$path}")) {
  454. $data = Statamic::get_content_meta("page", $path);
  455. }
  456. return $data;
  457. }
  458. public static function get_next_numeric($folder=null) {
  459. $next = '01';
  460. $list = self::get_content_all($folder, true, true, null, true);
  461. if (sizeof($list) > 0) {
  462. $item = array_pop($list);
  463. $current = $item['numeric'];
  464. if ($current <> '') {
  465. $next = $current + 1;
  466. $format= '%1$0'.strlen($current).'d';
  467. $next = sprintf($format, $next);
  468. }
  469. }
  470. return $next;
  471. }
  472. public static function get_next_numeric_folder($folder=null) {
  473. $next = '01';
  474. $list = self::get_content_tree($folder,1,1,true,false,true);
  475. if (sizeof($list) > 0) {
  476. $item = array_pop($list);
  477. if (isset($item['numeric'])) {
  478. $current = $item['numeric'];
  479. if ($current <> '') {
  480. $next = $current + 1;
  481. $format= '%1$0'.strlen($current).'d';
  482. $next = sprintf($format, $next);
  483. }
  484. }
  485. }
  486. return $next;
  487. }
  488. public static function get_content_count($folder=null,$future=false,$past=true,$conditions=null,$since=null,$until=null) {
  489. return sizeof(self::get_content_all($folder, $future, $past, $conditions,false,false, $since, $until));
  490. }
  491. public static function get_content_all($folder=null,$future=false,$past=true,$conditions=null,$skip_status=false,$parse=true,$since=null,$until=null) {
  492. $app = \Slim\Slim::getInstance();
  493. $content_type = self::get_content_type();
  494. $site_root = self::get_site_root();
  495. $absolute_folder = Statamic_helper::resolve_path($folder);
  496. $posts = self::get_file_list($absolute_folder);
  497. $list = array();
  498. foreach ($posts as $key => $post)
  499. {
  500. // starts with numeric value
  501. unset($list[$key]);
  502. if ((preg_match(self::$date_regex, $key) || preg_match(self::$numerical_regex, $key)) && file_exists($post.".{$content_type}")) {
  503. $data = Statamic::get_content_meta($key, $absolute_folder, false, $parse);
  504. $list[$key] = $data;
  505. $list[$key]['slug'] = $site_root.'/'.$key;
  506. $list[$key]['url'] = $folder ? $site_root.$folder."/".$key : $site_root.$key;
  507. $list[$key]['raw_url'] = $list[$key]['url'];
  508. $date_entry = false;
  509. if (self::get_entry_timestamps() && Statamic_helper::is_datetime_slug($key)) {
  510. $datestamp = Statamic_helper::get_datestamp($key);
  511. $date_entry = true;
  512. # strip the date
  513. $list[$key]['slug'] = substr($key, 16);
  514. $list[$key]['url'] = preg_replace(self::$datetime_regex, '', $list[$key]['url']); #override
  515. $list[$key]['datestamp'] = $data['datestamp'];
  516. $list[$key]['date'] = $data['date'];
  517. } else if (Statamic_helper::is_date_slug($key)) {
  518. $datestamp = Statamic_helper::get_datestamp($key);
  519. $date_entry = true;
  520. # strip the date
  521. $list[$key]['slug'] = substr($key, 11);
  522. $list[$key]['url'] = preg_replace(self::$date_regex, '', $list[$key]['url']); #override
  523. $list[$key]['datestamp'] = $data['datestamp'];
  524. $list[$key]['date'] = $data['date'];
  525. } else {
  526. $list[$key]['slug'] = substr($key, strpos($key, '.')+1);
  527. $list[$key]['url'] = preg_replace(self::$numerical_regex, '', $list[$key]['url']); #override
  528. }
  529. # fully qualified url
  530. $list[$key]['permalink'] = Statamic_helper::reduce_double_slashes(Statamic::get_site_url().'/'.$list[$key]['url']);
  531. /* $content = preg_replace('/<img(.*)src="(.*?)"(.*)\/?>/', '<img \/1 src="'.Statamic::get_asset_path(null).'/\2" /\3 />', $data['content']); */
  532. //$list[$key]['content'] = Statamic::transform_content($data['content']);
  533. if (!$skip_status) {
  534. if (isset($data['status']) && $data['status'] != 'live') {
  535. unset($list[$key]);
  536. }
  537. }
  538. // Remove future entries
  539. if ($date_entry && $future === FALSE && $datestamp > strtotime(date("Y-m-d"))) {
  540. unset($list[$key]);
  541. }
  542. // Remove past entries
  543. if ($date_entry && $past === FALSE && $datestamp < strtotime(date("Y-m-d"))) {
  544. unset($list[$key]);
  545. }
  546. // Remove entries before $since
  547. if ($date_entry && !is_null($since) && $datestamp < strtotime($since)) {
  548. unset($list[$key]);
  549. }
  550. // Remove entries after $until
  551. if ($date_entry && !is_null($until) && $datestamp > strtotime($until)) {
  552. unset($list[$key]);
  553. }
  554. if ($conditions) {
  555. $keepers = array();
  556. $conditions_array = explode(",", $conditions);
  557. foreach ($conditions_array as $condition) {
  558. $condition = trim($condition);
  559. $inclusive = true;
  560. list($condition_key, $condition_values) = explode(":", $condition);
  561. # yay php!
  562. $pos = strpos($condition_values, 'not ');
  563. if ($pos === FALSE) {
  564. } else {
  565. if ($pos == 0) {
  566. $inclusive = false;
  567. $condition_values = substr($condition_values, 4);
  568. }
  569. }
  570. $condition_values = explode("|", $condition_values);
  571. foreach ($condition_values as $k => $condition_value) {
  572. $keep = false;
  573. if (isset($list[$key][$condition_key])) {
  574. if (is_array($list[$key][$condition_key])) {
  575. foreach ($list[$key][$condition_key] as $key2 => $value2) {
  576. #todo add regex driven taxonomy matching here
  577. if ($inclusive) {
  578. if (strtolower($value2['name']) == strtolower($condition_value)) {
  579. $keepers[$key] = $key;
  580. break;
  581. }
  582. } else {
  583. if (strtolower($value2['name']) != strtolower($condition_value)) {
  584. $keepers[$key] = $key;
  585. } else {
  586. // EXCLUDE!
  587. unset($keepers[$key]);
  588. break;
  589. }
  590. }
  591. }
  592. } else {
  593. if ($list[$key][$condition_key] == $condition_value) {
  594. if ($inclusive) {
  595. $keepers[$key] = $key;
  596. } else {
  597. unset($keepers[$key]);
  598. }
  599. } else {
  600. if ( ! $inclusive) {
  601. $keepers[$key] = $key;
  602. }
  603. }
  604. }
  605. } else {
  606. $keep = false;
  607. }
  608. }
  609. if ( ! $keep && ! in_array($key, $keepers)) {
  610. unset($list[$key]);
  611. }
  612. }
  613. }
  614. }
  615. }
  616. return $list;
  617. }
  618. public static function get_content_tree($directory='/',$depth=1,$max_depth=5,$folders_only=false,$include_entries=false,$hide_hidden=true,$include_content=false,$site_root=false) {
  619. // $folders_only=true only page.md
  620. // folders_only=false includes any numbered or non-numbered page (excluding anything with a fields.yaml file)
  621. // if include_entries is true then any numbered files are included
  622. $app = \Slim\Slim::getInstance();
  623. $content_root = self::get_content_root();
  624. $content_type = self::get_content_type();
  625. $site_root = $site_root ? $site_root : self::get_site_root();
  626. $current_url = Statamic_helper::reduce_double_slashes($site_root.'/'.$app->request()->getResourceUri());
  627. $taxonomy_url = FALSE;
  628. if (self::is_taxonomy_url($current_url)) {
  629. list($taxonomy_type, $taxonomy_name) = self::get_taxonomy_criteria($current_url);
  630. $taxonomy_url = self::remove_taxonomy_from_path($current_url, $taxonomy_type, $taxonomy_name);
  631. }
  632. $directory = '/'.$directory.'/'; #ensure proper slashing
  633. $base = '';
  634. if ($directory <> '/') {
  635. $base = Statamic_helper::reduce_double_slashes("{$content_root}/{$directory}");
  636. } else if ($directory == '/') {
  637. $base = "{$content_root}";
  638. } else {
  639. $base = "{$content_root}";
  640. }
  641. $files = glob("{$base}/*");
  642. $data = array();
  643. if ($files) {
  644. foreach($files as $path) {
  645. $current_name = basename($path);
  646. if (!Statamic_helper::starts_with($current_name, '_') && !Statamic_helper::ends_with($current_name, '.yaml')) {
  647. $node = array();
  648. $file = substr($path, strlen($base)+1, strlen($path)-strlen($base)-strlen($content_type)-2);
  649. if (is_dir($path)) {
  650. $folder = substr($path, strlen($base)+1);
  651. $node['type'] = 'folder';
  652. $node['slug'] = basename($folder);
  653. $node['title'] = ucwords(basename($folder));
  654. $node['numeric'] = Statamic_helper::get_numeric($folder);
  655. $node['file_path'] = Statamic_helper::reduce_double_slashes($site_root.'/'.$directory.'/'.$folder.'/page');
  656. if (Statamic_helper::is_numeric_slug($folder)) {
  657. $pos = stripos($folder, ".");
  658. if ($pos !== false) {
  659. $node['raw_url'] = Statamic_helper::reduce_double_slashes(
  660. Statamic_helper::remove_numerics_from_path(
  661. $site_root.'/'.$directory.'/'.$folder
  662. )
  663. );
  664. $node['url'] = rtrim(preg_replace(self::$numerical_regex, '', $node['raw_url']),'/');
  665. $node['title'] = ucwords(basename(substr($folder, $pos+1)));
  666. } else {
  667. $node['title'] = ucwords(basename($folder));
  668. $node['raw_url'] = Statamic_helper::reduce_double_slashes($site_root.'/'.$directory.'/'.$folder);
  669. $node['url'] = rtrim(preg_replace(self::$numerical_regex, '', $node['raw_url']),'/');
  670. }
  671. } else {
  672. $node['title'] = ucwords(basename($folder));
  673. $node['raw_url'] = Statamic_helper::reduce_double_slashes($site_root.'/'.$directory.'/'.$folder);
  674. $node['url'] = rtrim(preg_replace(self::$numerical_regex, '', $node['raw_url']), '/');
  675. }
  676. $node['depth'] = $depth;
  677. $node['children'] = $depth < $max_depth ? self::get_content_tree($directory.$folder.'/', $depth+1, $max_depth, $folders_only, $include_entries, $hide_hidden, $include_content, $site_root) : null;
  678. $node['is_current'] = $node['raw_url'] == $current_url || $node['url'] == $current_url ? TRUE : FALSE;
  679. $node['is_parent'] = FALSE;
  680. if ($node['url'] == Statamic_helper::pop_last_segment($current_url) || ($taxonomy_url && $node['url'] == $taxonomy_url)) {
  681. $node['is_parent'] = TRUE;
  682. }
  683. $node['has_children'] = $node['children'] ? TRUE : FALSE;
  684. // has entries?
  685. if (file_exists(Statamic_helper::reduce_double_slashes($path."/fields.yaml"))) {
  686. $node['has_entries'] = TRUE;
  687. } else {
  688. $node['has_entries'] = FALSE;
  689. }
  690. $meta = self::get_content_meta("page", Statamic_helper::reduce_double_slashes($directory."/".$folder), false, true);
  691. //$meta = self::get_content_meta("page", Statamic_helper::reduce_double_slashes($directory."/".$folder));
  692. if (isset($meta['title'])) {
  693. $node['title'] = $meta['title'];
  694. }
  695. if (isset($meta['last_modified'])) {
  696. $node['last_modified'] = $meta['last_modified'];
  697. }
  698. if ($hide_hidden === true && (isset($meta['status']) && (($meta['status'] == 'hidden' || $meta['status'] == 'draft')))) {
  699. // placeholder condition
  700. } else {
  701. $data[] = $include_content ? array_merge($meta, $node) : $node;
  702. // print_r($data);
  703. }
  704. } else {
  705. if (Statamic_helper::ends_with($path, $content_type)) {
  706. if ($folders_only == false) {
  707. if ($file == 'page' || $file == 'feed' || $file == '404') {
  708. // $node['url'] = $directory;
  709. // $node['title'] = basename($directory);
  710. // $meta = self::get_content_meta('page', substr($directory, 1));
  711. // $node['depth'] = $depth;
  712. } else {
  713. $include = true;
  714. // date based is never included
  715. if (self::get_entry_timestamps() && Statamic_helper::is_datetime_slug(basename($path))) {
  716. $include = false;
  717. } else if (Statamic_helper::is_date_slug(basename($path))) {
  718. $include = false;
  719. } else if (Statamic_helper::is_numeric_slug(basename($path))) {
  720. if ($include_entries == false) {
  721. if (file_exists(Statamic_helper::reduce_double_slashes(dirname($path)."/fields.yaml"))) {
  722. $include = false;
  723. }
  724. }
  725. }
  726. if ($include) {
  727. $node['type'] = 'file';
  728. $node['raw_url'] = Statamic_helper::reduce_double_slashes($directory).basename($path);
  729. $pretty_url = rtrim(preg_replace(self::$numerical_regex, '', $node['raw_url']),'/');
  730. $node['url'] = substr($pretty_url, 0, -1*(strlen($content_type)+1));
  731. $node['is_current'] = $node['url'] == $current_url || $node['url'] == $current_url ? TRUE : FALSE;
  732. $node['slug'] = substr(basename($path), 0, -1*(strlen($content_type)+1));
  733. $meta = self::get_content_meta(substr(basename($path), 0, -1*(strlen($content_type)+1)), substr($directory, 1), false, true);
  734. //$node['meta'] = $meta;
  735. if (isset($meta['title'])) $node['title'] = $meta['title'];
  736. $node['depth'] = $depth;
  737. if ($hide_hidden === true && (isset($meta['status']) && (($meta['status'] == 'hidden' || $meta['status'] == 'draft')))) {
  738. } else {
  739. $data[] = $include_content ? array_merge($meta, $node) : $node;
  740. }
  741. }
  742. }
  743. }
  744. }
  745. }
  746. }
  747. }
  748. }
  749. return $data;
  750. }
  751. public static function get_file_list($directory=null) {
  752. $content_root = self::get_content_root();
  753. $content_type = self::get_content_type();
  754. if ($directory) {
  755. $files = glob("{$content_root}{$directory}/*.{$content_type}");
  756. } else {
  757. $files = glob('{$content_root}*.{$content_type}');
  758. }
  759. $posts = array();
  760. if ($files) {
  761. foreach ($files as $file) {
  762. $len = strlen($content_type);
  763. $len = $len + 1;
  764. $len = $len * -1;
  765. $posts[substr(basename($file), 0, $len)] = substr($file, 0, $len);
  766. }
  767. }
  768. return $posts;
  769. }
  770. public static function find_prev($current,$folder=null,$future=false,$past=true) {
  771. if ($folder == '') {
  772. $folder = '/';
  773. }
  774. $list = Statamic::get_content_list($folder, null, 0, $future, $past);
  775. $keys = array_keys($list);
  776. $current_key = array_search($current, $keys);
  777. if ($current_key !== FALSE) {
  778. while (key($keys) !== $current_key) next($keys);
  779. return next($keys);
  780. }
  781. return FALSE;
  782. }
  783. public static function find_next($current,$folder=null,$future=false,$past=true) {
  784. if ($folder == '') {
  785. $folder = '/';
  786. }
  787. $list = Statamic::get_content_list($folder, null, 0, $future, $past);
  788. $keys = array_keys($list);
  789. $current_key = array_search($current, $keys);
  790. if ($current_key !== FALSE) {
  791. while (key($keys) !== $current_key) next($keys);
  792. return prev($keys);
  793. }
  794. return FALSE;
  795. }
  796. public static function get_asset_path($asset) {
  797. $content_root = self::get_content_root();
  798. $app = \Slim\Slim::getInstance();
  799. return "{$content_root}".$app->request()->getResourceUri().''.$asset;
  800. }
  801. public static function parse_content($content, $tag_data) {
  802. $app = \Slim\Slim::getInstance();
  803. $tag_data = array_merge($tag_data, $app->config);
  804. $parser = new Lex_Parser();
  805. $parser->cumulative_noparse(true);
  806. $parser->scope_glue(':');
  807. $parse_order = Statamic::get_parse_order();
  808. if ($parse_order[0] == 'tags') {
  809. $output = $parser->parse($content, $tag_data);
  810. $output = self::transform_content($output);
  811. } else {
  812. $output = self::transform_content($content);
  813. $output = $parser->parse($output, $tag_data);
  814. }
  815. return $output;
  816. }
  817. public static function transform_content($content) {
  818. $content_type = self::get_content_type();
  819. if ($content_type == "markdown" || $content_type == 'md') {
  820. $content = Markdown($content);
  821. } else if ($content_type == 'html') {
  822. // no modifications
  823. } else if ($content_type == 'txt') {
  824. $content = nl2br(strip_tags($content));
  825. } else if ($content_type == 'textile') {
  826. $textile = new Textile();
  827. $content = $textile->TextileThis($content);
  828. }
  829. if (Statamic::get_setting('_enable_smartypants', true) == true) {
  830. $content = SmartyPants($content);
  831. }
  832. return $content;
  833. }
  834. public static function is_taxonomy($tax) {
  835. $app = \Slim\Slim::getInstance();
  836. if (isset($app->config['_taxonomy'])) {
  837. $taxonomies = $app->config['_taxonomy'];
  838. if (in_array($tax, $taxonomies)) {
  839. return TRUE;
  840. }
  841. }
  842. return FALSE;
  843. }
  844. public static function is_taxonomy_url($path) {
  845. $app = \Slim\Slim::getInstance();
  846. if (isset($app->config['_taxonomy'])) {
  847. $taxonomies = $app->config['_taxonomy'];
  848. $items = explode("/", $path); # get the last 2 segments of the path, format: /<taxonomy_type>/<slug>
  849. if (sizeof($items) > 2) {
  850. $slug = array_pop($items);
  851. $type = array_pop($items);
  852. foreach ($taxonomies as $key => $taxonomy) {
  853. if ($type == $taxonomy) {
  854. return TRUE;
  855. }
  856. }
  857. }
  858. }
  859. return FALSE;
  860. }
  861. public static function get_taxonomy_criteria($path) {
  862. $app = \Slim\Slim::getInstance();
  863. if (isset($app->config['_taxonomy'])) {
  864. $taxonomies = $app->config['_taxonomy'];
  865. // get the last 2 segments of the path
  866. // format: /<taxonomy_type>/<slug>
  867. $items = explode("/", $path);
  868. if (sizeof($items) > 2) {
  869. $slug = array_pop($items);
  870. $type = array_pop($items);
  871. foreach ($taxonomies as $key => $taxonomy) {
  872. if ($type == $taxonomy) {
  873. return array($type, $slug);
  874. }
  875. }
  876. }
  877. }
  878. return FALSE;
  879. }
  880. public static function remove_taxonomy_from_path($path, $type, $slug) {
  881. $return = $path;
  882. $return = substr($path, 0, -1 * strlen("/{$type}/{$slug}"));
  883. return $return;
  884. }
  885. public static function detect_environment(array $environments, $uri) {
  886. foreach ($environments as $environment => $patterns) {
  887. foreach ($patterns as $pattern) {
  888. if (Statamic_Helper::is($pattern, $uri)) {
  889. return $environment;
  890. }
  891. }
  892. }
  893. }
  894. }
  895. function statamic_sort_by_title($a, $b) {
  896. return strcmp($a['title'], $b['title']);
  897. }