PageRenderTime 203ms CodeModel.GetById 29ms RepoModel.GetById 1ms app.codeStats 0ms

/php/lib/MTUtil.php

http://github.com/movabletype/movabletype
PHP | 1823 lines | 1635 code | 137 blank | 51 comment | 284 complexity | 5eb7b64e88326a0e2c251165b78dbb25 MD5 | raw file
Possible License(s): LGPL-2.1, MIT, BSD-3-Clause

Large files files are truncated, but you can click here to view the full file

  1. <?php
  2. # Movable Type (r) (C) 2001-2020 Six Apart Ltd. All Rights Reserved.
  3. # This code cannot be redistributed without permission from www.sixapart.com.
  4. # For more information, consult your Movable Type license.
  5. #
  6. # $Id$
  7. function datetime_to_timestamp($dt, $type = 'local') {
  8. $mktime = (isset($type) && $type == 'gmt') ? 'gmmktime' : 'mktime';
  9. $dt = preg_replace('/[^0-9]/', '', $dt);
  10. $ts = $mktime(substr($dt, 8, 2), substr($dt, 10, 2), substr($dt, 12, 2), substr($dt, 4, 2), substr($dt, 6, 2), substr($dt, 0, 4));
  11. return $ts;
  12. }
  13. function start_end_ts($ts) {
  14. if ($ts) {
  15. if (strlen($ts) == 4) {
  16. $ts_start = $ts . '0101';
  17. $ts_end = $ts . '1231';
  18. } elseif (strlen($ts) == 6) {
  19. $ts_start = $ts . '01';
  20. $ts_end = $ts . sprintf("%02d", days_in(substr($ts, 4, 2), substr($ts, 0, 4)));
  21. } else {
  22. $ts_start = $ts;
  23. $ts_end = $ts;
  24. }
  25. }
  26. return array($ts_start . '000000', $ts_end . '235959');
  27. }
  28. function start_end_month($ts) {
  29. $y = substr($ts, 0, 4);
  30. $mo = substr($ts, 4, 2);
  31. $start = sprintf("%04d%02d01000000", $y, $mo);
  32. $end = sprintf("%04d%02d%02d235959", $y, $mo, days_in($mo, $y));
  33. return array($start, $end);
  34. }
  35. function days_in($m, $y) {
  36. return date('t', mktime(0, 0, 0, $m, 1, $y));
  37. }
  38. function start_end_day($ts) {
  39. $day = substr($ts, 0, 8);
  40. return array($day . "000000", $day . "235959");
  41. }
  42. function start_end_year($ts) {
  43. $year = substr($ts, 0, 4);
  44. return array($year . "0101000000", $year . "1231235959");
  45. }
  46. function start_end_week($ts) {
  47. $y = substr($ts, 0, 4);
  48. $mo = substr($ts, 4, 2);
  49. $d = substr($ts, 6, 2);
  50. $h = substr($ts, 8, 2);
  51. $s = substr($ts, 10, 2);
  52. $wday = wday_from_ts($y, $mo, $d);
  53. list($sd, $sm, $sy) = array($d - $wday, $mo, $y);
  54. if ($sd < 1) {
  55. $sm--;
  56. if ($sm < 1) {
  57. $sm = 12; $sy--;
  58. }
  59. $sd += days_in($sm, $sy);
  60. }
  61. $start = sprintf("%04d%02d%02d%s", $sy, $sm, $sd, "000000");
  62. list($ed, $em, $ey) = array($d + 6 - $wday, $mo, $y);
  63. if ($ed > days_in($em, $ey)) {
  64. $ed -= days_in($em, $ey);
  65. $em++;
  66. if ($em > 12) {
  67. $em = 1; $ey++;
  68. }
  69. }
  70. $end = sprintf("%04d%02d%02d%s", $ey, $em, $ed, "235959");
  71. return array($start, $end);
  72. }
  73. global $In_Year;
  74. $In_Year = array(
  75. array( 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365 ),
  76. array( 0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335, 366 ),
  77. );
  78. function week2ymd($y, $week) {
  79. $jan_one_dow_m1 = (ymd2rd($y, 1, 1) + 6) % 7;
  80. if ($jan_one_dow_m1 < 4) $week--;
  81. $day_of_year = $week * 7 - $jan_one_dow_m1;
  82. $leap_year = is_leap_year($y);
  83. if ($day_of_year < 1) {
  84. $y--;
  85. $day_of_year = ($leap_year ? 366 : 365) + $day_of_year;
  86. }
  87. if ($leap_year) {
  88. $ref = array(0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335);
  89. } else {
  90. $ref = array(0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334);
  91. }
  92. $m = 0;
  93. for ($i = count($ref); $i > 0; $i--) {
  94. if ($day_of_year > $ref[$i-1]) {
  95. $m = $i;
  96. break;
  97. }
  98. }
  99. return array($y, $m, $day_of_year - $ref[$m-1]);
  100. }
  101. function is_leap_year($y) {
  102. return (!($y % 4) && ($y % 100)) || !($y % 400) ? true : false;
  103. }
  104. function ymd2rd($y,$m,$d) {
  105. # make month in range 3..14 (treat Jan & Feb as months 13..14 of
  106. # prev year)
  107. if ( $m <= 2 ) {
  108. $adj = (int)(( 14 - $m ) / 12);
  109. $y -= $adj;
  110. $m += 12 * $adj;
  111. }
  112. elseif ( $m > 14 )
  113. {
  114. $adj = (int)(( $m - 3 ) / 12);
  115. $y += $adj;
  116. $m -= 12 * $adj;
  117. }
  118. # make year positive (oh, for a use integer 'sane_div'!)
  119. if ( $y < 0 )
  120. {
  121. $adj = (int)(( 399 - $y ) / 400);
  122. $d -= 146097 * $adj;
  123. $y += 400 * $adj;
  124. }
  125. # add: day of month, days of previous 0-11 month period that began
  126. # w/March, days of previous 0-399 year period that began w/March
  127. # of a 400-multiple year), days of any 400-year periods before
  128. # that, and 306 days to adjust from Mar 1, year 0-relative to Jan
  129. # 1, year 1-relative (whew)
  130. $d += (int)(( $m * 367 - 1094 ) / 12) + (int)((($y % 100) * 1461) / 4) +
  131. ( (int)($y / 100) * 36524 + (int)($y / 400) ) - 306;
  132. return $d;
  133. }
  134. function wday_from_ts($y, $m, $d) {
  135. global $In_Year;
  136. $leap = $y % 4 == 0 && ($y % 100 != 0 || $y % 400 == 0) ? 1 : 0;
  137. $y--;
  138. ## Copied from Date::Calc.
  139. $days = $y * 365;
  140. $days += $y >>= 2;
  141. $days -= intval($y /= 25);
  142. $days += $y >> 2;
  143. $days += $In_Year[$leap][$m-1] + $d;
  144. return $days % 7;
  145. }
  146. function yday_from_ts($y, $m, $d) {
  147. global $In_Year;
  148. $leap = $y % 4 == 0 && ($y % 100 != 0 || $y % 400 == 0) ? 1 : 0;
  149. return $In_Year[$leap][$m-1] + $d;
  150. }
  151. function substr_wref($str, $start, $length) {
  152. if (preg_match_all('/(&[^;]*;|.)/', $str, $character_entities)) {
  153. return implode('', array_slice($character_entities[0], $start, $length));
  154. } else {
  155. return '';
  156. }
  157. }
  158. function format_ts($format, $ts, $blog, $lang = null) {
  159. global $Languages;
  160. if (!isset($lang) || empty($lang)) {
  161. $mt = MT::get_instance();
  162. $lang = (
  163. $blog && $blog->blog_date_language
  164. ? $blog->blog_date_language
  165. : $mt->config('DefaultLanguage')
  166. );
  167. }
  168. if ($lang == 'jp') {
  169. $lang = 'ja';
  170. }
  171. $lang = strtolower(substr($lang, 0, 2));
  172. if (!isset($format) || empty($format)) {
  173. if (count($Languages[$lang]) >= 4)
  174. $format = $Languages[$lang][3];
  175. $format or $format = "%B %e, %Y %l:%M %p";
  176. }
  177. global $_format_ts_cache;
  178. if (!isset($_format_ts_cache)) {
  179. $_format_ts_cache = array();
  180. }
  181. if (isset($_format_ts_cache[$ts.$lang])) {
  182. $f = $_format_ts_cache[$ts.$lang];
  183. } else {
  184. $L = $Languages[$lang];
  185. $tsa = array(substr($ts, 0, 4), substr($ts, 4, 2), substr($ts, 6, 2),
  186. substr($ts, 8, 2), substr($ts, 10, 2), substr($ts, 12, 2));
  187. list($f['Y'], $f['m'], $f['d'], $f['H'], $f['M'], $f['S']) = $tsa;
  188. $f['w'] = wday_from_ts($tsa[0],$tsa[1],$tsa[2]);
  189. $f['j'] = yday_from_ts($tsa[0],$tsa[1],$tsa[2]);
  190. $f['y'] = substr($f['Y'], 2);
  191. $f['b'] = substr_wref($L[1][$f['m']-1], 0, 3);
  192. $f['B'] = $L[1][$f['m']-1];
  193. if ($lang == 'ja') {
  194. $f['a'] = substr($L[0][$f['w']], 0, 8);
  195. } else {
  196. $f['a'] = substr_wref($L[0][$f['w']], 0, 3);
  197. }
  198. $f['A'] = $L[0][$f['w']];
  199. $f['e'] = $f['d'];
  200. $f['e'] = preg_replace('!^0!', ' ', $f['e']);
  201. $f['I'] = $f['H'];
  202. if ($f['I'] > 12) {
  203. $f['I'] -= 12;
  204. $f['p'] = $L[2][1];
  205. } elseif ($f['I'] == 0) {
  206. $f['I'] = 12;
  207. $f['p'] = $L[2][0];
  208. } elseif ($f['I'] == 12) {
  209. $f['p'] = $L[2][1];
  210. } else {
  211. $f['p'] = $L[2][0];
  212. }
  213. $f['I'] = sprintf("%02d", $f['I']);
  214. $f['k'] = $f['H'];
  215. $f['k'] = preg_replace('!^0!', ' ', $f['k']);
  216. $f['l'] = $f['I'];
  217. $f['l'] = preg_replace('!^0!', ' ', $f['l']);
  218. $f['j'] = sprintf("%03d", $f['j']);
  219. $f['Z'] = '';
  220. $_format_ts_cache[$ts . $lang] = $f;
  221. }
  222. $date_format = null;
  223. if (count($Languages[$lang]) >= 5)
  224. $date_format = $Languages[$lang][4];
  225. $date_format or $date_format = "%B %e, %Y";
  226. $time_format = null;
  227. if (count($Languages[$lang]) >= 6)
  228. $time_format = $Languages[$lang][5];
  229. $time_format or $time_format = "%l:%M %p";
  230. $format = preg_replace('!%x!', $date_format, $format);
  231. $format = preg_replace('!%X!', $time_format, $format);
  232. ## This is a dreadful hack. I can't think of a good format specifier
  233. ## for "%B %Y" (which is used for monthly archives, for example) so
  234. ## I'll just hardcode this, for Japanese dates.
  235. if ($lang == 'ja') {
  236. if (count($Languages[$lang]) >= 8) {
  237. $format = preg_replace('!%B %Y!', $Languages[$lang][6], $format);
  238. $format = preg_replace('!%B %E,? %Y!i', $Languages[$lang][4], $format);
  239. $format = preg_replace('!%B %E!', $Languages[$lang][7], $format);
  240. }
  241. }
  242. elseif ( $lang == 'it' ) {
  243. ## Hack for the Italian dates
  244. ## In Italian, the date always come before the month.
  245. $format = preg_replace('!%b %e!', '%e %b', $format);
  246. }
  247. if (isset($format)) {
  248. $keys = array();
  249. $values = array();
  250. foreach ($f as $k => $v) {
  251. $keys[] = '%' . $k;
  252. $values[] = $v;
  253. }
  254. $format = str_replace($keys, $values, $format);
  255. }
  256. return $format;
  257. }
  258. function dirify($s, $sep = '_') {
  259. $mt = MT::get_instance();
  260. $charset = $mt->config('PublishCharset');
  261. $charset or $charset = 'utf-8';
  262. if (preg_match('/utf-?8/i', $charset)) {
  263. return utf8_dirify($s, $sep);
  264. } else {
  265. return iso_dirify($s, $sep);
  266. }
  267. }
  268. function utf8_dirify($s, $sep = '_') {
  269. if ($sep == '1') $sep = '_';
  270. $s = xliterate_utf8($s); ## convert high-ASCII chars to 7bit.
  271. $s = strtolower($s); ## lower-case.
  272. $s = strip_tags($s); ## remove HTML tags.
  273. $s = preg_replace('!&[^;\s]+;!', '', $s); ## remove HTML entities.
  274. $s = preg_replace('![^\w\s]!', '', $s); ## remove non-word/space chars.
  275. $s = preg_replace('/\s+/',$sep,$s); ## change space chars to underscores.
  276. return($s);
  277. }
  278. global $Utf8_ASCII;
  279. $Utf8_ASCII = array(
  280. "\xc3\x80" => 'A', # A`
  281. "\xc3\xa0" => 'a', # a`
  282. "\xc3\x81" => 'A', # A'
  283. "\xc3\xa1" => 'a', # a'
  284. "\xc3\x82" => 'A', # A^
  285. "\xc3\xa2" => 'a', # a^
  286. "\xc4\x82" => 'A', # latin capital letter a with breve
  287. "\xc4\x83" => 'a', # latin small letter a with breve
  288. "\xc3\x86" => 'AE', # latin capital letter AE
  289. "\xc3\xa6" => 'ae', # latin small letter ae
  290. "\xc3\x85" => 'A', # latin capital letter a with ring above
  291. "\xc3\xa5" => 'a', # latin small letter a with ring above
  292. "\xc4\x80" => 'A', # latin capital letter a with macron
  293. "\xc4\x81" => 'a', # latin small letter a with macron
  294. "\xc4\x84" => 'A', # latin capital letter a with ogonek
  295. "\xc4\x85" => 'a', # latin small letter a with ogonek
  296. "\xc3\x84" => 'A', # A:
  297. "\xc3\xa4" => 'a', # a:
  298. "\xc3\x83" => 'A', # A~
  299. "\xc3\xa3" => 'a', # a~
  300. "\xc3\x88" => 'E', # E`
  301. "\xc3\xa8" => 'e', # e`
  302. "\xc3\x89" => 'E', # E'
  303. "\xc3\xa9" => 'e', # e'
  304. "\xc3\x8a" => 'E', # E^
  305. "\xc3\xaa" => 'e', # e^
  306. "\xc3\x8b" => 'E', # E:
  307. "\xc3\xab" => 'e', # e:
  308. "\xc4\x92" => 'E', # latin capital letter e with macron
  309. "\xc4\x93" => 'e', # latin small letter e with macron
  310. "\xc4\x98" => 'E', # latin capital letter e with ogonek
  311. "\xc4\x99" => 'e', # latin small letter e with ogonek
  312. "\xc4\x9a" => 'E', # latin capital letter e with caron
  313. "\xc4\x9b" => 'e', # latin small letter e with caron
  314. "\xc4\x94" => 'E', # latin capital letter e with breve
  315. "\xc4\x95" => 'e', # latin small letter e with breve
  316. "\xc4\x96" => 'E', # latin capital letter e with dot above
  317. "\xc4\x97" => 'e', # latin small letter e with dot above
  318. "\xc3\x8c" => 'I', # I`
  319. "\xc3\xac" => 'i', # i`
  320. "\xc3\x8d" => 'I', # I'
  321. "\xc3\xad" => 'i', # i'
  322. "\xc3\x8e" => 'I', # I^
  323. "\xc3\xae" => 'i', # i^
  324. "\xc3\x8f" => 'I', # I:
  325. "\xc3\xaf" => 'i', # i:
  326. "\xc4\xaa" => 'I', # latin capital letter i with macron
  327. "\xc4\xab" => 'i', # latin small letter i with macron
  328. "\xc4\xa8" => 'I', # latin capital letter i with tilde
  329. "\xc4\xa9" => 'i', # latin small letter i with tilde
  330. "\xc4\xac" => 'I', # latin capital letter i with breve
  331. "\xc4\xad" => 'i', # latin small letter i with breve
  332. "\xc4\xae" => 'I', # latin capital letter i with ogonek
  333. "\xc4\xaf" => 'i', # latin small letter i with ogonek
  334. "\xc4\xb0" => 'I', # latin capital letter with dot above
  335. "\xc4\xb1" => 'i', # latin small letter dotless i
  336. "\xc4\xb2" => 'IJ', # latin capital ligature ij
  337. "\xc4\xb3" => 'ij', # latin small ligature ij
  338. "\xc4\xb4" => 'J', # latin capital letter j with circumflex
  339. "\xc4\xb5" => 'j', # latin small letter j with circumflex
  340. "\xc4\xb6" => 'K', # latin capital letter k with cedilla
  341. "\xc4\xb7" => 'k', # latin small letter k with cedilla
  342. "\xc4\xb8" => 'k', # latin small letter kra
  343. "\xc5\x81" => 'L', # latin capital letter l with stroke
  344. "\xc5\x82" => 'l', # latin small letter l with stroke
  345. "\xc4\xbd" => 'L', # latin capital letter l with caron
  346. "\xc4\xbe" => 'l', # latin small letter l with caron
  347. "\xc4\xb9" => 'L', # latin capital letter l with acute
  348. "\xc4\xba" => 'l', # latin small letter l with acute
  349. "\xc4\xbb" => 'L', # latin capital letter l with cedilla
  350. "\xc4\xbc" => 'l', # latin small letter l with cedilla
  351. "\xc4\xbf" => 'l', # latin capital letter l with middle dot
  352. "\xc5\x80" => 'l', # latin small letter l with middle dot
  353. "\xc3\x92" => 'O', # O`
  354. "\xc3\xb2" => 'o', # o`
  355. "\xc3\x93" => 'O', # O'
  356. "\xc3\xb3" => 'o', # o'
  357. "\xc3\x94" => 'O', # O^
  358. "\xc3\xb4" => 'o', # o^
  359. "\xc3\x96" => 'O', # O:
  360. "\xc3\xb6" => 'o', # o:
  361. "\xc3\x95" => 'O', # O~
  362. "\xc3\xb5" => 'o', # o~
  363. "\xc3\x98" => 'O', # O/
  364. "\xc3\xb8" => 'o', # o/
  365. "\xc5\x8c" => 'O', # latin capital letter o with macron
  366. "\xc5\x8d" => 'o', # latin small letter o with macron
  367. "\xc5\x90" => 'O', # latin capital letter o with double acute
  368. "\xc5\x91" => 'o', # latin small letter o with double acute
  369. "\xc5\x8e" => 'O', # latin capital letter o with breve
  370. "\xc5\x8f" => 'o', # latin small letter o with breve
  371. "\xc5\x92" => 'OE', # latin capital ligature oe
  372. "\xc5\x93" => 'oe', # latin small ligature oe
  373. "\xc5\x94" => 'R', # latin capital letter r with acute
  374. "\xc5\x95" => 'r', # latin small letter r with acute
  375. "\xc5\x98" => 'R', # latin capital letter r with caron
  376. "\xc5\x99" => 'r', # latin small letter r with caron
  377. "\xc5\x96" => 'R', # latin capital letter r with cedilla
  378. "\xc5\x97" => 'r', # latin small letter r with cedilla
  379. "\xc3\x99" => 'U', # U`
  380. "\xc3\xb9" => 'u', # u`
  381. "\xc3\x9a" => 'U', # U'
  382. "\xc3\xba" => 'u', # u'
  383. "\xc3\x9b" => 'U', # U^
  384. "\xc3\xbb" => 'u', # u^
  385. "\xc3\x9c" => 'U', # U:
  386. "\xc3\xbc" => 'u', # u:
  387. "\xc5\xaa" => 'U', # latin capital letter u with macron
  388. "\xc5\xab" => 'u', # latin small letter u with macron
  389. "\xc5\xae" => 'U', # latin capital letter u with ring above
  390. "\xc5\xaf" => 'u', # latin small letter u with ring above
  391. "\xc5\xb0" => 'U', # latin capital letter u with double acute
  392. "\xc5\xb1" => 'u', # latin small letter u with double acute
  393. "\xc5\xac" => 'U', # latin capital letter u with breve
  394. "\xc5\xad" => 'u', # latin small letter u with breve
  395. "\xc5\xa8" => 'U', # latin capital letter u with tilde
  396. "\xc5\xa9" => 'u', # latin small letter u with tilde
  397. "\xc5\xb2" => 'U', # latin capital letter u with ogonek
  398. "\xc5\xb3" => 'u', # latin small letter u with ogonek
  399. "\xc3\x87" => 'C', # ,C
  400. "\xc3\xa7" => 'c', # ,c
  401. "\xc4\x86" => 'C', # latin capital letter c with acute
  402. "\xc4\x87" => 'c', # latin small letter c with acute
  403. "\xc4\x8c" => 'C', # latin capital letter c with caron
  404. "\xc4\x8d" => 'c', # latin small letter c with caron
  405. "\xc4\x88" => 'C', # latin capital letter c with circumflex
  406. "\xc4\x89" => 'c', # latin small letter c with circumflex
  407. "\xc4\x8a" => 'C', # latin capital letter c with dot above
  408. "\xc4\x8b" => 'c', # latin small letter c with dot above
  409. "\xc4\x8e" => 'D', # latin capital letter d with caron
  410. "\xc4\x8f" => 'd', # latin small letter d with caron
  411. "\xc4\x90" => 'D', # latin capital letter d with stroke
  412. "\xc4\x91" => 'd', # latin small letter d with stroke
  413. "\xc3\x91" => 'N', # N~
  414. "\xc3\xb1" => 'n', # n~
  415. "\xc5\x83" => 'N', # latin capital letter n with acute
  416. "\xc5\x84" => 'n', # latin small letter n with acute
  417. "\xc5\x87" => 'N', # latin capital letter n with caron
  418. "\xc5\x88" => 'n', # latin small letter n with caron
  419. "\xc5\x85" => 'N', # latin capital letter n with cedilla
  420. "\xc5\x86" => 'n', # latin small letter n with cedilla
  421. "\xc5\x89" => 'n', # latin small letter n preceded by apostrophe
  422. "\xc5\x8a" => 'N', # latin capital letter eng
  423. "\xc5\x8b" => 'n', # latin small letter eng
  424. "\xc3\x9f" => 'ss', # double-s
  425. "\xc5\x9a" => 'S', # latin capital letter s with acute
  426. "\xc5\x9b" => 's', # latin small letter s with acute
  427. "\xc5\xa0" => 'S', # latin capital letter s with caron
  428. "\xc5\xa1" => 's', # latin small letter s with caron
  429. "\xc5\x9e" => 'S', # latin capital letter s with cedilla
  430. "\xc5\x9f" => 's', # latin small letter s with cedilla
  431. "\xc5\x9c" => 'S', # latin capital letter s with circumflex
  432. "\xc5\x9d" => 's', # latin small letter s with circumflex
  433. "\xc8\x98" => 'S', # latin capital letter s with comma below
  434. "\xc8\x99" => 's', # latin small letter s with comma below
  435. "\xc5\xa4" => 'T', # latin capital letter t with caron
  436. "\xc5\xa5" => 't', # latin small letter t with caron
  437. "\xc5\xa2" => 'T', # latin capital letter t with cedilla
  438. "\xc5\xa3" => 't', # latin small letter t with cedilla
  439. "\xc5\xa6" => 'T', # latin capital letter t with stroke
  440. "\xc5\xa7" => 't', # latin small letter t with stroke
  441. "\xc8\x9a" => 'T', # latin capital letter t with comma below
  442. "\xc8\x9b" => 't', # latin small letter t with comma below
  443. "\xc6\x92" => 'f', # latin small letter f with hook
  444. "\xc4\x9c" => 'G', # latin capital letter g with circumflex
  445. "\xc4\x9d" => 'g', # latin small letter g with circumflex
  446. "\xc4\x9e" => 'G', # latin capital letter g with breve
  447. "\xc4\x9f" => 'g', # latin small letter g with breve
  448. "\xc4\xa0" => 'G', # latin capital letter g with dot above
  449. "\xc4\xa1" => 'g', # latin small letter g with dot above
  450. "\xc4\xa2" => 'G', # latin capital letter g with cedilla
  451. "\xc4\xa3" => 'g', # latin small letter g with cedilla
  452. "\xc4\xa4" => 'H', # latin capital letter h with circumflex
  453. "\xc4\xa5" => 'h', # latin small letter h with circumflex
  454. "\xc4\xa6" => 'H', # latin capital letter h with stroke
  455. "\xc4\xa7" => 'h', # latin small letter h with stroke
  456. "\xc5\xb4" => 'W', # latin capital letter w with circumflex
  457. "\xc5\xb5" => 'w', # latin small letter w with circumflex
  458. "\xc3\x9d" => 'Y', # latin capital letter y with acute
  459. "\xc3\xbd" => 'y', # latin small letter y with acute
  460. "\xc5\xb8" => 'Y', # latin capital letter y with diaeresis
  461. "\xc3\xbf" => 'y', # latin small letter y with diaeresis
  462. "\xc5\xb6" => 'Y', # latin capital letter y with circumflex
  463. "\xc5\xb7" => 'y', # latin small letter y with circumflex
  464. "\xc5\xbd" => 'Z', # latin capital letter z with caron
  465. "\xc5\xbe" => 'z', # latin small letter z with caron
  466. "\xc5\xbb" => 'Z', # latin capital letter z with dot above
  467. "\xc5\xbc" => 'z', # latin small letter z with dot above
  468. "\xc5\xb9" => 'Z', # latin capital letter z with acute
  469. "\xc5\xba" => 'z', # latin small letter z with acute
  470. );
  471. function xliterate_utf8($s) {
  472. global $Utf8_ASCII;
  473. return strtr($s, $Utf8_ASCII);
  474. }
  475. function iso_dirify($s, $sep = '_') {
  476. if ($sep == '1') $sep = '_';
  477. $s = convert_high_ascii($s); ## convert high-ASCII chars to 7bit.
  478. $s = strtolower($s); ## lower-case.
  479. $s = strip_tags($s); ## remove HTML tags.
  480. $s = preg_replace('!&[^;\s]+;!', '', $s); ## remove HTML entities.
  481. $s = preg_replace('![^\w\s]!', '', $s); ## remove non-word/space chars.
  482. $s = preg_replace('/\s+/',$sep,$s); ## change space chars to underscores.
  483. return($s);
  484. }
  485. global $Latin1_ASCII;
  486. $Latin1_ASCII = array(
  487. "\xc0" => 'A', # A`
  488. "\xe0" => 'a', # a`
  489. "\xc1" => 'A', # A'
  490. "\xe1" => 'a', # a'
  491. "\xc2" => 'A', # A^
  492. "\xe2" => 'a', # a^
  493. "\xc4" => 'A', # A:
  494. "\xe4" => 'a', # a:
  495. "\xc5" => 'A', # Aring
  496. "\xe5" => 'a', # aring
  497. "\xc6" => 'AE', # AE
  498. "\xe6" => 'ae', # ae
  499. "\xc3" => 'A', # A~
  500. "\xe3" => 'a', # a~
  501. "\xc8" => 'E', # E`
  502. "\xe8" => 'e', # e`
  503. "\xc9" => 'E', # E'
  504. "\xe9" => 'e', # e'
  505. "\xca" => 'E', # E^
  506. "\xea" => 'e', # e^
  507. "\xcb" => 'E', # E:
  508. "\xeb" => 'e', # e:
  509. "\xcc" => 'I', # I`
  510. "\xec" => 'i', # i`
  511. "\xcd" => 'I', # I'
  512. "\xed" => 'i', # i'
  513. "\xce" => 'I', # I^
  514. "\xee" => 'i', # i^
  515. "\xcf" => 'I', # I:
  516. "\xef" => 'i', # i:
  517. "\xd2" => 'O', # O`
  518. "\xf2" => 'o', # o`
  519. "\xd3" => 'O', # O'
  520. "\xf3" => 'o', # o'
  521. "\xd4" => 'O', # O^
  522. "\xf4" => 'o', # o^
  523. "\xd6" => 'O', # O:
  524. "\xf6" => 'o', # o:
  525. "\xd5" => 'O', # O~
  526. "\xf5" => 'o', # o~
  527. "\xd8" => 'O', # O/
  528. "\xf8" => 'o', # o/
  529. "\xd9" => 'U', # U`
  530. "\xf9" => 'u', # u`
  531. "\xda" => 'U', # U'
  532. "\xfa" => 'u', # u'
  533. "\xdb" => 'U', # U^
  534. "\xfb" => 'u', # u^
  535. "\xdc" => 'U', # U:
  536. "\xfc" => 'u', # u:
  537. "\xc7" => 'C', # ,C
  538. "\xe7" => 'c', # ,c
  539. "\xd1" => 'N', # N~
  540. "\xf1" => 'n', # n~
  541. "\xdd" => 'Y', # Yacute
  542. "\xfd" => 'y', # yacute
  543. "\xdf" => 'ss', # szlig
  544. "\xff" => 'y' # yuml
  545. );
  546. function convert_high_ascii($s) {
  547. $mt = MT::get_instance();
  548. $lang = $mt->config('DefaultLanguage');
  549. if ($lang == 'ja') {
  550. $s = mb_convert_encoding($s, 'UTF-8');
  551. return $s;
  552. }
  553. global $Latin1_ASCII;
  554. return strtr($s, $Latin1_ASCII);
  555. }
  556. global $Languages;
  557. $Languages = array(
  558. 'en' => array(
  559. array('Sunday','Monday','Tuesday','Wednesday','Thursday','Friday','Saturday'),
  560. array('January','February','March','April','May','June',
  561. 'July','August','September','October','November','December'),
  562. array('AM','PM'),
  563. ),
  564. 'fr' => array(
  565. array('dimanche','lundi','mardi','mercredi','jeudi','vendredi','samedi' ),
  566. array('janvier', "f&#xe9;vrier", 'mars', 'avril', 'mai', 'juin',
  567. 'juillet', "ao&#xfb;t", 'septembre', 'octobre', 'novembre',
  568. "d&#xe9;cembre"),
  569. array('AM','PM'),
  570. ),
  571. 'es' => array(
  572. array('Domingo', 'Lunes', 'Martes', "Mi&#xe9;rcoles", 'Jueves',
  573. 'Viernes', "S&#xe1;bado"),
  574. array('Enero','Febrero','Marzo','Abril','Mayo','Junio','Julio','Agosto',
  575. 'Septiembre','Octubre','Noviembre','Diciembre'),
  576. array('AM','PM'),
  577. ),
  578. 'pt' => array(
  579. array('domingo', 'segunda-feira', "ter&#xe7;a-feira", 'quarta-feira',
  580. 'quinta-feira', 'sexta-feira', "s&#xe1;bado"),
  581. array('janeiro', 'fevereiro', "mar&#xe7;o", 'abril', 'maio', 'junho',
  582. 'julho', 'agosto', 'setembro', 'outubro', 'novembro',
  583. 'dezembro' ),
  584. array('AM','PM'),
  585. ),
  586. 'nl' => array(
  587. array('zondag','maandag','dinsdag','woensdag','donderdag','vrijdag',
  588. 'zaterdag'),
  589. array('januari','februari','maart','april','mei','juni','juli','augustus',
  590. 'september','oktober','november','december'),
  591. array('am','pm'),
  592. "%d %B %Y %H:%M",
  593. "%d %B %Y"
  594. ),
  595. 'dk' => array(
  596. array("s&#xf8;ndag", 'mandag', 'tirsdag', 'onsdag', 'torsdag',
  597. 'fredag', "l&#xf8;rdag"),
  598. array('januar','februar','marts','april','maj','juni','juli','august',
  599. 'september','oktober','november','december'),
  600. array('am','pm'),
  601. "%d.%m.%Y %H:%M",
  602. "%d.%m.%Y",
  603. "%H:%M",
  604. ),
  605. 'se' => array(
  606. array("s&#xf6;ndag", "m&#xe5;ndag", 'tisdag', 'onsdag', 'torsdag',
  607. 'fredag', "l&#xf6;rdag"),
  608. array('januari','februari','mars','april','maj','juni','juli','augusti',
  609. 'september','oktober','november','december'),
  610. array('FM','EM'),
  611. ),
  612. 'no' => array(
  613. array("S&#xf8;ndag", "Mandag", 'Tirsdag', 'Onsdag', 'Torsdag',
  614. 'Fredag', "L&#xf8;rdag"),
  615. array('Januar','Februar','Mars','April','Mai','Juni','Juli','August',
  616. 'September','Oktober','November','Desember'),
  617. array('FM','EM'),
  618. ),
  619. 'de' => array(
  620. array('Sonntag','Montag','Dienstag','Mittwoch','Donnerstag','Freitag',
  621. 'Samstag'),
  622. array('Januar', 'Februar', "M&#xe4;rz", 'April', 'Mai', 'Juni',
  623. 'Juli', 'August', 'September', 'Oktober', 'November',
  624. 'Dezember'),
  625. array('FM','EM'),
  626. "%d.%m.%y %H:%M",
  627. "%d.%m.%y",
  628. "%H:%M",
  629. ),
  630. 'it' => array(
  631. array('Domenica', "Luned&#xec;", "Marted&#xec;", "Mercoled&#xec;",
  632. "Gioved&#xec;", "Venerd&#xec;", 'Sabato'),
  633. array('Gennaio','Febbraio','Marzo','Aprile','Maggio','Giugno','Luglio',
  634. 'Agosto','Settembre','Ottobre','Novembre','Dicembre'),
  635. array('AM','PM'),
  636. "%d.%m.%y %H:%M",
  637. "%d.%m.%y",
  638. "%H:%M",
  639. ),
  640. 'pl' => array(
  641. array('niedziela', "poniedzia&#322;ek", 'wtorek', "&#347;roda",
  642. 'czwartek', "pi&#261;tek", 'sobota'),
  643. array('stycznia', 'lutego', 'marca', 'kwietnia', 'maja', 'czerwca',
  644. 'lipca', 'sierpnia', "wrze&#347;nia", "pa&#378;dziernika",
  645. 'listopada', 'grudnia'),
  646. array('AM','PM'),
  647. "%e %B %Y %k:%M",
  648. "%e %B %Y",
  649. "%k:%M",
  650. ),
  651. 'fi' => array(
  652. array('sunnuntai','maanantai','tiistai','keskiviikko','torstai','perjantai',
  653. 'lauantai'),
  654. array('tammikuu', 'helmikuu', 'maaliskuu', 'huhtikuu', 'toukokuu',
  655. "kes&#xe4;kuu", "hein&#xe4;kuu", 'elokuu', 'syyskuu', 'lokakuu',
  656. 'marraskuu', 'joulukuu'),
  657. array('AM','PM'),
  658. "%d.%m.%y %H:%M",
  659. ),
  660. 'is' => array(
  661. array('Sunnudagur', "M&#xe1;nudagur", "&#xde;ri&#xf0;judagur",
  662. "Mi&#xf0;vikudagur", 'Fimmtudagur', "F&#xf6;studagur",
  663. 'Laugardagur'),
  664. array("jan&#xfa;ar", "febr&#xfa;ar", 'mars', "apr&#xed;l", "ma&#xed;",
  665. "j&#xfa;n&#xed;", "j&#xfa;l&#xed;", "&#xe1;g&#xfa;st", 'september',
  666. "okt&#xf3;ber", "n&#xf3;vember", 'desember'),
  667. array('FH','EH'),
  668. "%d.%m.%y %H:%M",
  669. ),
  670. 'si' => array(
  671. array('nedelja', 'ponedeljek', 'torek', 'sreda', "&#xe3;etrtek",
  672. 'petek', 'sobota'),
  673. array('januar','februar','marec','april','maj','junij','julij','avgust',
  674. 'september','oktober','november','december'),
  675. array('AM','PM'),
  676. "%d.%m.%y %H:%M",
  677. ),
  678. 'cz' => array(
  679. array('Ned&#283;le', 'Pond&#283;l&#237;', '&#218;ter&#253;',
  680. 'St&#345;eda', '&#268;tvrtek', 'P&#225;tek', 'Sobota'),
  681. array('Leden', '&#218;nor', 'B&#345;ezen', 'Duben', 'Kv&#283;ten',
  682. '&#268;erven', '&#268;ervenec', 'Srpen', 'Z&#225;&#345;&#237;',
  683. '&#216;&#237;jen', 'Listopad', 'Prosinec'),
  684. array('AM','PM'),
  685. "%e. %B %Y %k:%M",
  686. "%e. %B %Y",
  687. "%k:%M",
  688. ),
  689. 'sk' => array(
  690. array('nede&#318;a', 'pondelok', 'utorok', 'streda',
  691. '&#353;tvrtok', 'piatok', 'sobota'),
  692. array('janu&#225;r', 'febru&#225;r', 'marec', 'apr&#237;l',
  693. 'm&#225;j', 'j&#250;n', 'j&#250;l', 'august', 'september',
  694. 'okt&#243;ber', 'november', 'december'),
  695. array('AM','PM'),
  696. "%e. %B %Y %k:%M",
  697. "%e. %B %Y",
  698. "%k:%M",
  699. ),
  700. 'jp' => array(
  701. array('&#26085;&#26332;&#26085;', '&#26376;&#26332;&#26085;',
  702. '&#28779;&#26332;&#26085;', '&#27700;&#26332;&#26085;',
  703. '&#26408;&#26332;&#26085;', '&#37329;&#26332;&#26085;',
  704. '&#22303;&#26332;&#26085;'),
  705. array('1','2','3','4','5','6','7','8','9','10','11','12'),
  706. array('AM','PM'),
  707. "%Y&#24180;%b&#26376;%e&#26085; %H:%M",
  708. "%Y&#24180;%b&#26376;%e&#26085;",
  709. "%H:%M",
  710. "%Y&#24180;%b&#26376;",
  711. "%b&#26376;%e&#26085;",
  712. ),
  713. 'ja' => array(
  714. array('&#26085;&#26332;&#26085;', '&#26376;&#26332;&#26085;',
  715. '&#28779;&#26332;&#26085;', '&#27700;&#26332;&#26085;',
  716. '&#26408;&#26332;&#26085;', '&#37329;&#26332;&#26085;',
  717. '&#22303;&#26332;&#26085;'),
  718. array('1','2','3','4','5','6','7','8','9','10','11','12'),
  719. array('AM','PM'),
  720. "%Y&#24180;%b&#26376;%e&#26085; %H:%M",
  721. "%Y&#24180;%b&#26376;%e&#26085;",
  722. "%H:%M",
  723. "%Y&#24180;%b&#26376;",
  724. "%b&#26376;%e&#26085;",
  725. ),
  726. 'et' => array(
  727. array('ip&uuml;hap&auml;ev','esmasp&auml;ev','teisip&auml;ev',
  728. 'kolmap&auml;ev','neljap&auml;ev','reede','laup&auml;ev'),
  729. array('jaanuar', 'veebruar', 'm&auml;rts', 'aprill', 'mai',
  730. 'juuni', 'juuli', 'august', 'september', 'oktoober',
  731. 'november', 'detsember'),
  732. array('AM','PM'),
  733. "%m.%d.%y %H:%M",
  734. "%e. %B %Y",
  735. "%H:%M",
  736. ),
  737. );
  738. global $_encode_xml_Map;
  739. $_encode_xml_Map = array('&' => '&amp;', '"' => '&quot;',
  740. '<' => '&lt;', '>' => '&gt;',
  741. '\'' => '&apos;');
  742. function __check_xml_char($matches) {
  743. $val = $matches[2];
  744. $is_hex = $matches[1];
  745. if ($is_hex)
  746. $val = hexdec($val);
  747. $val = 0 + $val;
  748. if ( ($val == 9)
  749. || ($val == 0xA)
  750. || ($val == 0xD)
  751. || (($val >= 0x20) and ($val <= 0xD7FF))
  752. || (($val >= 0xE000) and ($val <= 0xFFFD))
  753. || (($val >= 0x10000) and ($val <= 0x10FFFF)))
  754. {
  755. return "&#" . $is_hex . $matches[2] . ";";
  756. }
  757. else {
  758. return "&amp;#" . $is_hex . $matches[2] . ";";
  759. }
  760. }
  761. function encode_xml($str, $nocdata = 0) {
  762. $mt = MT::get_instance();
  763. global $_encode_xml_Map;
  764. $cfg_nocdata = $mt->config('NoCDATA');
  765. $nocdata or (isset($cfg_nocdata) and $nocdata = $cfg_nocdata);
  766. if ((!$nocdata) && (preg_match('/
  767. <[^>]+> ## HTML markup
  768. | ## or
  769. &(?:(?!(\#([0-9]+)|\#x([0-9a-fA-F]+))).*?);
  770. ## something that looks like an HTML entity.
  771. /x', $str))) {
  772. ## If ]]> exists in the string, encode the > to &gt;.
  773. $str = preg_replace('/]]>/', ']]&gt;', $str);
  774. $str = '<![CDATA[' . $str . ']]>';
  775. } else {
  776. $str = strtr($str, $_encode_xml_Map);
  777. $str = preg_replace_callback('/&amp;#(x?)((?:[0-9]+|[0-9a-fA-F]+).*?);/', '__check_xml_char', $str);
  778. }
  779. return $str;
  780. }
  781. function decode_xml($str) {
  782. if (preg_match('/<!\[CDATA\[(.*?)]]>/', $str)) {
  783. $str = preg_replace('/<!\[CDATA\[(.*?)]]>/', '\1', $str);
  784. ## Decode encoded ]]&gt;
  785. $str = preg_replace('/]]&(gt|#62);/', ']]>', $str);
  786. } else {
  787. global $_encode_xml_Map;
  788. $str = strtr($str, array_flip($_encode_xml_Map));
  789. }
  790. return $str;
  791. }
  792. function encode_js($str) {
  793. if (!isset($str)) return '';
  794. $str = preg_replace('!\\\\!', '\\\\', $str);
  795. $str = preg_replace('!>!', '\\>', $str);
  796. $str = preg_replace('!<!', '\\<', $str);
  797. $str = preg_replace('!(s)(cript)!i', '$1\\\\$2', $str);
  798. $str = preg_replace('!</!', '<\\/', $str); # </ is supposed to be the end of Javascript (</script in most UA)
  799. $str = preg_replace('!\'!', '\\\'', $str);
  800. $str = preg_replace('!"!', '\\"', $str);
  801. $str = preg_replace('!\n!', '\\n', $str);
  802. $str = preg_replace('!\f!', '\\f', $str);
  803. $str = preg_replace('!\r!', '\\r', $str);
  804. $str = preg_replace('!\t!', '\\t', $str);
  805. return $str;
  806. }
  807. function encode_json($str) {
  808. if (!isset($str)) return '';
  809. // Do not use JSON_UNESCAPED_UNICODE with json_encode for supporting PHP 5.3.x and before.
  810. // Do not use closure for supporting PHP 5.2.x and before.
  811. $callback = function($matches) {
  812. return mb_convert_encoding(pack("H*", str_replace("\\u", "", $matches[0])), "UTF-8", "UTF-16");
  813. };
  814. // Do not escape slashes for compatible with Perl,
  815. // and JSON spec says that it is OK whether slashes are escaped or not.
  816. $encoded_str = preg_replace_callback(
  817. '/(?:\\\\u[0-9a-zA-Z]{4})++/',
  818. $callback,
  819. str_replace('\/', '/', json_encode($str))
  820. );
  821. // "foo" => foo
  822. return preg_replace('/^"(.+)"$/', '$1', $encoded_str);
  823. }
  824. function gmtime($ts = null) {
  825. if (!isset($ts)) {
  826. $ts = time();
  827. }
  828. $offset = date('Z', $ts);
  829. $ts -= $offset;
  830. $tsa = localtime($ts);
  831. $tsa[8] = 0;
  832. return $tsa;
  833. }
  834. function is_hash($array) {
  835. if ( is_array($array) ) {
  836. if ( array_keys($array) === range(0, count($array) - 1) ) {
  837. // 0,1,2,3... must be an array
  838. return false;
  839. }
  840. return true;
  841. }
  842. return false;
  843. }
  844. function offset_time_list($ts, $blog = null, $dir = null) {
  845. return gmtime(offset_time($ts, $blog, $dir));
  846. }
  847. function strip_hyphen($s) {
  848. return preg_replace('/-+/', '-', $s);
  849. }
  850. function first_n_words($text, $n) {
  851. $text = strip_tags($text);
  852. $words = preg_split('/\s+/', $text);
  853. $max = count($words) > $n ? $n : count($words);
  854. return join(' ', array_slice($words, 0, $max));
  855. }
  856. function html_text_transform($str = '') {
  857. $paras = preg_split('/\r?\n\r?\n/', $str);
  858. if ($str == '') {
  859. return '';
  860. }
  861. foreach ($paras as $k => $p) {
  862. if (!preg_match('/^<\/?(?:h1|h2|h3|h4|h5|h6|table|ol|dl|ul|menu|dir|p|pre|center|form|select|fieldset|blockquote|address|div|hr)/', $p)) {
  863. $p = preg_replace('/\r?\n/', "<br />\n", $p);
  864. $p = "<p>$p</p>";
  865. $paras[$k] = $p;
  866. }
  867. }
  868. return implode("\n\n", $paras);
  869. }
  870. function encode_html($str, $quote_style = ENT_QUOTES) {
  871. if (!isset($str)) return '';
  872. $trans_table = get_html_translation_table(HTML_SPECIALCHARS, $quote_style);
  873. if( $trans_table["'"] != '&#039;' ) { # some versions of PHP match single quotes to &#39;
  874. $trans_table["'"] = '&#039;';
  875. }
  876. return (strtr($str, $trans_table));
  877. }
  878. function encode_html_entities($str, $quote_style = ENT_QUOTES) {
  879. if (!$str) {
  880. return '';
  881. }
  882. static $use_htmlspecialchars;
  883. static $encoding;
  884. static $is_old_php;
  885. if (! isset($is_old_php)) {
  886. $is_old_php = version_compare(phpversion(), '4.3.0', '<');
  887. }
  888. if ($is_old_php) {
  889. return htmlentities($str, $quote_style);
  890. }
  891. if (! isset($use_htmlspecialchars)) {
  892. $mt = MT::get_instance();
  893. $encoding = strtolower($mt->config('PublishCharset'));
  894. $use_htmlspecialchars = !in_array($encoding, array(
  895. 'iso-8859-1', 'iso8859-1',
  896. 'iso-8859-5', 'iso8859-5',
  897. 'iso-8859-15', 'iso8859-15',
  898. 'utf-8',
  899. 'cp866', 'ibm866', '866',
  900. 'cp1251', 'windows-1251', 'win-1251', '1251',
  901. 'cp1252', 'windows-1252', '1252',
  902. 'koi8-r', 'koi8-ru', 'koi8r'
  903. ), true);
  904. }
  905. return $use_htmlspecialchars ?
  906. htmlspecialchars($str, $quote_style, $encoding) :
  907. htmlentities($str, $quote_style, $encoding);
  908. }
  909. function decode_html($str, $quote_style = ENT_QUOTES) {
  910. if (!isset($str)) return '';
  911. $trans_table = get_html_translation_table(HTML_SPECIALCHARS, $quote_style);
  912. if( $trans_table["'"] != '&#039;' ) { # some versions of PHP match single quotes to &#39;
  913. $trans_table["'"] = '&#039;';
  914. }
  915. return (strtr($str, array_flip($trans_table)));
  916. }
  917. function get_category_context(&$ctx, $class = 'category', $error_avoid = FALSE) {
  918. # Get our hands on the category for the current context
  919. # Either in MTCategories, a Category Archive Template
  920. # Or the category for the current entry
  921. $cat = $ctx->stash('category') or
  922. $ctx->stash('archive_category');
  923. if (!isset($cat)) {
  924. # No category found so far, test the entry
  925. if ($ctx->stash('entry')) {
  926. $entry = $ctx->stash('entry');
  927. $place = $entry->placement();
  928. if (empty($place))
  929. return null;
  930. $cat = $place[0]->category();
  931. # Return empty string if entry has no category
  932. # as the tag has been used in the correct context
  933. # but there is no category to work with
  934. if (!isset($cat)) {
  935. return null;
  936. }
  937. } else if ($ctx->stash('content')) {
  938. $content_data = $ctx->stash('content');
  939. if ($ctx->stash('_fileinfo') && $ctx->stash('_fileinfo')->templatemap()) {
  940. $maps = array($ctx->stash('_fileinfo')->templatemap());
  941. }
  942. if (!isset($maps)) {
  943. $maps = $ctx->mt->db()->fetch_templatemap(array(
  944. 'content_type_id' => $content_data->cd_content_type_id,
  945. 'preferred' => 1,
  946. 'type' => 'ContentType'
  947. ));
  948. }
  949. if (!isset($maps) || !is_array($maps) || !$maps[0]->templatemap_cat_field_id) {
  950. return null;
  951. }
  952. $objcats = $ctx->mt->db()->fetch_objectcategories(array(
  953. 'category_field_id' => $maps[0]->templatemap_cat_field_id,
  954. 'object_id' => $content_data->cd_id
  955. ));
  956. if (!isset($objcats) || !is_array($objcats)) {
  957. return null;
  958. }
  959. foreach ($objcats as $objcat) {
  960. if ($objcat->objectcategory_is_primary) {
  961. $objectcategory = $objcat;
  962. break;
  963. }
  964. }
  965. if (!isset($objectcategory)) {
  966. return null;
  967. }
  968. $cat = $ctx->mt->db()->fetch_category($objectcategory->objectcategory_category_id);
  969. } else {
  970. if($error_avoid)
  971. return null;
  972. $tag = $ctx->this_tag();
  973. return $ctx->error("$tag must be used in a category context");
  974. }
  975. }
  976. return $cat;
  977. }
  978. function munge_comment($text, $blog) {
  979. if (!$blog->blog_allow_comment_html) {
  980. $text = strip_tags($text);
  981. }
  982. if ($blog->blog_autolink_urls) {
  983. $text = preg_replace('!(^|\s|>)(https?://[^\s<]+)!s', '$1<a href="$2">$2</a>', $text);
  984. }
  985. return $text;
  986. }
  987. function length_text($text) {
  988. if (!extension_loaded('mbstring')) {
  989. $len = strlen($text);
  990. } else {
  991. $len = mb_strlen($text);
  992. }
  993. return $len;
  994. }
  995. function substr_text($text, $startpos, $length) {
  996. if (!extension_loaded('mbstring')) {
  997. $text = substr($text, $startpos, $length);
  998. } else {
  999. $text = mb_substr($text, $startpos, $length);
  1000. }
  1001. return $text;
  1002. }
  1003. function first_n_text($text, $n) {
  1004. if (!isset($lang) || empty($lang)) {
  1005. $mt = MT::get_instance();
  1006. $lang = ($blog && $blog->blog_language ? $blog->blog_language :
  1007. $mt->config('DefaultLanguage'));
  1008. }
  1009. if ($lang == 'jp') {
  1010. $lang = 'ja';
  1011. }
  1012. if ($lang == 'ja') {
  1013. $text = strip_tags($text);
  1014. $text = preg_replace('/\r?\n/', " ", $text);
  1015. return substr_text($text, 0, $n);
  1016. }else{
  1017. return first_n_words($text, $n);
  1018. }
  1019. }
  1020. function tag_split_delim($delim, $str) {
  1021. $delim = quotemeta($delim);
  1022. $tags = array();
  1023. $str = trim($str);
  1024. while (strlen($str) && (preg_match("/^(((['\"])(.*?)\3[^$delim]*?|.*?)($delim\s*|$))/s", $str, $match))) {
  1025. $str = substr($str, strlen($match[1]));
  1026. $tag = (isset($match[4]) && $match[4] != '') ? $match[4] : $match[2];
  1027. $tag = trim($tag);
  1028. $tag = preg_replace('/\s+/', ' ', $tag);
  1029. $n8d_tag = tag_normalize($tag);
  1030. if ($n8d_tag != '')
  1031. if ($tag != '') $tags[] = $tag;
  1032. }
  1033. return $tags;
  1034. }
  1035. function tag_split($str) {
  1036. return tag_split_delim(',', $str);
  1037. }
  1038. function catarray_path_length_sort($a, $b) {
  1039. $al = strlen($a->category_label_path);
  1040. $bl = strlen($b->category_label_path);
  1041. return $al === $bl ? 0 : ($al < $bl ? 1 : -1);
  1042. }
  1043. # sorts by length of category label, from longest to shortest
  1044. function catarray_length_sort($a, $b) {
  1045. $al = strlen($a->category_label);
  1046. $bl = strlen($b->category_label);
  1047. return $al === $bl ? 0 : ($al < $bl ? 1 : -1);
  1048. }
  1049. function create_expr_exception($m) {
  1050. if ($m[2])
  1051. return '(0)';
  1052. else
  1053. return $m[1];
  1054. }
  1055. function create_cat_expr_function($expr, &$cats, $datasource = 'entry', $param) {
  1056. $mt = MT::get_instance();
  1057. $cats_used = array();
  1058. $orig_expr = $expr;
  1059. $include_children = $param['children'] ? 1 : 0;
  1060. $cats_used = array();
  1061. if (preg_match('/\//', $expr)) {
  1062. foreach ($cats as $id => $cat) {
  1063. $catp = category_label_path($cat);
  1064. $cats[$id]->category_label_path = $catp;
  1065. }
  1066. $cols = array('category_label_path', 'category_label');
  1067. } else {
  1068. $cols = array('category_label');
  1069. }
  1070. foreach ($cols as $col) {
  1071. if ($col == 'category_label_path') {
  1072. usort($cats, 'catarray_path_length_sort');
  1073. } else {
  1074. usort($cats, 'catarray_length_sort');
  1075. }
  1076. $cats_replaced = array();
  1077. foreach ($cats as $cat) {
  1078. $catl = $cat->$col;
  1079. $catid = $cat->category_id;
  1080. $catre = preg_quote($catl, "/");
  1081. if (!preg_match("/(?:(?<![#\d])\[$catre\]|$catre)|(?:#$catid\b)/", $expr))
  1082. continue;
  1083. if ($include_children) {
  1084. $kids = array($cat);
  1085. $child_cats = array();
  1086. while ($c = array_shift($kids)) {
  1087. $child_cats[$c->category_id] = $c;
  1088. $children = $mt->db()->fetch_categories(array('category_id' => $c->category_id, 'children' => 1, 'show_empty' => 1, 'class' => $c->category_class));
  1089. if ($children) {
  1090. foreach ($children as $child) {
  1091. $kids[] = $child;
  1092. }
  1093. }
  1094. }
  1095. $repl = '';
  1096. foreach ($child_cats as $ccid => $cc) {
  1097. $repl .= ' OR #' . $ccid;
  1098. }
  1099. if (strlen($repl)) $repl = substr($repl, 4);
  1100. $repl = " $repl ";
  1101. } else {
  1102. $repl = " #$catid ";
  1103. }
  1104. if (isset($cats_replaced[$catl])) {
  1105. $last_catid = $cats_replaced[$catl];
  1106. $expr = preg_replace("/(#$last_catid\b)/", '($1 OR #' . $catid . ')', $expr);
  1107. } else {
  1108. $expr = preg_replace("/(?:(?<!#)(?:\[$catre\]|$catre))|#$catid\b/", $repl,
  1109. $expr);
  1110. $cats_replaced[$catl] = $catid;
  1111. }
  1112. if ($include_children) {
  1113. foreach ($child_cats as $ccid => $cc)
  1114. $cats_used[$ccid] = $cc;
  1115. } else {
  1116. $cats_used[$catid] = $cat;
  1117. }
  1118. }
  1119. }
  1120. # when $expr not containing AND, OR or NOT, parenthesis is invalid token.
  1121. if (preg_match('/\b(AND|OR|NOT)\b/i', $expr)) {
  1122. $regexp = '#\d+|&&|\|\||!|\(|\)';
  1123. }
  1124. else {
  1125. $regexp = '#\d+';
  1126. }
  1127. $expr = preg_replace('/\bAND\b/i', '&&', $expr);
  1128. $expr = preg_replace('/\bOR\b/i', '||', $expr);
  1129. $expr = preg_replace('/\bNOT\b/i', '!', $expr);
  1130. # replace any other 'thing' with '(0)' since it's a category that doesn't even exist.
  1131. $cat_expr = preg_split("/($regexp)/", $expr, NULL, PREG_SPLIT_DELIM_CAPTURE | PREG_SPLIT_NO_EMPTY);
  1132. $new_cat_expr = array();
  1133. foreach ($cat_expr as $token) {
  1134. if (preg_match("/^(\s+|$regexp)$/", $token, $matches)) {
  1135. $new_cat_expr[] = $matches[0];
  1136. } else {
  1137. $new_cat_expr[] = '(0)';
  1138. }
  1139. }
  1140. $expr = implode($new_cat_expr);
  1141. # strip out all the 'ok' stuff. if anything is left, we have
  1142. # some invalid data in our expression:
  1143. $test_expr = preg_replace("/\s+|\(0\)|$regexp/", '', $expr);
  1144. if ($test_expr != '') {
  1145. echo "Invalid category filter: $orig_expr";
  1146. return;
  1147. }
  1148. if (!preg_match('/!/', $expr))
  1149. $cats = array_values($cats_used);
  1150. $expr = preg_replace('/#(\d+)/', "array_key_exists('\\1', \$pm)", $expr);
  1151. $expr = '$pm = array_key_exists($o->'.$datasource.'_id, $c["c"]) ? $c["c"][$o->'.$datasource.'_id] : array(); return (' . $expr . ');';
  1152. try {
  1153. eval("\$fn = function(&\$o, &\$c) { $expr };");
  1154. } catch (ParseError $e) {
  1155. $error = true;
  1156. }
  1157. if ($error || $fn === FALSE) {
  1158. echo "Invalid category filter: $orig_expr";
  1159. return;
  1160. }
  1161. return $fn;
  1162. }
  1163. function category_label_path($cat) {
  1164. $mt = MT::get_instance();
  1165. $mtdb =& $mt->db();
  1166. if (isset($cat->__label_path))
  1167. return $cat->__label_path;
  1168. $result = preg_match('/\//', $cat->category_label) ? '[' . $cat->category_label . ']' : $cat->category_label;
  1169. while ($cat) {
  1170. $cat = $cat->category_parent ? $mtdb->fetch_category($cat->category_parent) : null;
  1171. if ($cat)
  1172. $result = (preg_match('/\//', $cat->category_label) ? '[' . $cat->category_label . ']' : $cat->category_label) . '/' . $result;
  1173. }
  1174. # caching this information may be problematic IF
  1175. # parent category labels are changed.
  1176. $cat->__label_path = $result;
  1177. return $result;
  1178. }
  1179. function cat_path_to_category($path, $blogs = null, $class = 'category', $category_set_id = 0) {
  1180. $mt = MT::get_instance();
  1181. if (!$blogs) {
  1182. $ctx = $mt->context();
  1183. $blogs = array('include_blogs' => $ctx->stash('blog_id'));
  1184. }
  1185. if (!is_array($blogs))
  1186. $blogs = array($blogs);
  1187. $mtdb =& $mt->db();
  1188. if (preg_match_all('/(\[[^]]+?\]|[^]\/]+)/', $path, $matches)) {
  1189. # split on slashes, fields quoted by []
  1190. $cat_path = $matches[1];
  1191. for ($i = 0; $i < count($cat_path); $i++) {
  1192. $cat_path[$i] = preg_replace('/^\[(.*)\]$/', '\1', $cat_path[$i]); # remove any []
  1193. }
  1194. $last_cat_ids = array(0);
  1195. foreach ($cat_path as $label) {
  1196. $cats = $mtdb->fetch_categories(array_merge($blogs, array('label' => $label, 'parent' => $last_cat_ids, 'show_empty' => 1, 'class' => $class, 'category_set_id' => $category_set_id)));
  1197. if (!$cats)
  1198. break;
  1199. $last_cat_ids = array();
  1200. foreach ($cats as $cat)
  1201. $last_cat_ids[] = $cat->category_id;
  1202. }
  1203. }
  1204. if ($cats)
  1205. return $cats;
  1206. if (!$cats && $path) {
  1207. $cats = $mtdb->fetch_categories(array_merge($blogs, array('label' => $path, 'show_empty' => 1, 'class' => $class, 'category_set_id' => $category_set_id)));
  1208. if ($cats)
  1209. return $cats;
  1210. }
  1211. return null;
  1212. }
  1213. # sorts by length of tag name, from longest to shortest
  1214. function tagarray_name_sort($a, $b) {
  1215. return strcmp(strtolower($a->tag_name), strtolower($b->tag_name));
  1216. }
  1217. function create_tag_expr_function($expr, &$tags, $datasource = 'entry') {
  1218. $tags_used = array();
  1219. $orig_expr = $expr;
  1220. $tags_dict = array();
  1221. foreach ($tags as $tag) {
  1222. $tags_dict[$tag->tag_name] = $tag;
  1223. }
  1224. $tokens = preg_split('/\b(AND|NOT|OR|\(\))\b/i', $expr, NULL, PREG_SPLIT_DELIM_CAPTURE | PREG_SPLIT_NO_EMPTY);
  1225. $result = '';
  1226. foreach ($tokens as $t) {
  1227. $upperToken = strtoupper( $t );
  1228. if ( ($t === ')') || ($t === '(') || preg_match('/^\s+$/', $t) ) {
  1229. $result .= $t; continue;
  1230. }
  1231. if ($upperToken === 'AND') {
  1232. $result .= '&&'; continue;
  1233. }
  1234. if ($upperToken === 'OR') {
  1235. $result .= '||'; continue;
  1236. }
  1237. if ($upperToken === 'NOT') {
  1238. $result .= '!'; continue;
  1239. }
  1240. $t = trim($t);
  1241. if (!array_key_exists($t, $tags_dict)) {
  1242. # a tag that does not exists - is always false
  1243. $result .= ' (0) ';
  1244. continue;
  1245. }
  1246. $tag = $tags_dict[$t];
  1247. $result .= ' array_key_exists(' . $tag->tag_id . ', $tm) ';
  1248. $tags_used[$tag->tag_id] = $tag;
  1249. }
  1250. # Populate array (passed in by reference) of used tags
  1251. $tags = array_values($tags_used);
  1252. # Create a PHP-blessed function of that code and return it
  1253. # if all is well. This function will be used later to
  1254. # test for existence of specified tags in entries.
  1255. $expr = '$tm = array_key_exists($o->'.$datasource.'_id, $c["t"]) ? $c["t"][$o->'.$datasource.'_id] : array(); return (' . $result . ');';
  1256. try {
  1257. eval("\$fn = function(&\$o, &\$c) { $expr; };");
  1258. } catch (ParseError $e) {
  1259. $error = true;
  1260. }
  1261. if ($error || $fn === FALSE) {
  1262. echo "Inv…

Large files files are truncated, but you can click here to view the full file