BioTorrents.de’s version of Gazelle
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

twig.class.php 8.1KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277
  1. <?php
  2. declare(strict_types=1);
  3. /**
  4. * Twig class
  5. *
  6. * Converted to a singleton class like $ENV.
  7. * One instance should only ever exist,
  8. * because of its separate disk cache system.
  9. *
  10. * Based on OPS's useful rule set:
  11. * https://github.com/OPSnet/Gazelle/blob/master/app/Util/Twig.php
  12. */
  13. class Twig
  14. {
  15. /**
  16. * __functions
  17. */
  18. private static $Twig = null;
  19. private function __construct()
  20. {
  21. return;
  22. }
  23. public function __clone()
  24. {
  25. return trigger_error(
  26. 'clone() not allowed',
  27. E_USER_ERROR
  28. );
  29. }
  30. public function __wakeup()
  31. {
  32. return trigger_error(
  33. 'wakeup() not allowed',
  34. E_USER_ERROR
  35. );
  36. }
  37. /**
  38. * go
  39. */
  40. public static function go()
  41. {
  42. return (self::$Twig === null)
  43. ? self::$Twig = Twig::factory()
  44. : self::$Twig;
  45. }
  46. /**
  47. * factory
  48. */
  49. private static function factory(): \Twig\Environment
  50. {
  51. $ENV = ENV::go();
  52. # https://twig.symfony.com/doc/3.x/api.html
  53. $Twig = new \Twig\Environment(
  54. new \Twig\Loader\FilesystemLoader("$ENV->SERVER_ROOT/templates"),
  55. [
  56. 'auto_reload' => true,
  57. 'autoescape' => 'name',
  58. 'cache' => "$ENV->WEB_ROOT/cache/twig",
  59. 'debug' => $ENV->DEV,
  60. 'strict_variables' => true,
  61. ]
  62. );
  63. $Twig->addFilter(new \Twig\TwigFilter(
  64. 'article',
  65. function ($word) {
  66. return preg_match('/^[aeiou]/i', $word) ? 'an' : 'a';
  67. }
  68. ));
  69. $Twig->addFilter(new \Twig\TwigFilter(
  70. 'b64',
  71. function (string $binary) {
  72. return base64_encode($binary);
  73. }
  74. ));
  75. $Twig->addFilter(new \Twig\TwigFilter(
  76. 'bb_format',
  77. function ($text) {
  78. return new \Twig\Markup(\Text::full_format($text), 'UTF-8');
  79. }
  80. ));
  81. $Twig->addFilter(new \Twig\TwigFilter(
  82. 'checked',
  83. function ($isChecked) {
  84. return $isChecked ? ' checked="checked"' : '';
  85. }
  86. ));
  87. $Twig->addFilter(new \Twig\TwigFilter(
  88. 'image',
  89. function ($i) {
  90. return new \Twig\Markup(\ImageTools::process($i, true), 'UTF-8');
  91. }
  92. ));
  93. $Twig->addFilter(new \Twig\TwigFilter(
  94. 'ipaddr',
  95. function ($ipaddr) {
  96. return new \Twig\Markup(\Tools::display_ip($ipaddr), 'UTF-8');
  97. }
  98. ));
  99. $Twig->addFilter(new \Twig\TwigFilter(
  100. 'octet_size',
  101. function ($size, array $option = []) {
  102. return \Format::get_size($size, empty($option) ? 2 : $option[0]);
  103. },
  104. ['is_variadic' => true]
  105. ));
  106. $Twig->addFilter(new \Twig\TwigFilter(
  107. 'plural',
  108. function ($number) {
  109. return plural($number);
  110. }
  111. ));
  112. $Twig->addFilter(new \Twig\TwigFilter(
  113. 'selected',
  114. function ($isSelected) {
  115. return $isSelected ? ' selected="selected"' : '';
  116. }
  117. ));
  118. $Twig->addFilter(new \Twig\TwigFilter(
  119. 'shorten',
  120. function (string $text, int $length) {
  121. return shortenString($text, $length);
  122. }
  123. ));
  124. $Twig->addFilter(new \Twig\TwigFilter(
  125. 'time_diff',
  126. function ($time) {
  127. return new \Twig\Markup(time_diff($time), 'UTF-8');
  128. }
  129. ));
  130. $Twig->addFilter(new \Twig\TwigFilter(
  131. 'ucfirst',
  132. function ($text) {
  133. return ucfirst($text);
  134. }
  135. ));
  136. $Twig->addFilter(new \Twig\TwigFilter(
  137. 'ucfirstall',
  138. function ($text) {
  139. return implode(' ', array_map(function ($w) {
  140. return ucfirst($w);
  141. }, explode(' ', $text)));
  142. }
  143. ));
  144. $Twig->addFilter(new \Twig\TwigFilter(
  145. 'user_url',
  146. function ($userId) {
  147. return new \Twig\Markup(\Users::format_username($userId, false, false, false), 'UTF-8');
  148. }
  149. ));
  150. $Twig->addFilter(new \Twig\TwigFilter(
  151. 'user_full',
  152. function ($userId) {
  153. return new \Twig\Markup(\Users::format_username($userId, true, true, true, true), 'UTF-8');
  154. }
  155. ));
  156. $Twig->addFunction(new \Twig\TwigFunction('donor_icon', function ($icon, $userId) {
  157. return new \Twig\Markup(
  158. \ImageTools::process($icon, false, 'donoricon', $userId),
  159. 'UTF-8'
  160. );
  161. }));
  162. $Twig->addFunction(new \Twig\TwigFunction('privilege', function ($default, $config, $key) {
  163. return new \Twig\Markup(
  164. (
  165. $default
  166. ? sprintf(
  167. '<input id="%s" type="checkbox" disabled="disabled"%s />&nbsp;',
  168. "default_$key",
  169. (isset($default[$key]) && $default[$key] ? ' checked="checked"' : '')
  170. )
  171. : ''
  172. )
  173. . sprintf(
  174. '<input type="checkbox" name="%s" id="%s" value="1"%s />&nbsp;<label title="%s" for="%s">%s</label><br />',
  175. "perm_$key",
  176. $key,
  177. (empty($config[$key]) ? '' : ' checked="checked"'),
  178. $key,
  179. $key,
  180. \Permissions::list()[$key] ?? "!unknown($key)!"
  181. ),
  182. 'UTF-8'
  183. );
  184. }));
  185. $Twig->addFunction(new \Twig\TwigFunction('ratio', function ($up, $down) {
  186. return new \Twig\Markup(
  187. \Format::get_ratio_html($up, $down),
  188. 'UTF-8'
  189. );
  190. }));
  191. $Twig->addFunction(new \Twig\TwigFunction('resolveCountryIpv4', function ($addr) {
  192. return new \Twig\Markup(
  193. (function ($ip) {
  194. static $cache = [];
  195. if (!isset($cache[$ip])) {
  196. $Class = strtr($ip, '.', '-');
  197. $cache[$ip] = '<span class="cc_'.$Class.'">Resolving CC...'
  198. . '<script type="text/javascript">'
  199. . '$(document).ready(function() {'
  200. . '$.get(\'tools.php?action=get_cc&ip='.$ip.'\', function(cc) {'
  201. . '$(\'.cc_'.$Class.'\').html(cc);'
  202. . '});'
  203. . '});'
  204. . '</script></span>';
  205. }
  206. return $cache[$ip];
  207. })($addr),
  208. 'UTF-8'
  209. );
  210. }));
  211. $Twig->addFunction(new \Twig\TwigFunction('resolveIpv4', function ($addr) {
  212. return new \Twig\Markup(
  213. (function ($ip) {
  214. if (!$ip) {
  215. $ip = '127.0.0.1';
  216. }
  217. static $cache = [];
  218. if (!isset($cache[$ip])) {
  219. $class = strtr($ip, '.', '-');
  220. $cache[$ip] = '<span class="host_' . $class
  221. . '">Resolving host' . "\xE2\x80\xA6" . '<script type="text/javascript">$(document).ready(function() {'
  222. . "\$.get('tools.php?action=get_host&ip=$ip', function(host) {\$('.host_$class').html(host)})})</script></span>";
  223. }
  224. return $cache[$ip];
  225. })($addr),
  226. 'UTF-8'
  227. );
  228. }));
  229. $Twig->addFunction(new \Twig\TwigFunction('shorten', function ($text, $length) {
  230. return new \Twig\Markup(
  231. shortenString($text, $length),
  232. 'UTF-8'
  233. );
  234. }));
  235. $Twig->addTest(
  236. new \Twig\TwigTest('numeric', function ($value) {
  237. return is_numeric($value);
  238. })
  239. );
  240. return $Twig;
  241. }
  242. }