Browse Source

Add search by size

spaghetti 8 years ago
parent
commit
b6b3343db1
2 changed files with 106 additions and 91 deletions
  1. 85
    85
      classes/torrentsearch.class.php
  2. 21
    6
      sections/torrents/browse.php

+ 85
- 85
classes/torrentsearch.class.php View File

6
   const SPH_BOOL_OR = ' | ';
6
   const SPH_BOOL_OR = ' | ';
7
 
7
 
8
   // Map of sort mode => attribute name for ungrouped torrent page
8
   // Map of sort mode => attribute name for ungrouped torrent page
9
-  public static $SortOrders = array(
9
+  public static $SortOrders = [
10
     'year' => 'year',
10
     'year' => 'year',
11
     'time' => 'id',
11
     'time' => 'id',
12
     'size' => 'size',
12
     'size' => 'size',
14
     'leechers' => 'leechers',
14
     'leechers' => 'leechers',
15
     'snatched' => 'snatched',
15
     'snatched' => 'snatched',
16
     'cataloguenumber' => 'cataloguenumber',
16
     'cataloguenumber' => 'cataloguenumber',
17
-    'random' => 1);
17
+    'random' => 1
18
+  ];
18
 
19
 
19
   // Map of sort mode => attribute name for grouped torrent page
20
   // Map of sort mode => attribute name for grouped torrent page
20
-  private static $SortOrdersGrouped = array(
21
+  private static $SortOrdersGrouped = [
21
     'year' => 'year',
22
     'year' => 'year',
22
     'time' => 'id',
23
     'time' => 'id',
23
     'size' => 'maxsize',
24
     'size' => 'maxsize',
25
     'leechers' => 'sumleechers',
26
     'leechers' => 'sumleechers',
26
     'snatched' => 'sumsnatched',
27
     'snatched' => 'sumsnatched',
27
     'cataloguenumber' => 'cataloguenumber',
28
     'cataloguenumber' => 'cataloguenumber',
28
-    'random' => 1);
29
+    'random' => 1
30
+  ];
29
 
31
 
30
   // Map of sort mode => aggregate expression required for some grouped sort orders
32
   // Map of sort mode => aggregate expression required for some grouped sort orders
31
-  private static $AggregateExp = array(
33
+  private static $AggregateExp = [
32
     'size' => 'MAX(size) AS maxsize',
34
     'size' => 'MAX(size) AS maxsize',
33
     'seeders' => 'SUM(seeders) AS sumseeders',
35
     'seeders' => 'SUM(seeders) AS sumseeders',
34
     'leechers' => 'SUM(leechers) AS sumleechers',
36
     'leechers' => 'SUM(leechers) AS sumleechers',
35
-    'snatched' => 'SUM(snatched) AS sumsnatched');
37
+    'snatched' => 'SUM(snatched) AS sumsnatched'
38
+  ];
36
 
39
 
37
   // Map of attribute name => global variable name with list of values that can be used for filtering
40
   // Map of attribute name => global variable name with list of values that can be used for filtering
38
-  private static $Attributes = array(
41
+  private static $Attributes = [
39
     'filter_cat' => false,
42
     'filter_cat' => false,
40
     'releasetype' => 'ReleaseTypes',
43
     'releasetype' => 'ReleaseTypes',
41
     'freetorrent' => false,
44
     'freetorrent' => false,
42
     'censored' => false,
45
     'censored' => false,
43
-    'year' => false);
46
+    'size_unit' => false,
47
+    'year' => false
48
+  ];
44
 
49
 
45
   // List of fields that can be used for fulltext searches
50
   // List of fields that can be used for fulltext searches
46
-  private static $Fields = array(
51
+  private static $Fields = [
47
     'artistname' => 1,
52
     'artistname' => 1,
48
     'audioformat' => 1,
53
     'audioformat' => 1,
49
     'cataloguenumber' => 1,
54
     'cataloguenumber' => 1,
64
     'studio' => 1,
69
     'studio' => 1,
65
     'subber' => 1,
70
     'subber' => 1,
66
     'subbing' => 1,
71
     'subbing' => 1,
67
-    'taglist' => 1);
72
+    'taglist' => 1
73
+  ];
68
 
74
 
69
   // List of torrent-specific fields that can be used for filtering
75
   // List of torrent-specific fields that can be used for filtering
