TEXT_Helper.php 9.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276
  1. <?php
  2. /**
  3. * DB helper file.
  4. *
  5. * Provides a helper to perform database operations.
  6. *
  7. * @author Iñigo Valentin <i@inigovalentin.com>
  8. * @license https://www.gnu.org/licenses/gpl-3.0.en.html GNU General Public License V3
  9. * @package IV
  10. */
  11. require_once(__DIR__ . "/Helper.php");
  12. /**
  13. * Text helper.
  14. *
  15. * Contains utilities to show and manipulate texts.
  16. *
  17. * @category Helper.
  18. */
  19. final class TEXT extends Helper{
  20. /**
  21. * Selects the language the page will be displayed on.
  22. *
  23. * First, it tries to read the language cookie in the client. If none is
  24. * set, get the browser language preference list. If none is provided or
  25. * they are not supported, it will use the default language.
  26. *
  27. * @return string Lowercase, two-letter language code.
  28. */
  29. function select_language(){
  30. // Get available languages from db
  31. $available_languages = array();
  32. $q_lang = mysqli_query($db, "SELECT code FROM lang WHERE active = 1;");
  33. while ($r_lang = mysqli_fetch_array($q_lang)){
  34. array_push($available_languages, $r_lang["code"]);
  35. }
  36. // Is there a language cookie installed on the client?.
  37. header("Cache-control: private");
  38. if (isSet($_COOKIE["lang"])){
  39. $lang = $_COOKIE["lang"];
  40. if (in_array($lang, $available_languages)){
  41. return $lang;
  42. }
  43. }
  44. // If no cookie, select from client browser preferences.
  45. $lang = prefered_language($available_languages, $_SERVER["HTTP_ACCEPT_LANGUAGE"]);
  46. if (in_array($lang, $available_languages)){
  47. return $lang;
  48. }
  49. // If no method was succesfull, default language
  50. $lang = $available_languages[0];
  51. return $lang;
  52. }
  53. /**
  54. * Parses the language prefrences of the client broser, comparing them to
  55. * the languages offered by the site and selects the prefered one among
  56. * the ones supported.
  57. *
  58. * @param string[] available_languages List of lowercase, two-letter
  59. * language codes allowed by the site.
  60. * @param string http_accept_language Raw header with info about client
  61. * language preferences.
  62. * @return string Lowercase, two-letter code of the prefered available
  63. * language.
  64. */
  65. function prefered_language(array $available_languages, $http_accept_language) {
  66. $available_languages = array_flip($available_languages);
  67. $langs;
  68. preg_match_all("~([\w-]+)(?:[^,\d]+([\d.]+))?~", strtolower($http_accept_language), $matches, PREG_SET_ORDER);
  69. foreach($matches as $match) {
  70. list($a, $b) = explode("-", $match[1]) + array("", "");
  71. $value = isset($match[2]) ? (float) $match[2] : 1.0;
  72. if(isset($available_languages[$match[1]])) {
  73. $langs[$match[1]] = $value;
  74. continue;
  75. }
  76. if(isset($available_languages[$a])) {
  77. $langs[$a] = $value - 0.1;
  78. }
  79. }
  80. if (count($langs) > 0){
  81. arsort($langs);
  82. //return $langs[0];
  83. array_values($langs)[0];
  84. }
  85. else{
  86. return 'en';
  87. }
  88. }
  89. /**
  90. * Tturns a date string into a human readable string on the specified
  91. * language. Only works for spanish, basque and english.
  92. *
  93. * @param string $str_date Date string ('yyyy-mm-dd' or 'yyyy-mm-dd HH:MM:SS')
  94. * @param string $lang Language code (es, en, eu).
  95. * @param string $time Append the time at the end.
  96. * @return string Formatted date string.
  97. */
  98. function format_date($str_date, $lang, $time = true){
  99. $date = strtotime($str_date);
  100. $year = date("o", $date);
  101. $month = date("n", $date);
  102. $month --;
  103. $day = date("j", $date);
  104. $wday = date("N", $date);
  105. $wday --;
  106. $hour = date("H", $date);
  107. $minute = date("i", $date);
  108. switch ($lang){
  109. case "en":
  110. $week = ["Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", "Sunday"];
  111. $months = ["January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"];
  112. if ($time){
  113. $str = "$week[$wday], $months[$month] $day, $year at $hour:$minute";
  114. }
  115. else{
  116. $str = "$week[$wday], $months[$month] $day, $year";
  117. }
  118. break;
  119. case "eu":
  120. $week = ["astelehena", "asteartea", "asteazkena", "osteguna", "ostirala", "larumbata", "igandea"];
  121. $months = ["urtarrilaren", "otsailaren", "martxoaren", "apirilaren", "maiatzaren", "ekainaren", "uztailaren", "abuztuaren", "irailaren", "urriaren", "azaroaren", "abenduaren"];
  122. if ($time){
  123. $str = $year . "ko $months[$month] $day" . "an, $week[$wday], $hour:$minute";
  124. }
  125. else{
  126. $str = $year . "ko $months[$month] $day" . "an, $week[$wday]";
  127. }
  128. break;
  129. default:
  130. $week = ["Lunes", "Martes", "Mi&eacute;rcoles", "Jueves", "Viernes", "S&aacute;bado", "Domingo"];
  131. $months = ["enero", " febrero", "marzo", "abril", "mayo", "junio", "julio", "agosto", "septiembre", "octubre", "noviembre", "diciembre"];
  132. if ($time){
  133. $str = "$week[$wday] $day de $months[$month] de $year a las $hour:$minute";
  134. }
  135. else{
  136. $str = "$week[$wday] $day de $months[$month] de $year";
  137. }
  138. }
  139. return $str;
  140. }
  141. /**
  142. * Retrieves a text fragment from the database.
  143. *
  144. * @param string $id Text identifier.
  145. * @param bool $html True to decode for HTML.
  146. * @returns string The text.
  147. */
  148. public static function get($id, $html = true){
  149. $statement = get_context()->get_db()->prepare("
  150. SELECT
  151. text,
  152. file
  153. FROM text
  154. WHERE
  155. id = :id AND
  156. lang = :lang
  157. ");
  158. $statement->bindValue(':id', $id, PDO::PARAM_STR);
  159. $statement->bindValue(':lang', get_context()->get_lang(), PDO::PARAM_STR);
  160. $statement->execute();
  161. $row = $statement->fetch(PDO::FETCH_ASSOC);
  162. if ($row !== false){
  163. $text = "";
  164. if (strlen($row["file"]) > 0){
  165. $text = file_get_contents(PATH::TEXT . $row["file"]);
  166. }
  167. else{
  168. $text = $row["text"];
  169. }
  170. $text = utf8_decode($text);
  171. if ($html === true){
  172. $text = htmlentities($text, ENT_QUOTES);
  173. }
  174. return $text;
  175. }
  176. else{
  177. Log::error("Text resource with id '$id' not found.");
  178. return false;
  179. }
  180. }
  181. /**
  182. * This function closes all the opened HTML tags in a given string.
  183. *
  184. * @param string html The string with HTML tags.
  185. * @return string HTML with closed tags.
  186. */
  187. function close_tags($html) {
  188. $result = [];
  189. preg_match_all("#<(?!meta|img|br|hr|input\b)\b([a-z]+)(?: .*)?(?<![/|/ ])>#iU", $html, $result);
  190. $openedtags = $result[1];
  191. preg_match_all("#</([a-z]+)>#iU", $html, $result);
  192. $closedtags = $result[1];
  193. $len_opened = count($openedtags);
  194. if (count($closedtags) == $len_opened) {
  195. return $html;
  196. }
  197. $openedtags = array_reverse($openedtags);
  198. for ($i=0; $i < $len_opened; $i++) {
  199. if (!in_array($openedtags[$i], $closedtags)) {
  200. $html .= "</".$openedtags[$i].">";
  201. } else {
  202. unset($closedtags[array_search($openedtags[$i], $closedtags)]);
  203. }
  204. }
  205. return $html;
  206. }
  207. /**
  208. * Text shortener. Given a string, it trims in the proximity of the
  209. * desired string, up to the next white character. If indicated, it will
  210. * append a link to the full text.
  211. *
  212. * @param string $text The text to shorten.
  213. * @param int $length The desired length.
  214. * @param string $link_text Text for the link. Optional.
  215. * @param string $link URI of the link.
  216. * @return string Shortened text.
  217. */
  218. function cut_text($text, $length, $link_text = "", $link = ""){
  219. if (strlen($text) < $length){
  220. return $text;
  221. }
  222. $cut = substr($text, 0, strpos($text, " ", $length));
  223. $cut = close_tags($cut);
  224. if (strlen($cut) == 0){
  225. $cut = $text;
  226. }
  227. if (strlen($text) != strlen($cut) && strlen($link) > 0 && strlen($link_text) > 0){
  228. $cut = $cut . "... <a href='$link'>$link_text</a>";
  229. }
  230. return $cut;
  231. }
  232. /**
  233. * Creates the srcset attribute for content images.
  234. * Creates 9 different resolutions, from 100px to 900px.
  235. *
  236. * @param string $file Path to the file, relative to $path["img"]["content"]).
  237. * @return string srcset atttribute content.
  238. */
  239. public static function srcset($file){
  240. global $static;
  241. $srcset = "";
  242. $dir = dirname($file);
  243. $name = basename($file);
  244. foreach (range(1, 9) as $d) {
  245. $srcset = $srcset . $static["content"] . $dir . "/x" . $d . "00/" . $name . " " . $d . "00px, ";
  246. }
  247. $srcset = rtrim($srcset, ", ");
  248. return $srcset;
  249. }
  250. }