diff --git a/localization/locale_dede.php b/localization/locale_dede.php index bcf88373d..51b01ba70 100644 --- a/localization/locale_dede.php +++ b/localization/locale_dede.php @@ -14,8 +14,7 @@ 'timeUnits' => array( 'sg' => ["Jahr", "Monat", "Woche", "Tag", "Stunde", "Minute", "Sekunde", "Millisekunde"], 'pl' => ["Jahre", "Monate", "Wochen", "Tage", "Stunden", "Minuten", "Sekunden", "Millisekunden"], - 'ab' => ["J.", "M.", "W.", "Tag", "Std.", "Min.", "Sek.", "Ms."], - 'ago' => 'vor %s' + 'ab' => ["J.", "M.", "W.", "Tag", "Std.", "Min.", "Sek.", "Ms."] ), 'main' => array( 'name' => "Name", @@ -52,6 +51,7 @@ 'or' => " oder ", 'back' => "Zurück", 'reputationTip' => "Rufpunkte", + 'byUserTimeAgo' => "Von %1s vor %s", // filter 'extSearch' => "Erweiterte Suche", diff --git a/localization/locale_enus.php b/localization/locale_enus.php index 46388f036..876d88cab 100644 --- a/localization/locale_enus.php +++ b/localization/locale_enus.php @@ -9,8 +9,7 @@ 'timeUnits' => array( 'sg' => ["year", "month", "week", "day", "hour", "minute", "second", "millisecond"], 'pl' => ["years", "months", "weeks", "days", "hours", "minutes", "seconds", "milliseconds"], - 'ab' => ["yr", "mo", "wk", "day", "hr", "min", "sec", "ms"], - 'ago' => '%s ago' + 'ab' => ["yr", "mo", "wk", "day", "hr", "min", "sec", "ms"] ), 'main' => array( 'name' => "name", @@ -47,6 +46,7 @@ 'or' => " or ", 'back' => "Back", 'reputationTip' => "Reputation points", + 'byUserTimeAgo' => "By %1s %s ago", // filter 'extSearch' => "Extended search", diff --git a/localization/locale_eses.php b/localization/locale_eses.php index 653f58d39..7b56d5aa9 100644 --- a/localization/locale_eses.php +++ b/localization/locale_eses.php @@ -14,8 +14,7 @@ 'timeUnits' => array( 'sg' => ["año", "mes", "semana", "día", "hora", "minuto", "segundo", "milisegundo"], 'pl' => ["años", "meses", "semanas", "dias", "horas", "minutos", "segundos", "milisegundos"], - 'ab' => ["año", "mes", "sem", "", "h", "min", "seg", "ms"], - 'ago' => 'hace %s' + 'ab' => ["año", "mes", "sem", "", "h", "min", "seg", "ms"] ), 'main' => array( 'name' => "nombre", @@ -52,6 +51,7 @@ 'or' => " o ", 'back' => "Arrière", 'reputationTip' => "Puntos de reputación", + 'byUserTimeAgo' => "Por %1s hace %s", // filter 'extSearch' => "Extender búsqueda", diff --git a/localization/locale_frfr.php b/localization/locale_frfr.php index 975b917f8..67941ed44 100644 --- a/localization/locale_frfr.php +++ b/localization/locale_frfr.php @@ -14,8 +14,7 @@ 'timeUnits' => array( 'sg' => ["année", "mois", "semaine", "jour", "heure", "minute", "seconde", "milliseconde"], 'pl' => ["années", "mois", "semaines", "jours", "heures", "minutes", "secondes", "millisecondes"], - 'ab' => ["an", "mo", "sem", "jour", "h", "min", "s", "ms"], - 'ago' => 'il y a %s' + 'ab' => ["an", "mo", "sem", "jour", "h", "min", "s", "ms"] ), 'main' => array( 'name' => "nom", @@ -52,6 +51,7 @@ 'or' => " ou ", 'back' => "Redro", 'reputationTip' => "Points de réputation", + 'byUserTimeAgo' => "Par %1s il y a %s", // filter 'extSearch' => "Recherche avancée", diff --git a/localization/locale_ruru.php b/localization/locale_ruru.php index 4e0e2d8a4..59867a62c 100644 --- a/localization/locale_ruru.php +++ b/localization/locale_ruru.php @@ -14,8 +14,7 @@ 'timeUnits' => array( 'sg' => ["год", "месяц", "неделя", "день", "час", "минута", "секунда", "миллисекунда"], 'pl' => ["годы", "месяцы", "недели", "дн.", "часы", "мин", "секунды", "миллисекундах"], - 'ab' => ["г.", "мес.", "нед.", "дн", "ч.", "мин", "сек.", "мс"], - 'ago' => '%s назад' + 'ab' => ["г.", "мес.", "нед.", "дн", "ч.", "мин", "сек.", "мс"] ), 'main' => array( 'name' => "название", @@ -52,6 +51,7 @@ 'or' => " или ", 'back' => "Назад", 'reputationTip' => "Очки репутации", + 'byUserTimeAgo' => "От %1s %s назад", // filter 'extSearch' => "Расширенный поиск", diff --git a/pages/utility.php b/pages/utility.php index dbf6caca7..2ca1d815d 100644 --- a/pages/utility.php +++ b/pages/utility.php @@ -16,8 +16,10 @@ class UtilityPage extends GenericPage 'latest-additions', 'latest-articles', 'latest-comments', 'latest-screenshots', 'random', 'unrated-comments', 11 => 'latest-videos', 12 => 'most-comments', 13 => 'missing-screenshots' ); + private $page = ''; private $rss = false; + private $feedData = []; public function __construct($pageCall, $pageParam) { @@ -44,7 +46,7 @@ public function display($override = '') { if ($this->rss) // this should not be cached { - header('Content-Type: application/rss+xml; charset=ISO-8859-1'); + header('Content-Type: application/rss+xml; charset=UTF-8'); die($this->generateRSS()); } else @@ -68,31 +70,103 @@ protected function generateContent() header('Location: ?'.Util::$typeStrings[$type].'='.$typeId, true, 302); die(); - case 'latest-comments': - $this->lvTabs[] = array( - 'file' => 'commentpreview', - 'data' => CommunityContent::getCommentPreviews(), - 'params' => [] - ); + case 'latest-comments': // rss + $data = CommunityContent::getCommentPreviews(); + + if ($this->rss) + { + foreach ($data as $d) + { + // todo (low): preview should be html-formated + $this->feedData[] = array( + 'title' => [true, [], Util::ucFirst(Lang::game(Util::$typeStrings[$d['type']])).Lang::main('colon').htmlentities($d['subject'])], + 'link' => [false, [], HOST_URL.'/?go-to-comment&id='.$d['id']], + 'description' => [true, [], htmlentities($d['preview'])."

".sprintf(Lang::main('byUserTimeAgo'), $d['user'], Util::formatTime($d['elapsed'] * 1000, true))], + 'pubDate' => [false, [], date(DATE_RSS, time() - $d['elapsed'])], + 'guid' => [false, [], HOST_URL.'/?go-to-comment&id='.$d['id']] + // 'domain' => [false, [], null] + ); + } + } + else + { + $this->lvTabs[] = array( + 'file' => 'commentpreview', + 'data' => $data, + 'params' => [] + ); + } break; - case 'latest-screenshots': - $this->lvTabs[] = array( - 'file' => 'screenshot', - 'data' => CommunityContent::getScreenshots(), - 'params' => [] - ); + case 'latest-screenshots': // rss + $data = CommunityContent::getScreenshots(); + + if ($this->rss) + { + foreach ($data as $d) + { + $desc = ''; + if ($d['caption']) + $desc .= '
'.$d['caption']; + $desc .= "

".sprintf(Lang::main('byUserTimeAgo'), $d['user'], Util::formatTime($d['elapsed'] * 1000, true)); + + // enclosure/length => filesize('static/uploads/screenshots/thumb/'.$d['id'].'.jpg') .. always set to this placeholder value though + $this->feedData[] = array( + 'title' => [true, [], Util::ucFirst(Lang::game(Util::$typeStrings[$d['type']])).Lang::main('colon').htmlentities($d['subject'])], + 'link' => [false, [], HOST_URL.'/?'.Util::$typeStrings[$d['type']].'='.$d['typeId'].'#screenshots:id='.$d['id']], + 'description' => [true, [], $desc], + 'pubDate' => [false, [], date(DATE_RSS, time() - $d['elapsed'])], + 'enclosure' => [false, ['url' => STATIC_URL.'/uploads/screenshots/thumb/'.$d['id'].'.jpg', 'length' => 12345, 'type' => 'image/jpeg'], null], + 'guid' => [false, [], HOST_URL.'/?'.Util::$typeStrings[$d['type']].'='.$d['typeId'].'#screenshots:id='.$d['id']], + // 'domain' => [false, [], live|ptr] + ); + } + } + else + { + $this->lvTabs[] = array( + 'file' => 'screenshot', + 'data' => $data, + 'params' => [] + ); + } break; - case 'latest-videos': - $this->lvTabs[] = array( - 'file' => 'video', - 'data' => CommunityContent::getVideos(), - 'params' => [] - ); + case 'latest-videos': // rss + $data = CommunityContent::getVideos(); + + if ($this->rss) + { + foreach ($data as $d) + { + $desc = ''; + if ($d['caption']) + $desc .= '
'.$d['caption']; + $desc .= "

".sprintf(Lang::main('byUserTimeAgo'), $d['user'], Util::formatTime($d['elapsed'] * 1000, true)); + + // is enclosure/length .. is this even relevant..? + $this->feedData[] = array( + 'title' => [true, [], Util::ucFirst(Lang::game(Util::$typeStrings[$d['type']])).Lang::main('colon').htmlentities($row['subject'])], + 'link' => [false, [], HOST_URL.'/?'.Util::$typeStrings[$d['type']].'='.$d['typeId'].'#videos:id='.$d['id']], + 'description' => [true, [], $desc], + 'pubDate' => [false, [], date(DATE_RSS, time() - $row['elapsed'])], + 'enclosure' => [false, ['url' => '//i3.ytimg.com/vi/'.$d['videoId'].'/default.jpg', 'length' => 12345, 'type' => 'image/jpeg'], null], + 'guid' => [false, [], HOST_URL.'/?'.Util::$typeStrings[$d['type']].'='.$d['typeId'].'#videos:id='.$d['id']], + // 'domain' => [false, [], live|ptr] + ); + } + } + else + { + $this->lvTabs[] = array( + 'file' => 'video', + 'data' => $data, + 'params' => [] + ); + } break; - case 'latest-articles': + case 'latest-articles': // rss $this->lvTabs = []; break; - case 'latest-additions': + case 'latest-additions': // rss $extraText = ''; break; case 'unrated-comments': @@ -125,7 +199,7 @@ protected function generateContent() } } break; - case 'most-comments': + case 'most-comments': // rss if ($this->category && !in_array($this->category[0], [1, 7, 30])) header('Location: ?most-comments=1'.($this->rss ? '&rss' : null), true, 302); @@ -155,23 +229,39 @@ protected function generateContent() if (!$typeClass->error) { $data = $typeClass->getListviewData(); - foreach ($data as $typeId => &$d) - $d['ncomments'] = $comments[$typeId]; - $this->extendGlobalData($typeClass->getJSGlobals(GLOBALINFO_ANY)); - $this->lvTabs[] = array( - 'file' => $typeClass::$brickFile, - 'data' => $data, - 'params' => $params, - '_type' => Util::$typeStrings[$type] - ); + if ($this->rss) + { + foreach ($data as $typeId => &$d) + { + $this->feedData[] = array( + 'title' => [true, [], htmlentities(Util::$typeStrings[$type] == 'item' ? substr($d['name'], 1) : $d['name'])], + 'type' => [false, [], Util::$typeStrings[$type]], + 'link' => [false, [], HOST_URL.'/?'.Util::$typeStrings[$type].'='.$d['id']], + 'ncomments' => [false, [], $comments[$typeId]['ncomments']] + ); + } + } + else + { + foreach ($data as $typeId => &$d) + $d['ncomments'] = $comments[$typeId]['ncomments']; + + $this->extendGlobalData($typeClass->getJSGlobals(GLOBALINFO_ANY)); + $this->lvTabs[] = array( + 'file' => $typeClass::$brickFile, + 'data' => $data, + 'params' => $params + ); + } } } + break; } // found nothing => set empty content - if (!$this->lvTabs) + if (!$this->lvTabs && !$this->rss) { $this->lvTabs[] = array( 'file' => 'commentpreview', // anything, doesn't matter what @@ -185,49 +275,35 @@ protected function generateRSS() { $this->generateContent(); - $xml = "\n". - "\n\n". - "".CFG_NAME_SHORT.' - '.$this->name."\n". - "".HOST_URL.'?'.$this->page . ($this->category ? '='.$this->category[0] : null)."\n". - "".CFG_NAME."\n". - "".implode('-', str_split(User::$localeString, 2))."\n". - "".CFG_TTL_RSS."\n". - "".date(DATE_RSS)."\n"; + $root = new SimpleXML(''); + $root->addAttribute('version', '2.0'); + $channel = $root->addChild('channel'); - if ($this->page == 'most-comments') - { - foreach ($this->lvTabs as $tab) - { - foreach ($tab['data'] as $row) - { - $xml .= "\n". - "<![CDATA[".htmlentities($tab['_type'] == 'item' ? substr($row['name'], 1) : $row['name'])."]]>\n". - "".$tab['_type']."\n". - "".HOST_URL.'/?'.$tab['_type'].'='.$row['id']."\n". - "".$row['ncomments']."\n". - "\n"; - } - } - } - else + $channel->addChild('title', CFG_NAME_SHORT.' - '.$this->name); + $channel->addChild('link', HOST_URL.'/?'.$this->page . ($this->category ? '='.$this->category[0] : null)); + $channel->addChild('description', CFG_NAME); + $channel->addChild('language', implode('-', str_split(User::$localeString, 2))); + $channel->addChild('ttl', CFG_TTL_RSS); + $channel->addChild('lastBuildDate', date(DATE_RSS)); + + foreach ($this->feedData as $row) { - foreach ($this->lvTabs[0]['data'] as $row) + $item = $channel->addChild('item'); + + foreach ($row as $key => list($isCData, $attrib, $text)) { - $xml .= "\n". - "<![CDATA[".htmlentities($row['subject'])."]]>\n". - "".HOST_URL.'?go-to-comment&id='.$row['id']."\n". - "\n". // todo (low): preview should be html-formated - "".date(DATE_RSS, time() - $row['elapsed'])."\n". - "".HOST_URL.'?go-to-comment&id='.$row['id']."\n". - "\n". - "\n"; + if ($isCData && $text) + $child = $item->addChild($key)->addCData($text); + else + $child = $item->addChild($key, $text); + + foreach ($attrib as $k => $v) + $child->addAttribute($k, $v); } } - $xml .= "\n"; - - return $xml; + return $root->asXML(); } protected function generateTitle()