70
-  private static $TorrentFields = array(
76
+  private static $TorrentFields = [
71
     'description' => 1,
77
     'description' => 1,
72
     'encoding' => 1,
78
     'encoding' => 1,
73
     'censored' => 1,
79
     'censored' => 1,
74
     'language' => 1,
80
     'language' => 1,
75
     'filelist' => 1,
81
     'filelist' => 1,
76
     'format' => 1,
82
     'format' => 1,
77
-    'media' => 1);
83
+    'media' => 1
84
+  ];
78
 
85
 
79
   // Some form field names don't match the ones in the index
86
   // Some form field names don't match the ones in the index
80
-  private static $FormsToFields = array(
87
+  private static $FormsToFields = [
81
     'searchstr' => '(groupname,groupnamerj,groupnamejp,artistname,studio,series,dlsiteid,cataloguenumber,yearfulltext)',
88
     'searchstr' => '(groupname,groupnamerj,groupnamejp,artistname,studio,series,dlsiteid,cataloguenumber,yearfulltext)',
82
-    'advgroupname' => '(groupname,groupnamerj,groupnamejp)');
89
+    'advgroupname' => '(groupname,groupnamerj,groupnamejp)'
90
+  ];
83
 
91
 
84
   // Specify the operator type to use for fields. Empty key sets the default
92
   // Specify the operator type to use for fields. Empty key sets the default
85
-  private static $FieldOperators = array(
93
+  private static $FieldOperators = [
86
     '' => self::SPH_BOOL_AND,
94
     '' => self::SPH_BOOL_AND,
87
     'encoding' => self::SPH_BOOL_OR,
95
     'encoding' => self::SPH_BOOL_OR,
88
     'format' => self::SPH_BOOL_OR,
96
     'format' => self::SPH_BOOL_OR,
89
-    'media' => self::SPH_BOOL_OR);
97
+    'media' => self::SPH_BOOL_OR
98
+  ];
90
 
99
 
91
   // Specify the separator character to use for fields. Empty key sets the default
100
   // Specify the separator character to use for fields. Empty key sets the default
92
-  private static $FieldSeparators = array(
101
+  private static $FieldSeparators = [
93
     '' => ' ',
102
     '' => ' ',
94
     'encoding' => '|',
103
     'encoding' => '|',
95
     'format' => '|',
104
     'format' => '|',
96
     'media' => '|',
105
     'media' => '|',
97
-    'taglist' => ',');
106
+    'taglist' => ','
107
+  ];
98
 
108
 
99
   // Primary SphinxqlQuery object used to get group IDs or torrent IDs for ungrouped searches
109
   // Primary SphinxqlQuery object used to get group IDs or torrent IDs for ungrouped searches
100
   private $SphQL;
110
   private $SphQL;
109
   // Number of results
119
   // Number of results
110
   private $NumResults = 0;
120
   private $NumResults = 0;
111
   // Array with info from all matching torrent groups
121
   // Array with info from all matching torrent groups
112
-  private $Groups = array();
122
+  private $Groups = [];
113
   // Whether any filters were used
123
   // Whether any filters were used
114
   private $Filtered = false;
124
   private $Filtered = false;
115
   // Whether the random sort order is selected
125
   // Whether the random sort order is selected
122
    *     'operator' => self::SPH_BOOL_AND | self::SPH_BOOL_OR
132
    *     'operator' => self::SPH_BOOL_AND | self::SPH_BOOL_OR
123
    * ]], ...
133
    * ]], ...
124
    */
134
    */
125
-  private $Terms = array();
135
+  private $Terms = [];
126
   // Unprocessed search terms for retrieval
136
   // Unprocessed search terms for retrieval
127
-  private $RawTerms = array();
137
+  private $RawTerms = [];
128
   // Storage for used torrent-specific attribute filters
138
   // Storage for used torrent-specific attribute filters
129
   // ['Field name' => 'Search expression', ...]
139
   // ['Field name' => 'Search expression', ...]
130
-  private $UsedTorrentAttrs = array();
140
+  private $UsedTorrentAttrs = [];
131
   // Storage for used torrent-specific fulltext fields
141
   // Storage for used torrent-specific fulltext fields
132
   // ['Field name' => 'Search expression', ...]
142
   // ['Field name' => 'Search expression', ...]
