diff --git a/classes/class_debug.php b/classes/class_debug.php index 09f9ecc2..94cfb4b7 100644 --- a/classes/class_debug.php +++ b/classes/class_debug.php @@ -199,6 +199,20 @@ public function php_error_handler($Level, $Error, $File, $Line) { /* Data wrappers */ public function get_perf() { + if (empty($this->Perf)) { + global $ScriptStartTime; + $PageTime = (microtime(true) - $ScriptStartTime); + $Perf = array(); + $Perf['Memory usage'] = Format::get_size(memory_get_usage(true)); + $Perf['Page process time'] = number_format($PageTime, 3).' s'; + if (!defined('PHP_WINDOWS_VERSION_MAJOR')) { + global $CPUTimeStart; + $RUsage = getrusage(); + $CPUTime = ($RUsage["ru_utime.tv_sec"]*1000000 + $RUsage['ru_utime.tv_usec'] - $CPUTimeStart) / 1000000; + $Perf['CPU time'] = number_format($CPUTime, 3)." s"; + } + return $Perf; + } return $this->Perf; } diff --git a/classes/class_votes.php b/classes/class_votes.php new file mode 100644 index 00000000..b3b0a25c --- /dev/null +++ b/classes/class_votes.php @@ -0,0 +1,172 @@ + + + ( Vote: + Up + Up + Down + Down + x + ) + +(GroupID, 'Up'|'Down') + */ + public static function get_user_votes($UserID) { + global $DB, $Cache; + + if ((int)$UserID == 0) { + return array(); + } + + $UserVotes = $Cache->get_value('voted_albums_'.$UserID); + if ($UserVotes === FALSE) { + $DB->query('SELECT GroupID, Type FROM users_votes WHERE UserID='.$UserID); + $UserVotes = $DB->to_array('GroupID', MYSQL_ASSOC, false); + $Cache->cache_value('voted_albums_'.$UserID, $UserVotes); + } + return $UserVotes; + } + + /** + * Returns an array with torrent group vote data + * @global CACHE $Cache + * @global DB_MYSQL $DB + * @param string|int $GroupID + * @return array (Upvotes, Total Votes) + */ + public static function get_group_votes($GroupID) { + global $DB, $Cache; + + $GroupVotes = $Cache->get_value('votes_'.$GroupID); + if ($GroupVotes === FALSE) { + $DB->query("SELECT Ups AS Ups, Total AS Total FROM torrents_votes WHERE GroupID=$GroupID"); + if ($DB->record_count() == 0) { + $GroupVotes = array('Ups'=>0, 'Total'=>0); + } else { + $GroupVotes = $DB->next_record(MYSQLI_ASSOC, false); + } + $Cache->cache_value('votes_'.$GroupID, $GroupVotes); + } + return $GroupVotes; + } + + /** + * Computes the inverse normal CDF of a p-value + * @param float $GroupID + * @return float Inverse Normal CDF + */ + private function inverse_ncdf($p) { + /*************************************************************************** + * inverse_ncdf.php + * ------------------- + * begin : Friday, January 16, 2004 + * copyright : (C) 2004 Michael Nickerson + * email : nickersonm@yahoo.com + * + ***************************************************************************/ + + //Inverse ncdf approximation by Peter John Acklam, implementation adapted to + //PHP by Michael Nickerson, using Dr. Thomas Ziegler's C implementation as + //a guide. http://home.online.no/~pjacklam/notes/invnorm/index.html + //I have not checked the accuracy of this implementation. Be aware that PHP + //will truncate the coeficcients to 14 digits. + + //You have permission to use and distribute this function freely for + //whatever purpose you want, but please show common courtesy and give credit + //where credit is due. + + //Input paramater is $p - probability - where 0 < p < 1. + + //Coefficients in rational approximations + $a = array(1 => -3.969683028665376e+01, 2 => 2.209460984245205e+02, + 3 => -2.759285104469687e+02, 4 => 1.383577518672690e+02, + 5 => -3.066479806614716e+01, 6 => 2.506628277459239e+00); + + $b = array(1 => -5.447609879822406e+01, 2 => 1.615858368580409e+02, + 3 => -1.556989798598866e+02, 4 => 6.680131188771972e+01, + 5 => -1.328068155288572e+01); + + $c = array(1 => -7.784894002430293e-03, 2 => -3.223964580411365e-01, + 3 => -2.400758277161838e+00, 4 => -2.549732539343734e+00, + 5 => 4.374664141464968e+00, 6 => 2.938163982698783e+00); + + $d = array(1 => 7.784695709041462e-03, 2 => 3.224671290700398e-01, + 3 => 2.445134137142996e+00, 4 => 3.754408661907416e+00); + + //Define break-points. + $p_low = 0.02425; //Use lower region approx. below this + $p_high = 1 - $p_low; //Use upper region approx. above this + + //Define/list variables (doesn't really need a definition) + //$p (probability), $sigma (std. deviation), and $mu (mean) are user inputs + $q = NULL; $x = NULL; $y = NULL; $r = NULL; + + //Rational approximation for lower region. + if (0 < $p && $p < $p_low) { + $q = sqrt(-2 * log($p)); + $x = ((((($c[1] * $q + $c[2]) * $q + $c[3]) * $q + $c[4]) * $q + $c[5]) * + $q + $c[6]) / (((($d[1] * $q + $d[2]) * $q + $d[3]) * $q + $d[4]) * + $q + 1); + } + + //Rational approximation for central region. + elseif ($p_low <= $p && $p <= $p_high) { + $q = $p - 0.5; + $r = $q * $q; + $x = ((((($a[1] * $r + $a[2]) * $r + $a[3]) * $r + $a[4]) * $r + $a[5]) * + $r + $a[6]) * $q / ((((($b[1] * $r + $b[2]) * $r + $b[3]) * $r + + $b[4]) * $r + $b[5]) * $r + 1); + } + + //Rational approximation for upper region. + elseif ($p_high < $p && $p < 1) { + $q = sqrt(-2 * log(1 - $p)); + $x = -((((($c[1] * $q + $c[2]) * $q + $c[3]) * $q + $c[4]) * $q + + $c[5]) * $q + $c[6]) / (((($d[1] * $q + $d[2]) * $q + $d[3]) * + $q + $d[4]) * $q + 1); + } + + //If 0 < p < 1, return a null value + else { + $x = NULL; + } + + return $x; + //END inverse ncdf implementation. + } + + /** + * Implementation of the algorithm described at http://www.evanmiller.org/how-not-to-sort-by-average-rating.html + * @param int $Ups Number of upvotes + * @param int $Total Number of total votes + * @return float Ranking score + */ + public static function binomial_score($Ups, $Total) { + // Confidence level for binomial scoring (p-value .95) + define(Z_VAL, 1.645211440143815); + + if (($Total <= 0) || ($Ups < 0)) { + return 0; + } + $phat = $Ups/$Total; + return ($phat + Z_VAL*Z_VAL/(2*$Total) - Z_VAL*sqrt(($phat*(1-$phat)+Z_VAL*Z_VAL/(4*$Total))/$Total))/(1+Z_VAL*Z_VAL/$Total); + } +} +?> \ No newline at end of file diff --git a/classes/script_start.php b/classes/script_start.php index d6f67e01..0b412d81 100644 --- a/classes/script_start.php +++ b/classes/script_start.php @@ -131,6 +131,9 @@ case 'TEXTAREA_PREVIEW': $FileName = 'class_textarea_preview'; break; + case 'Votes': + $FileName = 'class_votes'; + break; default: die("Couldn't import class " . $ClassName); } diff --git a/design/privatefooter.php b/design/privatefooter.php index 00523b96..c8aa1c2b 100644 --- a/design/privatefooter.php +++ b/design/privatefooter.php @@ -35,6 +35,7 @@
perf_table(); $Debug->flag_table(); $Debug->error_table(); $Debug->sphinx_table(); diff --git a/design/views/generic/textarea/buttons.phtml b/design/views/generic/textarea/buttons.phtml index ca3cd968..5208b8a2 100644 --- a/design/views/generic/textarea/buttons.phtml +++ b/design/views/generic/textarea/buttons.phtml @@ -1,3 +1,5 @@ - - +
+ + +
diff --git a/sections/ajax/browse.php b/sections/ajax/browse.php index bacb7473..dae430fc 100644 --- a/sections/ajax/browse.php +++ b/sections/ajax/browse.php @@ -15,14 +15,15 @@ function header_link($SortKey,$DefaultWay="desc") { return "torrents.php?order_way=".$NewWay."&order_by=".$SortKey."&".Format::get_url(array('order_way','order_by')); } +/** Start default parameters and validation **/ // Setting default search options -if(!empty($_GET['setdefault'])) { +if (!empty($_GET['setdefault'])) { $UnsetList = array('page','setdefault'); $UnsetRegexp = '/(&|^)('.implode('|',$UnsetList).')=.*?(&|$)/i'; $DB->query("SELECT SiteOptions FROM users_info WHERE UserID='".db_string($LoggedUser['ID'])."'"); list($SiteOptions)=$DB->next_record(MYSQLI_NUM, false); - if(!empty($SiteOptions)) { + if (!empty($SiteOptions)) { $SiteOptions = unserialize($SiteOptions); } else { $SiteOptions = array(); @@ -34,7 +35,7 @@ function header_link($SortKey,$DefaultWay="desc") { $Cache->commit_transaction(0); // Clearing default search options -} elseif(!empty($_GET['cleardefault'])) { +} elseif (!empty($_GET['cleardefault'])) { $DB->query("SELECT SiteOptions FROM users_info WHERE UserID='".db_string($LoggedUser['ID'])."'"); list($SiteOptions)=$DB->next_record(MYSQLI_NUM, false); $SiteOptions=unserialize($SiteOptions); @@ -45,266 +46,449 @@ function header_link($SortKey,$DefaultWay="desc") { $Cache->commit_transaction(0); // Use default search options -} elseif((empty($_SERVER['QUERY_STRING']) || (count($_GET) == 1 && isset($_GET['page']))) && !empty($LoggedUser['DefaultSearch'])) { - if(!empty($_GET['page'])) { - $Page = $_GET['page']; - parse_str($LoggedUser['DefaultSearch'],$_GET); - $_GET['page'] = $Page; - } else { - parse_str($LoggedUser['DefaultSearch'],$_GET); - } -} - -array_pop($Bitrates); // remove 'other' -$SearchBitrates = array_merge($Bitrates, array('v0','v1','v2','24bit')); - -foreach($SearchBitrates as $ID=>$Val) { - $SearchBitrates[$ID]=strtolower($Val); -} -foreach($Formats as $ID=>$Val) { - $SearchFormats[$ID]=strtolower($Val); -} - -$Queries = array(); - -//Simple search -if(!empty($_GET['searchstr'])) { - $Words = explode(' ',strtolower($_GET['searchstr'])); - $FilterBitrates = array_intersect($Words, $SearchBitrates); - if(count($FilterBitrates)>0) { - $Queries[]='@encoding '.implode(' ',$FilterBitrates); - } - - $FilterFormats = array_intersect($Words, $SearchFormats); - if(count($FilterFormats)>0) { - $Queries[]='@format '.implode(' ',$FilterFormats); - } - - if(in_array('100%', $Words)) { - $_GET['haslog'] = '100'; - unset($Words[array_search('100%',$Words)]); - } - - $Words = array_diff($Words, $FilterBitrates, $FilterFormats); - if(!empty($Words)) { - foreach($Words as $Key => &$Word) { - if($Word[0] == '!' && strlen($Word) >= 3 && count($Words) >= 2) { - if(strpos($Word,'!',1) === false) { - $Word = '!'.$SS->escape_string(substr($Word,1)); - } else { - $Word = $SS->escape_string($Word); - } - } elseif(strlen($Word) >= 2) { - $Word = $SS->escape_string($Word); - } else { - unset($Words[$Key]); - } - } - unset($Word); - $Words = trim(implode(' ',$Words)); - if(!empty($Words)) { - $Queries[]='@(groupname,artistname,yearfulltext) '.$Words; - } - } -} - -if(!empty($_GET['taglist'])) { - $_GET['taglist'] = str_replace('.','_',$_GET['taglist']); - $TagList = explode(',',$_GET['taglist']); - $TagListEx = array(); - foreach($TagList as $Key => &$Tag) { - $Tag = trim($Tag); - if(strlen($Tag) >= 2) { - if($Tag[0] == '!' && strlen($Tag) >= 3) { - $TagListEx[] = '!'.$SS->escape_string(substr($Tag,1)); - unset($TagList[$Key]); - } else { - $Tag = $SS->escape_string($Tag); - } +} elseif (empty($_SERVER['QUERY_STRING']) || (count($_GET) == 1 && isset($_GET['page']))) { + if (!empty($LoggedUser['DefaultSearch'])) { + if (!empty($_GET['page'])) { + $Page = $_GET['page']; + parse_str($LoggedUser['DefaultSearch'],$_GET); + $_GET['page'] = $Page; } else { - unset($TagList[$Key]); + parse_str($LoggedUser['DefaultSearch'],$_GET); } } - unset($Tag); +} +// Terms were not submitted via the search form +if (!isset($_GET['searchsubmit'])) { + $_GET['group_results'] = !$LoggedUser['DisableGrouping2']; } -if(empty($_GET['tags_type']) && !empty($TagList) && count($TagList) > 1) { - $_GET['tags_type'] = '0'; - if(!empty($TagListEx)) { - $Queries[]='@taglist ( '.implode(' | ', $TagList).' ) '.implode(' ', $TagListEx); - } else { - $Queries[]='@taglist ( '.implode(' | ', $TagList).' )'; - } -} elseif(!empty($TagList)) { - $Queries[]='@taglist '.implode(' ', array_merge($TagList,$TagListEx)); +if (isset($_GET['group_results']) && $_GET['group_results']) { + $_GET['group_results'] = 1; + $GroupResults = true; + $SortOrders = array( + // 'url attr' => [global order, order within group] + 'year' => array('year', 'year'), + 'time' => array('id', 'id'), + 'size' => array('maxsize', 'size'), + 'seeders' => array('sumseeders', 'seeders'), + 'leechers' => array('sumleechers', 'leechers'), + 'snatched' => array('sumsnatched', 'snatched'), + 'random' => false); + $AggregateExp = array( + 'maxsize' => 'MAX(size) AS maxsize', + 'sumseeders' => 'SUM(seeders) AS sumseeders', + 'sumleechers' => 'SUM(leechers) AS sumleechers', + 'sumsnatched' => 'SUM(snatched) AS sumsnatched'); } else { - $_GET['tags_type'] = '1'; + $SortOrders = array( + 'year' => 'year', + 'time' => 'id', + 'size' => 'size', + 'seeders' => 'seeders', + 'leechers' => 'leechers', + 'snatched' => 'snatched', + 'random' => false); } -foreach(array('artistname','groupname', 'recordlabel', 'cataloguenumber', - 'remastertitle', 'remasteryear', 'remasterrecordlabel', 'remastercataloguenumber', - 'filelist', 'format', 'media') as $Search) { - if(!empty($_GET[$Search])) { - $_GET[$Search] = str_replace(array('%'), '', $_GET[$Search]); - if($Search == 'filelist') { - $Queries[]='@filelist "'.$SS->escape_string($_GET['filelist']).'"~20'; - } else { - $Words = explode(' ', $_GET[$Search]); - foreach($Words as $Key => &$Word) { - if($Word[0] == '!' && strlen($Word) >= 3 && count($Words) >= 2) { - if(strpos($Word,'!',1) === false) { - $Word = '!'.$SS->escape_string(substr($Word,1)); - } else { - $Word = $SS->escape_string($Word); - } - } elseif(strlen($Word) >= 2) { - $Word = $SS->escape_string($Word); - } else { - unset($Words[$Key]); - } - } - $Words = trim(implode(' ',$Words)); - if(!empty($Words)) { - $Queries[]="@$Search ".$Words; - } - } - } -} - -if(!empty($_GET['year'])) { - $Years = explode('-', $_GET['year']); - if(is_number($Years[0]) || (empty($Years[0]) && !empty($Years[1]) && is_number($Years[1]))) { - if(count($Years) == 1) { - $SS->set_filter('year', array((int)$Years[0])); - } else { - if(empty($Years[1]) || !is_number($Years[1])) { - $Years[1] = PHP_INT_MAX; - } elseif($Years[0] > $Years[1]) { - $Years = array_reverse($Years); - } - $SS->set_filter_range('year', (int)$Years[0], (int)$Years[1]); - } - } -} -if(!empty($_GET['encoding'])) { - $Queries[]='@encoding "'.$SS->escape_string($_GET['encoding']).'"'; // Note the quotes, for 24bit lossless -} - -if(isset($_GET['haslog']) && $_GET['haslog']!=='') { - if($_GET['haslog'] == 100) { - $SS->set_filter('logscore', array(100)); - } elseif ($_GET['haslog'] < 0) { - // Exclude torrents with log score equal to 100 - $SS->set_filter('logscore', array(100), true); - $SS->set_filter('haslog', array(1)); - } else { - $SS->set_filter('haslog', array(1)); - } -} - -foreach(array('hascue','scene','vanityhouse','freetorrent','releasetype') as $Search) { - if(isset($_GET[$Search]) && $_GET[$Search]!=='') { - if($Search == 'freetorrent') { - switch($_GET[$Search]) { - case 0: $SS->set_filter($Search, array(0)); break; - case 1: $SS->set_filter($Search, array(1)); break; - case 2: $SS->set_filter($Search, array(2)); break; - case 3: $SS->set_filter($Search, array(0), true); break; - } - } else { - $SS->set_filter($Search, array($_GET[$Search])); - } - } -} - - -if(!empty($_GET['filter_cat'])) { - $SS->set_filter('categoryid', array_keys($_GET['filter_cat'])); -} - - -if(!empty($_GET['page']) && is_number($_GET['page']) && $_GET['page'] > 0) { - if(check_perms('site_search_many')) { - $Page = $_GET['page']; - } else { - $Page = min(SPHINX_MAX_MATCHES/TORRENTS_PER_PAGE, $_GET['page']); - } - $SS->limit(($Page-1)*TORRENTS_PER_PAGE, TORRENTS_PER_PAGE); -} else { - $Page = 1; - $SS->limit(0, TORRENTS_PER_PAGE); -} - -if(!empty($_GET['order_way']) && $_GET['order_way'] == 'asc') { - $Way = SPH_SORT_ATTR_ASC; - $OrderWay = 'asc'; // For header links -} else { - $Way = SPH_SORT_ATTR_DESC; - $_GET['order_way'] = 'desc'; - $OrderWay = 'desc'; -} - -if(empty($_GET['order_by']) || !in_array($_GET['order_by'], array('year','time','size','seeders','leechers','snatched','random'))) { +if (empty($_GET['order_by']) || !isset($SortOrders[$_GET['order_by']])) { $_GET['order_by'] = 'time'; $OrderBy = 'time'; // For header links -} elseif($_GET['order_by'] == 'random') { - $OrderBy = '@random'; - $Way = SPH_SORT_EXTENDED; - $SS->limit(0, TORRENTS_PER_PAGE); } else { $OrderBy = $_GET['order_by']; } -$SS->SetSortMode($Way, $OrderBy); - - -if(count($Queries)>0) { - $Query = implode(' ',$Queries); +if(!empty($_GET['order_way']) && $_GET['order_way'] == 'asc') { + $OrderWay = 'asc'; } else { - $Query=''; - if(empty($SS->Filters)) { - $SS->set_filter('size', array(0), true); + $_GET['order_way'] = 'desc'; + $OrderWay = 'desc'; +} + +/** End default parameters and validation **/ + +/** Start preparation of property arrays **/ +array_pop($Bitrates); // remove 'other' +$SearchBitrates = array_merge($Bitrates, array('v0','v1','v2','24bit')); + +foreach ($SearchBitrates as $ID=>$Val) { + $SearchBitrates[$ID] = strtolower($Val); +} + +foreach ($Formats as $ID => $Val) { + $SearchFormats[$ID] = strtolower($Val); +} +/** End preparation of property arrays **/ + +/** Start query preparation **/ +$SphQL = new SphinxQL_Query(); +$SphQLTor = new SphinxQL_Query(); + +if ($OrderBy == 'random') { + $SphQL->select('id, groupid, categoryid') + ->order_by('RAND()', ''); + $Random = true; +} else if ($GroupResults) { + $OrderProperties = $SortOrders[$OrderBy]; + $SphQL->select('groupid, categoryid' . (isset($AggregateExp[$OrderProperties[0]]) ? ', '.$AggregateExp[$OrderProperties[0]] : '')) + ->group_by('groupid') + ->order_by($OrderProperties[0], $OrderWay) + ->order_group_by($OrderProperties[1], $OrderWay); + +} else { + $SphQL->select('id, groupid, categoryid') + ->order_by($SortOrders[$OrderBy], $OrderWay); +} +$SphQL->from('torrents, delta'); +$SphQLTor->select('id, groupid')->from('torrents, delta'); +/** End query preparation **/ + +/** Start building search query **/ +$Filtered = false; +$EnableNegation = false; // Sphinx needs at least one positive search condition to support the NOT operator + +// Filelist searches makes use of the proximity operator to ensure that all keywords match the same file +if (!empty($_GET['filelist'])) { + $SearchString = trim($_GET['filelist']); + if ($SearchString != '') { + $SearchString = '"'.SphinxQL::escape_string($_GET['filelist']).'"~20'; + $SphQL->where_match($SearchString, 'filelist', false); + $SphQLTor->where_match($SearchString, 'filelist', false); + $EnableNegation = true; + $Filtered = true; } } -$SS->set_index(SPHINX_INDEX.' delta'); -$Results = $SS->search($Query, '', 0, array(), '', ''); -if(check_perms('site_search_many')) { - $TorrentCount = $SS->TotalResults; -} else { - $TorrentCount = min($SS->TotalResults, SPHINX_MAX_MATCHES); -} - -// These ones were not found in the cache, run SQL -if(!empty($Results['notfound'])) { - $SQLResults = Torrents::get_groups($Results['notfound']); - - if(is_array($SQLResults['notfound'])) { // Something wasn't found in the db, remove it from results - reset($SQLResults['notfound']); - foreach($SQLResults['notfound'] as $ID) { - unset($SQLResults['matches'][$ID]); - unset($Results['matches'][$ID]); +// Collect all entered search terms to find out whether to enable the NOT operator +$GroupFields = array('artistname','groupname', 'recordlabel', 'cataloguenumber', 'taglist'); +$TorrentFields = array('remastertitle', 'remasteryear', 'remasterrecordlabel', 'remastercataloguenumber', 'encoding', 'format', 'media'); +$SearchWords = array(); +foreach (array('artistname', 'groupname', 'recordlabel', 'cataloguenumber', + 'taglist', 'remastertitle', 'remasteryear', 'remasterrecordlabel', + 'remastercataloguenumber', 'encoding', 'format', 'media') as $Search) { + if (!empty($_GET[$Search])) { + $SearchString = trim($_GET[$Search]); + if ($SearchString != '') { + $SearchWords[$Search] = array('include' => array(), 'exclude' => array()); + if ($Search == 'taglist') { + $SearchString = strtr($SearchString, '.', '_'); + $Words = explode(',', $SearchString); + } else { + $Words = explode(' ', $SearchString); + } + foreach ($Words as $Word) { + $Word = trim($Word); + if ($Word[0] == '!' && strlen($Word) >= 2) { + if (strpos($Word,'!',1) === false) { + $SearchWords[$Search]['exclude'][] = $Word; + } else { + $SearchWords[$Search]['include'][] = $Word; + $EnableNegation = true; + } + } elseif ($Word != '') { + $SearchWords[$Search]['include'][] = $Word; + $EnableNegation = true; + } + } } } - - // Merge SQL results with sphinx/memcached results - foreach($SQLResults['matches'] as $ID=>$SQLResult) { - $Results['matches'][$ID] = array_merge($Results['matches'][$ID], $SQLResult); - ksort($Results['matches'][$ID]); +} + +//Simple search +if (!empty($_GET['searchstr'])) { + $SearchString = trim($_GET['searchstr']); + $Words = explode(' ',strtolower($SearchString)); + if (!empty($Words)) { + $FilterBitrates = $FilterFormats = array(); + $BasicSearch = array('include' => array(), 'exclude' => array()); + foreach ($Words as $Word) { + $Word = trim($Word); + if ($Word[0] == '!' && strlen($Word) >= 2) { + if ($Word == '!100%') { + $_GET['haslog'] = '-1'; + } elseif (strpos($Word,'!',1) === false) { + $BasicSearch['exclude'][] = $Word; + } else { + $BasicSearch['include'][] = $Word; + $EnableNegation = true; + } + } elseif (in_array($Word, $SearchBitrates)) { + $FilterBitrates[] = $Word; + $EnableNegation = true; + } elseif (in_array($Word, $SearchFormats)) { + $FilterFormats[] = $Word; + $EnableNegation = true; + } elseif ($Word == '100%') { + $_GET['haslog'] = '100'; + } elseif ($Word != '') { + $BasicSearch['include'][] = $Word; + $EnableNegation = true; + } + } + if (!$EnableNegation && !empty($BasicSearch['exclude'])) { + $BasicSearch['include'] = array_merge($BasicSearch['include'], $BasicSearch['exclude']); + unset($BasicSearch['exclude']); + } + $QueryParts = array(); + foreach ($BasicSearch['include'] as $Word) { + $QueryParts[] = SphinxQL::escape_string($Word); + } + if (!empty($BasicSearch['exclude'])) { + foreach ($BasicSearch['exclude'] as $Word) { + $QueryParts[] = '!'.SphinxQL::escape_string(substr($Word,1)); + } + } + if (!empty($FilterBitrates)) { + $SearchString = implode(' ', $FilterBitrates); + $SphQL->where_match($SearchString, 'encoding', false); + $SphQLTor->where_match($SearchString, 'encoding', false); + $Filtered = true; + } + if (!empty($FilterFormats)) { + $SearchString = implode(' ', $FilterFormats); + $SphQL->where_match($SearchString, 'format', false); + $SphQLTor->where_match($SearchString, 'format', false); + $Filtered = true; + } + if (!empty($QueryParts)) { + $SearchString = implode(' ', $QueryParts); + $SphQL->where_match($SearchString, '(groupname,artistname,yearfulltext)', false); + $SphQLTor->where_match($SearchString, '(groupname,artistname,yearfulltext)', false); + $Filtered = true; + } } } -$Results = $Results['matches']; +// Tag list +if (!empty($SearchWords['taglist'])) { + $Tags = $SearchWords['taglist']; + if (!$EnableNegation && !empty($Tags['exclude'])) { + $Tags['include'] = array_merge($Tags['include'], $Tags['exclude']); + unset($Tags['exclude']); + } + foreach ($Tags['include'] as &$Tag) { + $Tag = SphinxQL::escape_string($Tag); + } + if (!empty($Tags['exclude'])) { + foreach ($Tags['exclude'] as &$Tag) { + $Tag = '!'.SphinxQL::escape_string(substr($Tag,1)); + } + } -$AdvancedSearch = false; -$Action = 'action=basic'; -if(((!empty($_GET['action']) && strtolower($_GET['action'])=="advanced") || (!empty($LoggedUser['SearchType']) && ((!empty($_GET['action']) && strtolower($_GET['action'])!="basic") || empty($_GET['action'])))) && check_perms('site_advanced_search')) { - $AdvancedSearch = true; - $Action = 'action=advanced'; + $QueryParts = array(); + // 'All' tags + if (!isset($_GET['tags_type']) || $_GET['tags_type'] == 1) { + $_GET['tags_type'] = '1'; + $Tags = array_merge($Tags['include'], $Tags['exclude']); + if (!empty($Tags)) { + $QueryParts[] = implode(' ', $Tags); + } + } + // 'Any' tags + else { + $_GET['tags_type'] = '0'; + if (!empty($Tags['include'])) { + $QueryParts[] = '( '.implode(' | ', $Tags['include']).' )'; + } + if (!empty($Tags['exclude'])) { + $QueryParts[] = implode(' ', $Tags['exclude']); + } + } + if (!empty($QueryParts)) { + $SphQL->where_match(implode(' ', $QueryParts), 'taglist', false); + $Filtered = true; + } + unset($SearchWords['taglist']); +} +elseif (!isset($_GET['tags_type'])) { + $_GET['tags_type'] = '1'; } +foreach ($SearchWords as $Search => $Words) { + $QueryParts = array(); + if (!$EnableNegation && !empty($Words['exclude'])) { + $Words['include'] = array_merge($Words['include'], $Words['exclude']); + unset($Words['exclude']); + } + foreach ($Words['include'] as $Word) { + $QueryParts[] = SphinxQL::escape_string($Word); + } + if (!empty($Words['exclude'])) { + foreach ($Words['exclude'] as $Word) { + $QueryParts[] = '!'.SphinxQL::escape_string(substr($Word,1)); + } + } + if (!empty($QueryParts)) { + $SearchString = implode(' ', $QueryParts); + $SphQL->where_match($SearchString, $Search, false); + $SphQLTor->where_match($SearchString, $Search, false); + $Filtered = true; + } +} -if(count($Results)==0) { +if (!empty($_GET['year'])) { + $Years = explode('-', $_GET['year']); + if (is_number($Years[0]) || (empty($Years[0]) && !empty($Years[1]) && is_number($Years[1]))) { + if (count($Years) == 1) { + $SphQL->where('year', (int)$Years[0]); + $SphQLTor->where('year', (int)$Years[0]); + } else { + if (empty($Years[1]) || !is_number($Years[1])) { + $Years[1] = PHP_INT_MAX; + } elseif ($Years[0] > $Years[1]) { + $Years = array_reverse($Years); + } + $SphQL->where_between('year', array((int)$Years[0], (int)$Years[1])); + $SphQLTor->where_between('year', array((int)$Years[0], (int)$Years[1])); + } + $Filtered = true; + } +} + +if (isset($_GET['haslog']) && $_GET['haslog']!=='') { + if ($_GET['haslog'] == 100) { + $SphQL->where('logscore', 100); + $SphQLTor->where('logscore', 100); + $Filtered = true; + } elseif ($_GET['haslog'] < 0) { + // Exclude torrents with log score equal to 100 + $SphQL->where('logscore', 100, true); + $SphQL->where('haslog', 1); + $SphQLTor->where('logscore', 100, true); + $SphQLTor->where('haslog', 1); + $Filtered = true; + } elseif ($_GET['haslog'] == 0) { + $SphQL->where('haslog', 0); + $SphQLTor->where('haslog', 0); + } else { + $SphQL->where('haslog', 1); + $SphQLTor->where('haslog', 1); + $Filtered = true; + } +} +foreach (array('hascue','scene','vanityhouse','releasetype') as $Search) { + if (isset($_GET[$Search]) && $_GET[$Search] !== '') { + $SphQL->where($Search, $_GET[$Search]); + // Release type is group specific + if ($Search != 'releasetype') { + $SphQLTor->where($Search, $_GET[$Search]); + } + if ($_GET[$Search] !== 0) { + // Hack! Deleted torrents may show up if we set to true unconditionally. Hope no one notices + $Filtered = true; + } + } +} + +if (!empty($_GET['freetorrent'])) { + switch ($_GET['freetorrent']) { + case 0: // Only normal freeleech + $SphQL->where('freetorrent', 0); + $SphQLTor->where('freetorrent', 0); + $Filtered = true; + break; + case 1: // Only free leech + $SphQL->where('freetorrent', 1); + $SphQLTor->where('freetorrent', 1); + $Filtered = true; + break; + case 2: // Only neutral leech + $SphQL->where('freetorrent', 2); + $SphQLTor->where('freetorrent', 2); + $Filtered = true; + break; + case 3: // Free or neutral leech + $SphQL->where('freetorrent', 0, true); + $SphQLTor->where('freetorrent', 0, true); + $Filtered = true; + break; + } +} + +if (!empty($_GET['filter_cat'])) { + $SphQL->where('categoryid', array_keys($_GET['filter_cat'])); + $Filtered = true; +} + +if (!$Filtered) { + $SphQL->where('size', 0, true); +} +/** End building search query **/ + +/** Run search query and collect results **/ +if (isset($Random) && $GroupResults) { + // ORDER BY RAND() can't be used together with GROUP BY, so we need some special tactics + $Page = 1; + $SphQL->limit(0, 5*TORRENTS_PER_PAGE, 5*TORRENTS_PER_PAGE); + $SphQLResult = $SphQL->query(); + $TotalCount = $SphQLResult->get_meta('total_found'); + $Results = $SphQLResult->to_array('groupid'); + $GroupIDs = array_keys($Results); + $GroupCount = count($GroupIDs); + while ($SphQLResult->get_meta('total') < $TotalCount && $GroupCount < TORRENTS_PER_PAGE) { + // Make sure we get TORRENTS_PER_PAGE results, or all of them if there are less than TORRENTS_PER_PAGE hits + $SphQL->where('groupid', $GroupIDs, true); + $SphQLResult = $SphQL->query(); + if (!$SphQLResult->get_meta('total')) { + break; + } + $Results += $SphQLResult->to_array('groupid'); + $GroupIDs = array_keys($Results); + $GroupCount = count($GroupIDs); + } + if ($GroupCount > TORRENTS_PER_PAGE) { + $Results = array_slice($Results, 0, TORRENTS_PER_PAGE, true); + } + $GroupIDs = array_keys($Results); + $TorrentCount = count($Results); +} else { + if (!empty($_GET['page']) && is_number($_GET['page']) && $_GET['page'] > 0) { + if (check_perms('site_search_many')) { + $Page = $_GET['page']; + } else { + $Page = min(SPHINX_MAX_MATCHES/TORRENTS_PER_PAGE, $_GET['page']); + } + $Offset = ($Page - 1) * TORRENTS_PER_PAGE; + $SphQL->limit($Offset, TORRENTS_PER_PAGE, $Offset + TORRENTS_PER_PAGE); + } else { + $Page = 1; + $SphQL->limit(0, TORRENTS_PER_PAGE, TORRENTS_PER_PAGE); + } + $SphQLResult = $SphQL->query(); + $TorrentCount = $SphQLResult->get_meta('total_found'); + if ($GroupResults) { + $Results = $SphQLResult->to_array('groupid'); + $GroupIDs = array_keys($Results); + } else { + $Results = $SphQLResult->to_array('id'); + $GroupIDs = $SphQLResult->collect('groupid'); + } +} + +if (!check_perms('site_search_many') && $TorrentCount > SPHINX_MAX_MATCHES) { + $TorrentCount = SPHINX_MAX_MATCHES; +} + +if ($TorrentCount) { + $Groups = Torrents::get_groups($GroupIDs); + $Groups = $Groups['matches']; + + if (!empty($Groups) && $GroupResults) { + $TorrentIDs = array(); + foreach ($Groups as $Group) { + if (!empty($Group['Torrents'])) { + $TorrentIDs = array_merge($TorrentIDs, array_keys($Group['Torrents'])); + } + } + + // Get a list of all torrent ids that match the search query + $SphQLTor->where('id', $TorrentIDs)->limit(0, count($TorrentIDs), count($TorrentIDs)); + $SphQLResultTor = $SphQLTor->query(); + $TorrentIDs = array_fill_keys($SphQLResultTor->collect('id'), true); + } +} +/** End run search query and collect results **/ + +if($TorrentCount == 0) { $DB->query("SELECT tags.Name, @@ -345,37 +529,62 @@ function header_link($SortKey,$DefaultWay="desc") { $Bookmarks = all_bookmarks('torrent'); $JsonGroups = array(); -foreach($Results as $GroupID=>$Data) { - list($Artists, $GroupCatalogueNumber, $ExtendedArtists, $GroupID2, $GroupName, $GroupRecordLabel, $ReleaseType, $TagList, $Torrents, $GroupVanityHouse, $GroupYear, $CategoryID, $FreeTorrent, $HasCue, $HasLog, $TotalLeechers, $LogScore, $ReleaseType, $ReleaseType, $TotalSeeders, $MaxSize, $TotalSnatched, $GroupTime) = array_values($Data); - - $TagList = explode(' ',str_replace('_','.',$TagList)); - $JsonArtists = array(); - if(count($Torrents)>1 || $CategoryID==1) { - // These torrents are in a group - if (!empty($ExtendedArtists[1]) || !empty($ExtendedArtists[4]) || !empty($ExtendedArtists[5]) || !empty($ExtendedArtists[6])) { - unset($ExtendedArtists[2]); - unset($ExtendedArtists[3]); - $DisplayName = Artists::display_artists($ExtendedArtists, false, false, true); - foreach ($ExtendedArtists[1] as $Artist) { - $JsonArtists[] = array( - 'id' => (int) $Artist['id'], - 'name' => $Artist['name'], - 'aliasid' => (int) $Artist['id'] - ); - } - } elseif(!empty($Artists)) { - $DisplayName = Artists::display_artists(array(1=>$Artists), false, false, true); - foreach ($Artists as $Artist) { - $JsonArtists[] = array( - 'id' => (int) $Artist['id'], - 'name' => $Artist['name'], - 'aliasid' => (int) $Artist['id'] - ); - } - } else { - $DisplayName=''; +foreach ($Results as $Result) { + $GroupID = $Result['groupid']; + $GroupInfo = $Groups[$GroupID]; + if (empty($GroupInfo['Torrents'])) { + continue; + } + $CategoryID = $Result['categoryid']; + $GroupYear = $GroupInfo['Year']; + $ExtendedArtists = $GroupInfo['ExtendedArtists']; + $GroupCatalogueNumber = $GroupInfo['CatalogueNumber']; + $GroupName = $GroupInfo['Name']; + $GroupRecordLabel = $GroupInfo['RecordLabel']; + $ReleaseType = $GroupInfo['ReleaseType']; + if ($GroupResults) { + $Torrents = $GroupInfo['Torrents']; + $GroupTime = $MaxSize = $TotalLeechers = $TotalSeeders = $TotalSnatched = 0; + foreach ($Torrents as $T) { + $GroupTime = max($GroupTime, strtotime($T['Time'])); + if ($T['Size'] > $MaxSize) { + $MaxSize = $T['Size']; + } + $TotalLeechers += $T['Leechers']; + $TotalSeeders += $T['Seeders']; + $TotalSnatched += $T['Snatched']; } - + } else { + $Torrents = array($Result['id'] => $GroupInfo['Torrents'][$Result['id']]); + } + + $TagList = explode(' ',str_replace('_','.',$GroupInfo['TagList'])); + $JsonArtists = array(); + if (!empty($ExtendedArtists[1]) || !empty($ExtendedArtists[4]) || !empty($ExtendedArtists[5]) || !empty($ExtendedArtists[6])) { + unset($ExtendedArtists[2]); + unset($ExtendedArtists[3]); + $DisplayName = Artists::display_artists($ExtendedArtists, false, false, true); + foreach ($ExtendedArtists[1] as $Artist) { + $JsonArtists[] = array( + 'id' => (int) $Artist['id'], + 'name' => $Artist['name'], + 'aliasid' => (int) $Artist['id'] + ); + } + } elseif(!empty($Artists)) { + $DisplayName = Artists::display_artists(array(1=>$Artists), false, false, true); + foreach ($Artists as $Artist) { + $JsonArtists[] = array( + 'id' => (int) $Artist['id'], + 'name' => $Artist['name'], + 'aliasid' => (int) $Artist['id'] + ); + } + } else { + $DisplayName=''; + } + if ($GroupResults && (count($Torrents)>1 || isset($GroupedCategories[$CategoryID-1]))) { + // These torrents are in a group $LastRemasterYear = '-'; $LastRemasterTitle = ''; $LastRemasterRecordLabel = ''; @@ -390,92 +599,7 @@ function header_link($SortKey,$DefaultWay="desc") { // All of the individual torrents in the group // If they're using the advanced search and have chosen enabled grouping, we just skip the torrents that don't check out - - $Filter = false; - $Pass = false; - - if(!empty($FilterBitrates)) { - $Filter = true; - $Bitrate = strtolower(array_shift(explode(' ',$Data['Encoding']))); - if(in_array($Bitrate, $FilterBitrates)) { - $Pass = true; - } - } - if(!empty($FilterFormats)) { - $Filter = true; - if(in_array(strtolower($Data['Format']), $FilterFormats)) { - $Pass = true; - } - } - - if(!empty($_GET['encoding'])) { - $Filter = true; - if($Data['Encoding']==$_GET['encoding']) { - $Pass = true; - } - } - if(!empty($_GET['format'])) { - $Filter = true; - if($Data['Format']==$_GET['format']) { - $Pass = true; - } - } - - - if(!empty($_GET['media'])) { - $Filter = true; - if($Data['Media']==$_GET['media']) { - $Pass = true; - } - } - if(isset($_GET['haslog']) && $_GET['haslog']!=='') { - $Filter = true; - if($_GET['haslog'] == '100' && $Data['LogScore']==100) { - $Pass = true; - } elseif (($_GET['haslog'] == '-1') && ($Data['LogScore'] < 100) && ($Data['HasLog'] == '1')) { - $Pass = true; - } elseif(($_GET['haslog'] == '1' || $_GET['haslog'] == '0') && (int)$Data['HasLog']==$_GET['haslog']) { - $Pass = true; - } - } - if(isset($_GET['hascue']) && $_GET['hascue']!=='') { - $Filter = true; - if((int)$Data['HasCue']==$_GET['hascue']) { - $Pass = true; - } - } - if(isset($_GET['scene']) && $_GET['scene']!=='') { - $Filter = true; - if((int)$Data['Scene']==$_GET['scene']) { - $Pass = true; - } - } - if(isset($_GET['vanityhouse']) && $_GET['vanityhouse']!=='') { - $Filter = true; - if((int)$Data['VanityHouse']==$_GET['vanityhouse']) { - $Pass = true; - } - } - if(isset($_GET['freetorrent']) && $_GET['freetorrent']!=='') { - $Filter = true; - if((int)$Data['FreeTorrent'] & $_GET['freetorrent'] || (int)$Data['FreeTorrent'] == $_GET['freetorrent']) { - $Pass = true; - } - } - if(!empty($_GET['remastertitle'])) { - $Filter = true; - $Continue = false; - $RemasterParts = explode(' ', $_GET['remastertitle']); - foreach($RemasterParts as $RemasterPart) { - if(stripos($Data['RemasterTitle'],$RemasterPart) === false) { - $Continue = true; - } - } - if(!$Continue) { - $Pass = true; - } - } - if($Filter && !$Pass) { + if (!isset($TorrentIDs[$TorrentID])) { continue; } @@ -483,24 +607,29 @@ function header_link($SortKey,$DefaultWay="desc") { $FirstUnknown = !isset($FirstUnknown); } - if($CategoryID == 1 && ($Data['RemasterTitle'] != $LastRemasterTitle || $Data['RemasterYear'] != $LastRemasterYear || - $Data['RemasterRecordLabel'] != $LastRemasterRecordLabel || $Data['RemasterCatalogueNumber'] != $LastRemasterCatalogueNumber) || $FirstUnknown || $Data['Media'] != $LastMedia) { + if (isset($GroupedCategories[$CategoryID-1]) + && ($Data['RemasterTitle'] != $LastRemasterTitle + || $Data['RemasterYear'] != $LastRemasterYear + || $Data['RemasterRecordLabel'] != $LastRemasterRecordLabel + || $Data['RemasterCatalogueNumber'] != $LastRemasterCatalogueNumber) + || $FirstUnknown + || $Data['Media'] != $LastMedia) { $EditionID++; - if($Data['Remastered'] && $Data['RemasterYear'] != 0) { + if ($Data['Remastered'] && $Data['RemasterYear'] != 0) { $RemasterName = $Data['RemasterYear']; $AddExtra = " - "; - if($Data['RemasterRecordLabel']) { $RemasterName .= $AddExtra.display_str($Data['RemasterRecordLabel']); $AddExtra=' / '; } - if($Data['RemasterCatalogueNumber']) { $RemasterName .= $AddExtra.display_str($Data['RemasterCatalogueNumber']); $AddExtra=' / '; } - if($Data['RemasterTitle']) { $RemasterName .= $AddExtra.display_str($Data['RemasterTitle']); $AddExtra=' / '; } + if ($Data['RemasterRecordLabel']) { $RemasterName .= $AddExtra.display_str($Data['RemasterRecordLabel']); $AddExtra=' / '; } + if ($Data['RemasterCatalogueNumber']) { $RemasterName .= $AddExtra.display_str($Data['RemasterCatalogueNumber']); $AddExtra=' / '; } + if ($Data['RemasterTitle']) { $RemasterName .= $AddExtra.display_str($Data['RemasterTitle']); $AddExtra=' / '; } $RemasterName .= $AddExtra.display_str($Data['Media']); } else { $AddExtra = " / "; if (!$Data['Remastered']) { $MasterName = "Original Release"; - if($GroupRecordLabel) { $MasterName .= $AddExtra.$GroupRecordLabel; $AddExtra=' / '; } - if($GroupCatalogueNumber) { $MasterName .= $AddExtra.$GroupCatalogueNumber; $AddExtra=' / '; } + if ($GroupRecordLabel) { $MasterName .= $AddExtra.$GroupRecordLabel; $AddExtra=' / '; } + if ($GroupCatalogueNumber) { $MasterName .= $AddExtra.$GroupCatalogueNumber; $AddExtra=' / '; } } else { $MasterName = "Unknown Release(s)"; } @@ -516,7 +645,7 @@ function header_link($SortKey,$DefaultWay="desc") { $JsonTorrents[] = array( 'torrentId' => (int) $TorrentID, 'editionId' => (int) $EditionID, - 'artists' => $JsonArtists, + 'artists' => $JsonArtists, 'remastered' => $Data['Remastered'] == '1', 'remasterYear' => (int) $Data['RemasterYear'], 'remasterCatalogueNumber' => $Data['RemasterCatalogueNumber'], @@ -552,7 +681,7 @@ function header_link($SortKey,$DefaultWay="desc") { 'vanityHouse' => $GroupVanityHouse == '1', 'groupYear' => (int) $GroupYear, 'releaseType' => $ReleaseTypes[$ReleaseType], - 'groupTime' => $GroupTime, + 'groupTime' => (string) $GroupTime, 'maxSize' => (int) $MaxSize, 'totalSnatched' => (int) $TotalSnatched, 'totalSeeders' => (int) $TotalSeeders, diff --git a/sections/ajax/takevote.php b/sections/ajax/takevote.php index e6b4ccdf..81042302 100644 --- a/sections/ajax/takevote.php +++ b/sections/ajax/takevote.php @@ -8,24 +8,10 @@ } // What groups has this guy voted? -$UserVotes = $Cache->get_value('voted_albums_'.$LoggedUser['ID'], true); -if ($UserVotes === FALSE) { - $DB->query('SELECT GroupID, Type FROM users_votes WHERE UserID='.$LoggedUser['ID']); - $UserVotes = $DB->to_array('GroupID', MYSQL_ASSOC, false); - $Cache->cache_value('voted_albums_'.$LoggedUser['ID'], $UserVotes); -} +$UserVotes = Votes::get_user_votes($LoggedUser['ID']); // What are the votes for this group? -$GroupVotes = $Cache->get_value('votes_'.$GroupID, true); -if ($GroupVotes === FALSE) { - $DB->query("SELECT Ups AS Ups, Total AS Total FROM torrents_votes WHERE GroupID=$GroupID"); - if ($DB->record_count() == 0) { - $GroupVotes = array('Ups'=>0, 'Total'=>0); - } else { - $GroupVotes = $DB->next_record(MYSQLI_ASSOC, false); - } - $Cache->cache_value('votes_'.$GroupID, $GroupVotes); -} +$GroupVotes = Votes::get_group_votes($GroupID); $UserID = $LoggedUser['ID']; if ($_REQUEST['do'] == 'vote') { diff --git a/sections/artist/artist.php b/sections/artist/artist.php index 62ec3e5d..b7a079c7 100644 --- a/sections/artist/artist.php +++ b/sections/artist/artist.php @@ -17,6 +17,8 @@ function compare($X, $Y){ include(SERVER_ROOT.'/classes/class_image_tools.php'); +$UserVotes = Votes::get_user_votes($LoggedUser['ID']); + $ArtistID = $_GET['id']; if(!is_number($ArtistID)) { error(0); } @@ -386,7 +388,7 @@ function compare($X, $Y){
- + @@ -473,7 +475,7 @@ function compare($X, $Y){ //----------------- End building list and getting stats -View::show_header($Name, 'browse,requests,bbcode,comments'); +View::show_header($Name, 'browse,requests,bbcode,comments,voting'); ?>
diff --git a/sections/collages/collage.php b/sections/collages/collage.php index df3737c2..4c181304 100644 --- a/sections/collages/collage.php +++ b/sections/collages/collage.php @@ -13,6 +13,8 @@ function compare($X, $Y){ $Text = new TEXT; +$UserVotes = Votes::get_user_votes($LoggedUser['ID']); + $CollageID = $_GET['id']; if(!is_number($CollageID)) { error(0); } @@ -176,7 +178,7 @@ function compare($X, $Y){
- + @@ -285,7 +287,7 @@ function compare($X, $Y){ | RP ] - + @@ -354,7 +356,7 @@ function compare($X, $Y){ $CollagePages[] = $CollagePage; } -View::show_header($Name,'browse,collage,bbcode'); +View::show_header($Name,'browse,collage,bbcode,voting'); ?>
diff --git a/sections/forums/functions.php b/sections/forums/functions.php index 2cfae87f..34cad3c6 100644 --- a/sections/forums/functions.php +++ b/sections/forums/functions.php @@ -1,7 +1,7 @@ get_value('thread_'.$ThreadID.'_info')) { + if((!$ThreadInfo = $Cache->get_value('thread_'.$ThreadID.'_info')) || !isset($ThreadInfo['OP'])) { $DB->query("SELECT t.Title, t.ForumID, diff --git a/sections/top10/votes.php b/sections/top10/votes.php index fcfd6f13..feeb65fc 100644 --- a/sections/top10/votes.php +++ b/sections/top10/votes.php @@ -3,6 +3,8 @@ include(SERVER_ROOT.'/sections/torrents/ranking_funcs.php'); include(SERVER_ROOT.'/sections/bookmarks/functions.php'); +$UserVotes = Votes::get_user_votes($LoggedUser['ID']); + if(!empty($_GET['advanced']) && check_perms('site_advanced_top10')) { $Details = 'all'; $Limit = 25; @@ -84,7 +86,7 @@ } } -View::show_header('Top '.$Limit.' Voted Groups','browse'); +View::show_header('Top '.$Limit.' Voted Groups','browse,voting'); ?>
@@ -213,11 +215,11 @@
- + - [ Unbookmark ] + [ Unbookmark ] - [ Bookmark ] + [ Bookmark ] @@ -334,7 +336,7 @@ ] - + diff --git a/sections/torrents/browse2.php b/sections/torrents/browse2.php index bb607c14..fce3c796 100644 --- a/sections/torrents/browse2.php +++ b/sections/torrents/browse2.php @@ -158,10 +158,8 @@ function header_link($SortKey,$DefaultWay="desc") { /** End preparation of property arrays **/ /** Start query preparation **/ -$SphQLHost = '192.168.5.6'; -$SphQLPort = '9307'; -$SphQL = new SphinxQL_Query($SphQLHost, $SphQLPort); -$SphQLTor = new SphinxQL_Query($SphQLHost, $SphQLPort); +$SphQL = new SphinxQL_Query(); +$SphQLTor = new SphinxQL_Query(); if ($OrderBy == 'random') { $SphQL->select('id, groupid, categoryid') @@ -543,7 +541,7 @@ function header_link($SortKey,$DefaultWay="desc") { ?>
-
+

Filter @@ -557,35 +555,35 @@ function header_link($SortKey,$DefaultWay="desc") { Artist Name: - + Album/Torrent Name: - + Record Label: - + Catalogue Number: - + Year: - + - [Click here to toggle searching for specific remaster information] + [Click here to toggle searching for specific remaster information] Edition Title: - + Edition Year: - + Edition Release Label: - + Edition Catalogue Number: - + File List: - + Rip Specifics: - + + + - - - - @@ -688,7 +686,7 @@ function header_link($SortKey,$DefaultWay="desc") { Search terms: - + @@ -698,7 +696,7 @@ function header_link($SortKey,$DefaultWay="desc") { Tags (comma-separated): - +   />   /> @@ -706,8 +704,8 @@ function header_link($SortKey,$DefaultWay="desc") { Order by: - - @@ -716,18 +714,22 @@ function header_link($SortKey,$DefaultWay="desc") { - - - /> + + + + + /> + - +
-
+
Results @@ -893,9 +895,7 @@ function header_link($SortKey,$DefaultWay="desc") { $Torrents = $GroupInfo['Torrents']; $GroupTime = $MaxSize = $TotalLeechers = $TotalSeeders = $TotalSnatched = 0; foreach ($Torrents as $T) { - if ($T['Time'] > $GroupTime) { - $GroupTime = $T['Time']; - } + $GroupTime = max($GroupTime, strtotime($T['Time'])); if ($T['Size'] > $MaxSize) { $MaxSize = $T['Size']; } @@ -948,9 +948,9 @@ function header_link($SortKey,$DefaultWay="desc") { - Unbookmark + Unbookmark - Bookmark + Bookmark
diff --git a/sections/torrents/details.php b/sections/torrents/details.php index db4c429a..74b48947 100644 --- a/sections/torrents/details.php +++ b/sections/torrents/details.php @@ -1,8 +1,8 @@
@@ -587,6 +587,7 @@ function filelist($Str) { + diff --git a/sections/torrents/notify.php b/sections/torrents/notify.php index 4834ddea..a8829e2c 100644 --- a/sections/torrents/notify.php +++ b/sections/torrents/notify.php @@ -117,6 +117,10 @@ function header_link($SortKey, $DefaultWay = "desc") { $Filters = $DB->to_array('ID', MYSQLI_ASSOC, array('Artists')); foreach ($Filters as &$Filter) { $Filter['Artists'] = explode('|', trim($Filter['Artists'], '|')); + foreach ($Filter['Artists'] as &$FilterArtist) { + $FilterArtist = mb_strtolower($FilterArtist, 'UTF-8'); + } + $Filter['Artists'] = array_flip($Filter['Artists']); } unset($Filter); @@ -215,10 +219,8 @@ function header_link($SortKey, $DefaultWay = "desc") { $MatchingArtists = array(); foreach ($GroupInfo['ExtendedArtists'] as $GroupArtists) { foreach ($GroupArtists as $GroupArtist) { - foreach ($Filters[$FilterID]['Artists'] as $FilterArtist) { - if (mb_strtolower($FilterArtist, 'UTF-8') == mb_strtolower($GroupArtist['name'], 'UTF-8')) { - $MatchingArtists[] = $GroupArtist['name']; - } + if (isset($Filters[$FilterID]['Artists'][mb_strtolower($GroupArtist['name'], 'UTF-8')])) { + $MatchingArtists[] = $GroupArtist['name']; } } } diff --git a/sections/torrents/user.php b/sections/torrents/user.php index 628d95aa..1a24cc2a 100644 --- a/sections/torrents/user.php +++ b/sections/torrents/user.php @@ -2,6 +2,7 @@ $Orders = array('Time', 'Name', 'Seeders', 'Leechers', 'Snatched', 'Size'); $Ways = array('ASC'=>'Ascending', 'DESC'=>'Descending'); +$UserVotes = Votes::get_user_votes($LoggedUser['ID']); // The "order by x" links on columns headers function header_link($SortKey,$DefaultWay="DESC") { @@ -264,7 +265,7 @@ function header_link($SortKey,$DefaultWay="DESC") { $Action = display_str($_GET['type']); $User = Users::user_info($UserID); -View::show_header($User['Username'].'\'s '.$Action.' torrents'); +View::show_header($User['Username'].'\'s '.$Action.' torrents','voting'); $Pages=Format::get_pages($Page,$TorrentCount,TORRENTS_PER_PAGE); @@ -465,7 +466,7 @@ function header_link($SortKey,$DefaultWay="DESC") { [ DL | RP ] - +
diff --git a/sections/torrents/vote.php b/sections/torrents/vote.php index 6c85c899..6f95c444 100644 --- a/sections/torrents/vote.php +++ b/sections/torrents/vote.php @@ -1,21 +1,7 @@ get_value('voted_albums_'.$LoggedUser['ID']); -if ($UserVotes === FALSE) { - $DB->query('SELECT GroupID, Type FROM users_votes WHERE UserID='.$LoggedUser['ID']); - $UserVotes = $DB->to_array('GroupID', MYSQL_ASSOC, false); - $Cache->cache_value('voted_albums_'.$LoggedUser['ID'], $UserVotes); -} +$UserVotes = Votes::get_user_votes($LoggedUser['ID']); +$GroupVotes = Votes::get_group_votes($GroupID); -$GroupVotes = $Cache->get_value('votes_'.$GroupID); -if ($GroupVotes === FALSE) { - $DB->query("SELECT Ups AS Ups, Total AS Total FROM torrents_votes WHERE GroupID=$GroupID"); - if ($DB->record_count() == 0) { - $GroupVotes = array('Ups'=>0, 'Total'=>0); - } else { - $GroupVotes = $DB->next_record(MYSQLI_ASSOC, false); - } - $Cache->cache_value('votes_'.$GroupID, $GroupVotes); -} $TotalVotes = $GroupVotes['Total']; $UpVotes = $GroupVotes['Ups']; diff --git a/sections/user/edit.php b/sections/user/edit.php index f8ec4fb6..0f31f122 100644 --- a/sections/user/edit.php +++ b/sections/user/edit.php @@ -327,7 +327,14 @@ function checked($Checked) { Auto-save Text checked="checked" /> - + + + + + Voting links + + checked="checked" /> + diff --git a/sections/user/takeedit.php b/sections/user/takeedit.php index 8878af3b..3349b1f2 100644 --- a/sections/user/takeedit.php +++ b/sections/user/takeedit.php @@ -196,6 +196,7 @@ $Options['NotifyOnQuote'] = (!empty($_POST['notifyquotes']) ? 1 : 0); $Options['ShowSnatched'] = (!empty($_POST['showsnatched']) ? 1 : 0); $Options['DisableAutoSave'] = (!empty($_POST['disableautosave']) ? 1 : 0); +$Options['NoVoteLinks'] = (!empty($_POST['novotelinks']) ? 1 : 0); if(isset($LoggedUser['DisableFreeTorrentTop10'])) { diff --git a/sphinx.conf b/sphinx.conf index e202e6f8..018f1269 100644 --- a/sphinx.conf +++ b/sphinx.conf @@ -11,9 +11,8 @@ source connect { sql_db = gazelle } -source torrents : connect { - #By inheriting from connect, we keep all the connection info - +source torrents_base : connect { + sql_attr_uint = groupid sql_attr_uint = time sql_attr_uint = categoryid sql_attr_uint = releasetype @@ -29,73 +28,95 @@ source torrents : connect { sql_attr_bool = hascue sql_attr_uint = freetorrent - sql_query_pre = TRUNCATE TABLE sphinx_hash - sql_query_pre = SET group_concat_max_len = 10140 - sql_query_pre = SET @StartTime = NOW() - - sql_query_pre = INSERT INTO sphinx_hash ( \ - ID, GroupName, TagList, Year, RecordLabel, \ - CatalogueNumber, CategoryID, Time, \ - ReleaseType, Size, Snatched, \ - Seeders, Leechers, LogScore, \ - Scene, VanityHouse, HasLog, \ - HasCue, FreeTorrent, \ - Media, Format, Encoding, RemasterYear, RemasterTitle, \ - RemasterRecordLabel, RemasterCatalogueNumber, FileList ) \ - SELECT \ - g.ID AS ID, g.Name AS GroupName, g.TagList, g.Year, g.RecordLabel, \ - g.CatalogueNumber, g.CategoryID, UNIX_TIMESTAMP(g.Time) AS Time, \ - g.ReleaseType, MAX(CEIL(t.Size/1024)) AS Size, SUM(t.Snatched) AS Snatched, \ - SUM(t.Seeders) AS Seeders, SUM(t.Leechers) AS Leechers, MAX(t.LogScore) AS LogScore, \ - MAX(t.Scene) AS Scene, MAX(g.VanityHouse) AS VanityHouse, MAX(t.HasLog) AS HasLog, \ - MAX(t.HasCue) AS HasCue, BIT_OR(t.FreeTorrent-1) AS FreeTorrent, \ - GROUP_CONCAT(DISTINCT t.Media SEPARATOR ' ') AS Media, \ - GROUP_CONCAT(DISTINCT t.Format SEPARATOR ' ') AS Format, \ - GROUP_CONCAT(DISTINCT t.Encoding SEPARATOR ' ') AS Encoding, \ - GROUP_CONCAT(DISTINCT t.RemasterYear SEPARATOR ' ') AS RemasterYear, \ - GROUP_CONCAT(DISTINCT t.RemasterTitle SEPARATOR ' ') AS RemasterTitle, \ - GROUP_CONCAT(DISTINCT t.RemasterRecordLabel SEPARATOR ' ') AS RemasterRecordLabel, \ - GROUP_CONCAT(DISTINCT t.RemasterCatalogueNumber SEPARATOR ' ') AS RemasterCatalogueNumber, \ - GROUP_CONCAT(REPLACE(REPLACE(FileList, '|||', '\n '), '_', ' ') SEPARATOR '\n ') AS FileList \ - FROM torrents AS t \ - JOIN torrents_group AS g ON g.ID=t.GroupID \ - GROUP BY g.ID - - sql_query_pre = INSERT INTO sphinx_hash ( \ - ID, ArtistName ) \ - SELECT GroupID, GROUP_CONCAT(aa.Name separator ' ') \ - FROM torrents_artists AS ta \ - JOIN artists_alias AS aa ON aa.AliasID=ta.AliasID \ - JOIN torrents_group AS tg ON tg.ID=ta.GroupID \ - WHERE ta.Importance IN ('1', '4', '5', '6') AND Time<=@StartTime \ - GROUP BY tg.ID \ - ON DUPLICATE KEY UPDATE ArtistName=values(ArtistName) - - sql_query = SELECT ID, GroupName, ArtistName, TagList, Year, Year AS YearFullText, \ - RecordLabel, CatalogueNumber, CategoryID, Time, ReleaseType, \ - Size, Snatched, Seeders, Leechers, LogScore, Scene, \ - VanityHouse, HasLog, HasCue, FreeTorrent, Media, Format, \ - Encoding, RemasterYear, RemasterTitle, RemasterRecordLabel, \ - RemasterCatalogueNumber, FileList \ - FROM sphinx_hash - - sql_query_post = DELETE FROM sphinx_delta WHERE Time<=UNIX_TIMESTAMP(@StartTime) OR Time IS NULL - sql_query_info = SELECT ID, GroupName, ArtistName, TagList, Filelist FROM sphinx_hash WHERE ID = $id + sql_query_info = select id, groupname, artistname, taglist, filelist from sphinx_hash where id = $id } -source delta : torrents { - sql_query_pre = SET @nothing = 0 # Overwrite the inherited sql_query_pre directive - sql_query = SELECT ID, GroupName, ArtistName, TagList, Year, Year AS YearFullText, \ - RecordLabel, CatalogueNumber, CategoryID, Time, ReleaseType, Size, \ - Snatched, Seeders, Leechers, LogScore, Scene, VanityHouse, \ - HasLog, HasCue, FreeTorrent, Media, Format, Encoding, RemasterYear, \ - RemasterTitle, RemasterRecordLabel, RemasterCatalogueNumber, FileList \ - FROM sphinx_delta +source torrents : torrents_base { + #By inheriting from torrents_base, we keep all the connection info - sql_query_post = SET @nothing = 0 - sql_query_info = SELECT ID, GroupName, ArtistName, TagList, FileList FROM sphinx_delta WHERE ID = $id - sql_query_killlist = SELECT ID FROM sphinx_delta + sql_query_pre = set group_concat_max_len = 101400 + sql_query_pre = set @starttime = now() + + sql_query_pre = create temporary table sphinx_tg \ + (id int primary key, name varchar(300), tags varchar(500), \ + year smallint, rlabel varchar(80), \ + cnumber varchar(80), catid smallint, time int, \ + reltype smallint, vanityhouse tinyint) \ + engine=myisam; + + sql_query_pre = insert into sphinx_tg \ + (id, name, tags, year, rlabel, cnumber, catid, time, reltype, \ + vanityhouse) \ + select id, name, taglist, year, recordlabel, cataloguenumber, \ + categoryid, unix_timestamp(time), releasetype, \ + vanityhouse \ + from torrents_group \ + where time < @starttime; + + + sql_query_pre = create temporary table sphinx_t \ + (id int primary key, gid int, size bigint, snatched int, \ + seeders int, leechers int, time int, logscore smallint, \ + scene tinyint, haslog tinyint, hascue tinyint, \ + freetorrent tinyint, media varchar(15), \ + format varchar(15), encoding varchar(30), \ + remyear smallint, remtitle varchar(50), \ + remrlabel varchar(50), remcnumber varchar(50), \ + filelist mediumtext, \ + index (gid)) \ + engine=myisam; + + sql_query_pre = insert into sphinx_t \ + (id, gid, size, snatched, seeders, leechers, time, logscore, scene, \ + haslog, hascue, freetorrent, media, format, encoding, \ + remyear, remtitle, remrlabel, remcnumber, filelist) \ + select id, groupid, size, snatched, seeders, leechers, time, \ + logscore, cast(scene as char), cast(haslog as char), \ + cast(hascue as char), cast(freetorrent as char), media, \ + format, encoding, remasteryear, remastertitle, \ + remasterrecordlabel, remastercataloguenumber, filelist \ + from torrents \ + where time < @starttime; + + + sql_query_pre = create temporary table sphinx_a \ + (gid int primary key, aname text) \ + engine=myisam; + + sql_query_pre = insert into sphinx_a \ + (gid, aname) \ + select groupid, group_concat(aa.name separator ' ') \ + from torrents_artists ta \ + join artists_alias aa using(aliasid) \ + where importance in ('1','3','4','5','6') \ + group by ta.groupid \ + order by null; + + + sql_query = select t.id, g.id groupid, g.name groupname, tags taglist, \ + year, year yearfulltext, rlabel recordlabel, \ + cnumber cataloguenumber, catid categoryid, \ + t.time, reltype releasetype, size>>10 size, \ + snatched, seeders, leechers, logscore, scene, \ + vanityhouse, haslog, hascue, freetorrent, \ + media, format, encoding, remyear remasteryear, \ + remtitle remastertitle, remrlabel remasterrecordlabel, \ + remcnumber remastercataloguenumber, \ + replace(replace(replace(replace(filelist, \ + '.flac', ' .flac'), \ + '.mp3', ' .mp3'), \ + '|||', '\n '), \ + '_', ' ') \ + filelist \ + from sphinx_t t \ + join sphinx_tg g on t.gid=g.id + + sql_joined_field = artistname from query; \ + select t.id, aname from sphinx_a join sphinx_t t using(gid) order by t.id asc; + + sql_query_post = delete from sphinx_delta where time<=unix_timestamp(@starttime) } + index torrents { source = torrents path = /var/data/sphinx/torrents @@ -306,6 +327,12 @@ index torrents { blend_chars = !, ", U+23, $, %, &, ', (, ), *, +, U+2C, -, ., /, :, U+3B, <, =, >, ?, @, U+5B, U+5C, U+5D, ^, U+60, U+7C, U+7E, U+A1..U+BF blend_mode = trim_none, trim_head, trim_tail, trim_both } + +source delta : torrents_base { + sql_query = select *, year yearfulltext from sphinx_delta; + sql_query_killlist = select id from sphinx_delta +} + index delta : torrents { source = delta path = /var/data/sphinx/delta diff --git a/static/functions/browse.js b/static/functions/browse.js index 51a16b57..e58ced18 100644 --- a/static/functions/browse.js +++ b/static/functions/browse.js @@ -17,6 +17,7 @@ function show_peers (TorrentID, Page) { $('#downloads_' + TorrentID).hide(); $('#files_' + TorrentID).hide(); $('#reported_' + TorrentID).hide(); + $('#spectrals_' + TorrentID).hide(); } function show_snatches (TorrentID, Page){ @@ -38,6 +39,7 @@ function show_snatches (TorrentID, Page){ $('#downloads_' + TorrentID).hide(); $('#files_' + TorrentID).hide(); $('#reported_' + TorrentID).hide(); + $('#spectrals_' + TorrentID).hide(); } function show_downloads (TorrentID, Page){ @@ -59,6 +61,7 @@ function show_downloads (TorrentID, Page){ $('#snatches_' + TorrentID).hide(); $('#files_' + TorrentID).hide(); $('#reported_' + TorrentID).hide(); + $('#spectrals_' + TorrentID).hide(); } function show_files(TorrentID){ @@ -67,6 +70,7 @@ function show_files(TorrentID){ $('#snatches_' + TorrentID).hide(); $('#downloads_' + TorrentID).hide(); $('#reported_' + TorrentID).hide(); + $('#spectrals_' + TorrentID).hide(); } function show_reported(TorrentID){ @@ -75,6 +79,32 @@ function show_reported(TorrentID){ $('#snatches_' + TorrentID).hide(); $('#downloads_' + TorrentID).hide(); $('#reported_' + TorrentID).toggle(); + $('#spectrals_' + TorrentID).hide(); +} + +function show_spectrals (TorrentID){ + $('#snatches_' + TorrentID).hide(); + $('#peers_' + TorrentID).hide(); + $('#downloads_' + TorrentID).hide(); + $('#files_' + TorrentID).hide(); + $('#reported_' + TorrentID).hide(); + + $('#spectrals_' + TorrentID).toggle(); + ajax.get('http://archive.org/~abuie/spectral.php?q=' + TorrentID,function(response){ + var json = JSON.parse(response); + var html = ""; + if(json['status']['state'] == 'success') { + for (var i = 0; i < json['count']; i++) { + html += "" + json["; + html += "

"; + } + } + else { + html = "
Error: " + json['status']['reason'] + "" + } + $('#spectrals_' + TorrentID).show().raw().innerHTML=html; + }); + } function add_tag(tag) { diff --git a/static/functions/voting.js b/static/functions/voting.js new file mode 100644 index 00000000..7db5f227 --- /dev/null +++ b/static/functions/voting.js @@ -0,0 +1,39 @@ +var voteLock = false; +function DownVoteGroup(groupid, authkey) { + if (voteLock) { + return; + } + voteLock = true; + ajax.get('ajax.php?action=votefavorite&do=vote&groupid='+groupid+'&vote=down'+'&auth='+authkey, function (response) {return}); + $('.vote_link_'+groupid).hide(); + $('.vote_clear_'+groupid).show(); + $('.voted_down_'+groupid).show(); + $('.voted_up_'+groupid).hide(); + voteLock = false; +} + +function UpVoteGroup(groupid, authkey) { + if (voteLock) { + return; + } + voteLock = true; + ajax.get('ajax.php?action=votefavorite&do=vote&groupid='+groupid+'&vote=up'+'&auth='+authkey, function (response) {return}); + $('.vote_link_'+groupid).hide(); + $('.vote_clear_'+groupid).show(); + $('.voted_down_'+groupid).hide(); + $('.voted_up_'+groupid).show(); + voteLock = false; +} + +function UnvoteGroup(groupid, authkey) { + if (voteLock) { + return; + } + voteLock = true; + ajax.get('ajax.php?action=votefavorite&do=unvote&groupid='+groupid+'&auth='+authkey, function (response) {return}); + $('.vote_link_'+groupid).show(); + $('.vote_clear_'+groupid).hide(); + $('.voted_down_'+groupid).hide(); + $('.voted_up_'+groupid).hide(); + voteLock = false; +} \ No newline at end of file diff --git a/static/styles/dark_mono_v2/images/leechers.png b/static/styles/dark_mono_v2/images/leechers.png new file mode 100644 index 00000000..586acf9e Binary files /dev/null and b/static/styles/dark_mono_v2/images/leechers.png differ diff --git a/static/styles/dark_mono_v2/images/seeders.png b/static/styles/dark_mono_v2/images/seeders.png new file mode 100644 index 00000000..586acf9e Binary files /dev/null and b/static/styles/dark_mono_v2/images/seeders.png differ diff --git a/static/styles/dark_mono_v2/images/snatched.png b/static/styles/dark_mono_v2/images/snatched.png new file mode 100644 index 00000000..586acf9e Binary files /dev/null and b/static/styles/dark_mono_v2/images/snatched.png differ diff --git a/static/styles/global.css b/static/styles/global.css index 65c382ad..fa0de48f 100644 --- a/static/styles/global.css +++ b/static/styles/global.css @@ -190,7 +190,7 @@ div#AddArtists a { z-index: 25; display: block; position: fixed; - background: transparent url('../rippy/rippy_halloween_1.png') no-repeat bottom + background: transparent url('../rippy/rippy.png') no-repeat bottom center; color: black; text-align: center; @@ -348,6 +348,8 @@ tr.torrent .bookmark>a:after { list-style-type: lower-alpha; } +.voted_type { font-weight: bold; } + .torrent_table .group .votes_info_td strong { font-size: inherit; } .text_preview { min-height: 100px }