MediaQuery.php 7.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250
  1. <?php
  2. namespace App\Database\Queries;
  3. use App\Database\DB;
  4. use League\Flysystem\FileNotFoundException;
  5. use League\Flysystem\Filesystem;
  6. use League\Flysystem\Plugin\ListFiles;
  7. class MediaQuery
  8. {
  9. const PER_PAGE = 21;
  10. const PER_PAGE_ADMIN = 27;
  11. const ORDER_TIME = 0;
  12. const ORDER_NAME = 1;
  13. const ORDER_SIZE = 2;
  14. /** @var DB */
  15. protected $db;
  16. /** @var bool */
  17. protected $isAdmin;
  18. protected $userId;
  19. /** @var int */
  20. protected $orderBy;
  21. /** @var string */
  22. protected $orderMode;
  23. /** @var string */
  24. protected $text;
  25. /** @var Filesystem */
  26. protected $storage;
  27. private $pages;
  28. private $media;
  29. /**
  30. * MediaQuery constructor.
  31. *
  32. * @param DB $db
  33. * @param bool $isAdmin
  34. * @param Filesystem $storage
  35. */
  36. public function __construct(DB $db, Filesystem $storage, bool $isAdmin)
  37. {
  38. $this->db = $db;
  39. $this->isAdmin = $isAdmin;
  40. $this->storage = $storage;
  41. }
  42. /**
  43. * @param DB $db
  44. * @param bool $isAdmin
  45. * @param Filesystem $storage
  46. * @return MediaQuery
  47. */
  48. public static function make(DB $db, Filesystem $storage, bool $isAdmin)
  49. {
  50. return new self($db, $storage, $isAdmin);
  51. }
  52. /**
  53. * @param $id
  54. *
  55. * @return $this
  56. */
  57. public function withUserId($id)
  58. {
  59. $this->userId = $id;
  60. return $this;
  61. }
  62. /**
  63. * @param string|null $type
  64. * @param string $mode
  65. *
  66. * @return $this
  67. */
  68. public function orderBy(string $type = null, $mode = 'ASC')
  69. {
  70. $this->orderBy = ($type === null) ? self::ORDER_TIME : $type;
  71. $this->orderMode = (strtoupper($mode) === 'ASC') ? 'ASC' : 'DESC';
  72. return $this;
  73. }
  74. /**
  75. * @param string $text
  76. *
  77. * @return $this
  78. */
  79. public function search(?string $text)
  80. {
  81. $this->text = $text;
  82. return $this;
  83. }
  84. /**
  85. * @param int $page
  86. * @return MediaQuery|void
  87. */
  88. public function run(int $page)
  89. {
  90. if ($this->orderBy == self::ORDER_SIZE) {
  91. $this->runWithOrderBySize($page);
  92. return;
  93. }
  94. $queryPages = 'SELECT COUNT(*) AS `count` FROM `uploads`';
  95. if ($this->isAdmin) {
  96. $queryMedia = 'SELECT `uploads`.*, `users`.`user_code`, `users`.`username` FROM `uploads` LEFT JOIN `users` ON `uploads`.`user_id` = `users`.`id` %s LIMIT ? OFFSET ?';
  97. } else {
  98. $queryMedia = 'SELECT `uploads`.*,`users`.`user_code`, `users`.`username` FROM `uploads` INNER JOIN `users` ON `uploads`.`user_id` = `users`.`id` WHERE `user_id` = ? %s LIMIT ? OFFSET ?';
  99. $queryPages .= ' WHERE `user_id` = ?';
  100. }
  101. $orderAndSearch = '';
  102. $params = [];
  103. if ($this->text !== null) {
  104. $orderAndSearch = $this->isAdmin ? 'WHERE `uploads`.`filename` LIKE ? ' : 'AND `uploads`.`filename` LIKE ? ';
  105. $queryPages .= $this->isAdmin ? ' WHERE `filename` LIKE ?' : ' AND `filename` LIKE ?';
  106. $params[] = '%'.htmlentities($this->text).'%';
  107. }
  108. switch ($this->orderBy) {
  109. case self::ORDER_NAME:
  110. $orderAndSearch .= 'ORDER BY `filename` '.$this->orderMode;
  111. break;
  112. default:
  113. case self::ORDER_TIME:
  114. $orderAndSearch .= 'ORDER BY `timestamp` '.$this->orderMode;
  115. break;
  116. }
  117. $queryMedia = sprintf($queryMedia, $orderAndSearch);
  118. if ($this->isAdmin) {
  119. $this->media = $this->db->query($queryMedia, array_merge($params, [self::PER_PAGE_ADMIN, $page * self::PER_PAGE_ADMIN]))->fetchAll();
  120. $this->pages = $this->db->query($queryPages, $params)->fetch()->count / self::PER_PAGE_ADMIN;
  121. } else {
  122. $this->media = $this->db->query($queryMedia, array_merge([$this->userId], $params, [self::PER_PAGE, $page * self::PER_PAGE]))->fetchAll();
  123. $this->pages = $this->db->query($queryPages, array_merge([$this->userId], $params))->fetch()->count / self::PER_PAGE;
  124. }
  125. foreach ($this->media as $media) {
  126. try {
  127. $media->size = humanFileSize($this->storage->getSize($media->storage_path));
  128. $media->mimetype = $this->storage->getMimetype($media->storage_path);
  129. } catch (FileNotFoundException $e) {
  130. $media->size = null;
  131. $media->mimetype = null;
  132. }
  133. $media->extension = pathinfo($media->filename, PATHINFO_EXTENSION);
  134. }
  135. return $this;
  136. }
  137. /**
  138. * @param int $page
  139. */
  140. private function runWithOrderBySize(int $page)
  141. {
  142. $this->storage->addPlugin(new ListFiles());
  143. if ($this->isAdmin) {
  144. $files = $this->storage->listFiles('/', true);
  145. $this->pages = count($files) / self::PER_PAGE_ADMIN;
  146. $offset = $page * self::PER_PAGE_ADMIN;
  147. $limit = self::PER_PAGE_ADMIN;
  148. } else {
  149. $userCode = $this->db->query('SELECT `user_code` FROM `users` WHERE `id` = ?', [$this->userId])->fetch()->user_code;
  150. $files = $this->storage->listFiles($userCode);
  151. $this->pages = count($files) / self::PER_PAGE;
  152. $offset = $page * self::PER_PAGE;
  153. $limit = self::PER_PAGE;
  154. }
  155. array_multisort(array_column($files, 'size'), ($this->orderMode === 'ASC') ? SORT_ASC : SORT_DESC, SORT_NUMERIC, $files);
  156. if ($this->text !== null) {
  157. if ($this->isAdmin) {
  158. $medias = $this->db->query('SELECT `uploads`.*, `users`.`user_code`, `users`.`username` FROM `uploads` LEFT JOIN `users` ON `uploads`.`user_id` = `users`.`id` WHERE `uploads`.`filename` LIKE ? ', ['%'.htmlentities($this->text).'%'])->fetchAll();
  159. } else {
  160. $medias = $this->db->query('SELECT `uploads`.*, `users`.`user_code`, `users`.`username` FROM `uploads` LEFT JOIN `users` ON `uploads`.`user_id` = `users`.`id` WHERE `user_id` = ? AND `uploads`.`filename` LIKE ? ', [$this->userId, '%'.htmlentities($this->text).'%'])->fetchAll();
  161. }
  162. $paths = array_column($files, 'path');
  163. } else {
  164. $files = array_slice($files, $offset, $limit);
  165. $paths = array_column($files, 'path');
  166. $medias = $this->db->query('SELECT `uploads`.*, `users`.`user_code`, `users`.`username` FROM `uploads` LEFT JOIN `users` ON `uploads`.`user_id` = `users`.`id` WHERE `uploads`.`storage_path` IN ("'.implode('","', $paths).'")')->fetchAll();
  167. }
  168. $paths = array_flip($paths);
  169. foreach ($medias as $media) {
  170. $paths[$media->storage_path] = $media;
  171. }
  172. $this->media = [];
  173. foreach ($files as $file) {
  174. $media = $paths[$file['path']];
  175. if (!is_object($media)) {
  176. continue;
  177. }
  178. $media->size = humanFileSize($file['size']);
  179. try {
  180. $media->mimetype = $this->storage->getMimetype($file['path']);
  181. } catch (FileNotFoundException $e) {
  182. $media->mimetype = null;
  183. }
  184. $media->extension = $file['extension'];
  185. $this->media[] = $media;
  186. }
  187. if ($this->text !== null) {
  188. $this->media = array_slice($this->media, $offset, $limit);
  189. }
  190. }
  191. /**
  192. * @return mixed
  193. */
  194. public function getMedia()
  195. {
  196. return $this->media;
  197. }
  198. /**
  199. * @return mixed
  200. */
  201. public function getPages()
  202. {
  203. return $this->pages;
  204. }
  205. }