133
-  private $UsedTorrentFields = array();
143
+  private $UsedTorrentFields = [];
134
 
144
 
135
   /**
145
   /**
136
    * Initialize and configure a TorrentSearch object
146
    * Initialize and configure a TorrentSearch object
144
   public function __construct($GroupResults, $OrderBy, $OrderWay, $Page, $PageSize) {
154
   public function __construct($GroupResults, $OrderBy, $OrderWay, $Page, $PageSize) {
145
     if ($GroupResults && !isset(self::$SortOrdersGrouped[$OrderBy])
155
     if ($GroupResults && !isset(self::$SortOrdersGrouped[$OrderBy])
146
         || !$GroupResults && !isset(self::$SortOrders[$OrderBy])
156
         || !$GroupResults && !isset(self::$SortOrders[$OrderBy])
147
-        || !in_array($OrderWay, array('asc', 'desc'))
157
+        || !in_array($OrderWay, ['asc', 'desc'])
148
     ) {
158
     ) {
149
       global $Debug;
159
       global $Debug;
150
       $ErrMsg = "TorrentSearch constructor arguments:\n" . print_r(func_get_args(), true);
160
       $ErrMsg = "TorrentSearch constructor arguments:\n" . print_r(func_get_args(), true);
199
    * @param array $Terms Array containing all search terms (e.g. $_GET)
209
    * @param array $Terms Array containing all search terms (e.g. $_GET)
200
    * @return array List of matching group IDs with torrent ID as key for ungrouped results
210
    * @return array List of matching group IDs with torrent ID as key for ungrouped results
201
    */
211
    */
202
-  public function query($Terms = array()) {
212
+  public function query($Terms = []) {
203
     $this->process_search_terms($Terms);
213
     $this->process_search_terms($Terms);
204
     $this->build_query();
214
     $this->build_query();
205
     $this->run_query();
215
     $this->run_query();
260
       if (isset(self::$FormsToFields[$Field])) {
270
       if (isset(self::$FormsToFields[$Field])) {
261
         $Field = self::$FormsToFields[$Field];
271
         $Field = self::$FormsToFields[$Field];
262
       }
272
       }
263
-      $QueryParts = array('include' => array(), 'exclude' => array());
273
+      $QueryParts = ['include' => [], 'exclude' => []];
264
       if (!empty($Words['include'])) {
274
       if (!empty($Words['include'])) {
265
         foreach ($Words['include'] as $Word) {
275
         foreach ($Words['include'] as $Word) {
266
           $QueryParts['include'][] = Sphinxql::sph_escape_string($Word);
276
           $QueryParts['include'][] = Sphinxql::sph_escape_string($Word);
316
       }
326
       }
317
       $this->RawTerms[$Key] = $Term;
327
       $this->RawTerms[$Key] = $Term;
318
     }
328
     }
319
-    $this->post_process_fields();
329
+    $this->post_process();
320
   }
330
   }
321
 
331
 
322
   /**
332
   /**
326
    * @param mixed $Value The filter's condition for a match
336
    * @param mixed $Value The filter's condition for a match
327
    */
337
    */
328
   private function process_attribute($Attribute, $Value) {
338
   private function process_attribute($Attribute, $Value) {
329
-    if ($Value === '') {
330
-      return;
331
-    }
332
-    switch ($Attribute) {
333
-      case 'year':
334
-        if (!$this->search_year($Value)) {
335
-          return;
336
-        }
337
-        break;
338
-
339
-      case 'freetorrent':
340
-        if ($Value == 3) {
341
-          $this->SphQL->where('freetorrent', 0, true);
342
-          $this->UsedTorrentAttrs['freetorrent'] = 3;
343
-        } elseif ($Value >= 0 && $Value < 3) {
344
-          $this->SphQL->where('freetorrent', $Value);
345
-          $this->UsedTorrentAttrs[$Attribute] = $Value;
339
+    if ($Value === '') { return; }
340
+
341
+    if ($Attribute === 'year') {
342
+      $this->search_year($Value);
343
+    } elseif ($Attribute === 'size_unit') {
344
+      // for the record, size_unit must appear in the GET parameters after size_min and size_max for this to work. Sorry.
345
+      if (is_numeric($this->RawTerms['size_min']) || is_numeric($this->RawTerms['size_max']))  {
346
+        $this->SphQL->where_between('size', [intval(($this->RawTerms['size_min'] ?? 0)*(1024**$Value)), intval(min(PHP_INT_MAX, ($this->RawTerms['size_max'] ?? INF)*(1024**$Value)))]);
347
+      }
348
+    } elseif ($Attribute === 'freetorrent') {
349
+      if ($Value == 3) {
350
+        $this->SphQL->where('freetorrent', 0, true);
351
+        $this->UsedTorrentAttrs['freetorrent'] = 3;
352
+      } elseif ($Value >= 0 && $Value < 3) {
353
+        $this->SphQL->where('freetorrent', $Value);
354
+        $this->UsedTorrentAttrs[$Attribute] = $Value;
355
+      }
356
+    } elseif ($Attribute === 'filter_cat') {
357
+      if (!is_array($Value)) {
358
+        $Value = array_fill_keys(explode('|', $Value), 1);
359
+      }
360
+      $CategoryFilter = [];
361
+      foreach (array_keys($Value) as $Category) {
362
+        if (is_number($Category)) {
363
+          $CategoryFilter[] = $Category;
346
         } else {
364
         } else {
347
-          return;
348
-        }
349
-        break;
350
-
351
-      case 'filter_cat':
352
-        if (!is_array($Value)) {
353
-          $Value = array_fill_keys(explode('|', $Value), 1);
354
-        }
355
-        $CategoryFilter = array();
356
-        foreach (array_keys($Value) as $Category) {
357
-          if (is_number($Category)) {
358
-            $CategoryFilter[] = $Category;
359
-          } else {
360
-            global $Categories;
361
-            $ValidValues = array_map('strtolower', $Categories);
362
-            if (($CategoryID = array_search(strtolower($Category), $ValidValues)) !== false) {
363
-              $CategoryFilter[] = $CategoryID + 1;
364
-            }
365
+          global $Categories;
366
+          $ValidValues = array_map('strtolower', $Categories);
367
+          if (($CategoryID = array_search(strtolower($Category), $ValidValues)) !== false) {
368
+            $CategoryFilter[] = $CategoryID + 1;
365
           }
369
           }
366
         }
370
         }
367
-        if (empty($CategoryFilter)) {
368
-          $CategoryFilter = 0;
369
-        }
370
-        $this->SphQL->where('categoryid', $CategoryFilter);
371
-        break;
372
-
373
-      default:
374
-        if (!is_number($Value) && self::$Attributes[$Attribute] !== false) {
375
-          // Check if the submitted value can be converted to a valid one
376
-          $ValidValuesVarname = self::$Attributes[$Attribute];
377
-          global $$ValidValuesVarname;
378
-          $ValidValues = array_map('strtolower', $$ValidValuesVarname);
379
-          if (($Value = array_search(strtolower($Value), $ValidValues)) === false) {
380
-            // Force the query to return 0 results if value is still invalid
381
-            $Value = max(array_keys($ValidValues)) + 1;
382
-          }
371
+      }
372
+      $this->SphQL->where('categoryid', ($CategoryFilter ?? 0));
373
+    } else {
374
+      if (!is_number($Value) && self::$Attributes[$Attribute] !== false) {
375
+        // Check if the submitted value can be converted to a valid one
376
+        $ValidValuesVarname = self::$Attributes[$Attribute];
377
+        global $$ValidValuesVarname;
378
+        $ValidValues = array_map('strtolower', $$ValidValuesVarname);
379
+        if (($Value = array_search(strtolower($Value), $ValidValues)) === false) {
380
+          // Force the query to return 0 results if value is still invalid
381
+          $Value = max(array_keys($ValidValues)) + 1;
383
         }
382
         }
384
-        $this->SphQL->where($Attribute, $Value);
385
-        $this->UsedTorrentAttrs[$Attribute] = $Value;
386
-        break;
383
+      }
384
+      $this->SphQL->where($Attribute, $Value);
385
+      $this->UsedTorrentAttrs[$Attribute] = $Value;
387
     }
386
     }
387
+
388
     $this->Filtered = true;
388
     $this->Filtered = true;
389
   }
389
   }
390
 
390
 
413
   /**
413
   /**
414
    * Some fields may require post-processing
414
    * Some fields may require post-processing
415
    */
415
    */
416
-  private function post_process_fields() {
416
+  private function post_process() {
417
     if (isset($this->Terms['taglist'])) {
417
     if (isset($this->Terms['taglist'])) {
418
       // Replace bad tags with tag aliases
418
       // Replace bad tags with tag aliases
419
       $this->Terms['taglist'] = Tags::remove_aliases($this->Terms['taglist']);
419
       $this->Terms['taglist'] = Tags::remove_aliases($this->Terms['taglist']);
424
       if (isset($this->Terms['taglist']['include'])) {
424
       if (isset($this->Terms['taglist']['include'])) {
425
         $AllTags = $this->Terms['taglist']['include'];
425
         $AllTags = $this->Terms['taglist']['include'];
426
       } else {
426
       } else {
427
-        $AllTags = array();
427
+        $AllTags = [];
428
       }
428
       }
429
       if (isset($this->Terms['taglist']['exclude'])) {
429
       if (isset($this->Terms['taglist']['exclude'])) {
430
         $AllTags = array_merge($AllTags, $this->Terms['taglist']['exclude']);
430
         $AllTags = array_merge($AllTags, $this->Terms['taglist']['exclude']);
501
         $this->SphQL->where_gt('year', $Years[0], true);
501
         $this->SphQL->where_gt('year', $Years[0], true);
502
       } elseif (is_number($Years[0]) && is_number($Years[1])) {
502
       } elseif (is_number($Years[0]) && is_number($Years[1])) {
503
         // Range: 2005 - 2009
503
         // Range: 2005 - 2009
504
-        $this->SphQL->where_between('year', array(min($Years), max($Years)));
504
+        $this->SphQL->where_between('year', [min($Years), max($Years)]);
505
       } else {
505
       } else {
506
         // Invalid input
506
         // Invalid input
507
         return false;
507
         return false;
609
    * were used to get primary results and they are grouped
609
    * were used to get primary results and they are grouped
610
    */
610
    */
611
   private function filter_torrents_sph() {
611
   private function filter_torrents_sph() {
612
-    $AllTorrents = array();
612
+    $AllTorrents = [];
613
     foreach ($this->Groups as $GroupID => $Group) {
613
     foreach ($this->Groups as $GroupID => $Group) {
614
       if (!empty($Group['Torrents'])) {
614
       if (!empty($Group['Torrents'])) {
615
         $AllTorrents += array_fill_keys(array_keys($Group['Torrents']), $GroupID);
615
         $AllTorrents += array_fill_keys(array_keys($Group['Torrents']), $GroupID);

+ 21
- 6
sections/torrents/browse.php View File

13
   } else {
13
   } else {
14
     $NewWay = $DefaultWay;
14
     $NewWay = $DefaultWay;
15
   }
15
   }
16
-  return "torrents.php?order_way=$NewWay&amp;order_by=$SortKey&amp;".Format::get_url(array('order_way', 'order_by'));
16
+  return "torrents.php?order_way=$NewWay&amp;order_by=$SortKey&amp;".Format::get_url(['order_way', 'order_by']);
17
 }
17
 }
18
 
18
 
19
 if (!empty($_GET['searchstr']) || !empty($_GET['groupname'])) {
19
 if (!empty($_GET['searchstr']) || !empty($_GET['groupname'])) {
41
 
41
 
42
 // Setting default search options
42
 // Setting default search options
43
 if (!empty($_GET['setdefault'])) {
43
 if (!empty($_GET['setdefault'])) {
44
-  $UnsetList = array('page', 'setdefault');
44
+  $UnsetList = ['page', 'setdefault'];
45
   $UnsetRegexp = '/(&|^)('.implode('|', $UnsetList).')=.*?(&|$)/i';
45
   $UnsetRegexp = '/(&|^)('.implode('|', $UnsetList).')=.*?(&|$)/i';
46
 
46
 
47
   $DB->query("
47
   $DB->query("
52
   if (!empty($SiteOptions)) {
52
   if (!empty($SiteOptions)) {
53
     $SiteOptions = unserialize($SiteOptions);
53
     $SiteOptions = unserialize($SiteOptions);
54
   } else {
54
   } else {
55
-    $SiteOptions = array();
55
+    $SiteOptions = [];
56
   }
56
   }
57
   $SiteOptions['DefaultSearch'] = preg_replace($UnsetRegexp, '', $_SERVER['QUERY_STRING']);
57
   $SiteOptions['DefaultSearch'] = preg_replace($UnsetRegexp, '', $_SERVER['QUERY_STRING']);
58
   $DB->query("
58
   $DB->query("
60
     SET SiteOptions = '".db_string(serialize($SiteOptions))."'
60
     SET SiteOptions = '".db_string(serialize($SiteOptions))."'
61
     WHERE UserID = '".db_string($LoggedUser['ID'])."'");
61
     WHERE UserID = '".db_string($LoggedUser['ID'])."'");
62
   $Cache->begin_transaction("user_info_heavy_$UserID");
62
   $Cache->begin_transaction("user_info_heavy_$UserID");
63
-  $Cache->update_row(false, array('DefaultSearch' => $SiteOptions['DefaultSearch']));
63
+  $Cache->update_row(false, ['DefaultSearch' => $SiteOptions['DefaultSearch']]);
64
   $Cache->commit_transaction(0);
64
   $Cache->commit_transaction(0);
65
 
65
 
66
 // Clearing default search options
66
 // Clearing default search options
77
     SET SiteOptions = '".db_string(serialize($SiteOptions))."'
77
     SET SiteOptions = '".db_string(serialize($SiteOptions))."'
78
     WHERE UserID = '".db_string($LoggedUser['ID'])."'");
78
     WHERE UserID = '".db_string($LoggedUser['ID'])."'");
79
   $Cache->begin_transaction("user_info_heavy_$UserID");
79
   $Cache->begin_transaction("user_info_heavy_$UserID");
80
-  $Cache->update_row(false, array('DefaultSearch' => ''));
80
+  $Cache->update_row(false, ['DefaultSearch' => '']);
81
   $Cache->commit_transaction(0);
81
   $Cache->commit_transaction(0);
82
 
82
 
83
 // Use default search options
83
 // Use default search options
268
             <input type="search" spellcheck="false" size="65" name="subber" class="inputtext smaller fti_advanced" placeholder="Translation Group" value="<?Format::form('subber')?>" />
268
             <input type="search" spellcheck="false" size="65" name="subber" class="inputtext smaller fti_advanced" placeholder="Translation Group" value="<?Format::form('subber')?>" />
269
           </td>
269
           </td>
270
         </tr>
270
         </tr>
271
+        <tr id="size" class="ftr_advanced<?=$HideAdvanced?>">
272
+          <td class="label">Size:</td>
273
+          <td class="ft_size">
274
+            <input type="size_min" spellcheck="false" size="6" name="size_min" class="inputtext smaller fti_advanced" placeholder="Min" value="<?Format::form('size_min')?>" /> -
275
+            <input type="size_max" spellcheck="false" size="6" name="size_max" class="inputtext smaller fti_advanced" placeholder="Max" value="<?Format::form('size_max')?>" />
276
+            <select name="size_unit" class="ft_size fti_advanced">
277
+              <option value="">Unit</option>
278
+              <option value="0"<?Format::selected('size_unit', 0)?>>B</option>
279
+              <option value="1"<?Format::selected('size_unit', 1)?>>KiB</option>
280
+              <option value="2"<?Format::selected('size_unit', 2)?>>MiB</option>
281
+              <option value="3"<?Format::selected('size_unit', 3)?>>GiB</option>
282
+              <option value="4"<?Format::selected('size_unit', 4)?>>TiB</option>
283
+            </select>
284
+          </td>
285
+        </tr>
271
         <tr id="misc" class="ftr_advanced<?=$HideAdvanced?>">
286
         <tr id="misc" class="ftr_advanced<?=$HideAdvanced?>">
272
           <td class="label">Misc:</td>
287
           <td class="label">Misc:</td>
273
           <td class="nobr ft_misc">
288
           <td class="nobr ft_misc">
495
     }
510
     }
496
   } else {
511
   } else {
497
     $TorrentID = $Key;
512
     $TorrentID = $Key;
498
-    $Torrents = array($TorrentID => $GroupInfo['Torrents'][$TorrentID]);
513
+    $Torrents = [$TorrentID => $GroupInfo['Torrents'][$TorrentID]];
499
   }
514
   }
500
 
515
 
501
   $TorrentTags = new Tags($GroupInfo['TagList']);
516
   $TorrentTags = new Tags($GroupInfo['TagList']);

Loading…
Cancel
Save