diff --git a/config.ini b/config.ini index 3f7f7be9..831968ed 100644 --- a/config.ini +++ b/config.ini @@ -5,8 +5,16 @@ prettyPrint=1 [main] dbPath=./db.sqlite filesPath=./files/ +thumbsPath=./files/ +mediaPath=./public_html/media/ title=szurubooru +[browsing] +postsPerPage=20 +thumbWidth=150 +thumbHeight=150 +thumbStyle=outside + [registration] emailActivation = 0 adminActivation = 0 diff --git a/public_html/media/css/upload.css b/public_html/media/css/upload.css index 40a106c7..1629206c 100644 --- a/public_html/media/css/upload.css +++ b/public_html/media/css/upload.css @@ -31,7 +31,7 @@ width: 100px; height: 100px; line-height: 100px; - background-image: url('../img/thumb-unavailable.png'); + background-image: url('../img/thumb-upload.png'); border: 1px solid black; vertical-align: middle; text-align: center; diff --git a/public_html/media/img/thumb-swf.png b/public_html/media/img/thumb-swf.png new file mode 100644 index 00000000..3100aa53 Binary files /dev/null and b/public_html/media/img/thumb-swf.png differ diff --git a/public_html/media/img/thumb-unavailable.png b/public_html/media/img/thumb-upload.png similarity index 100% rename from public_html/media/img/thumb-unavailable.png rename to public_html/media/img/thumb-upload.png diff --git a/public_html/media/img/thumb.png b/public_html/media/img/thumb.png new file mode 100644 index 00000000..d079c1e4 Binary files /dev/null and b/public_html/media/img/thumb.png differ diff --git a/src/Controllers/PostController.php b/src/Controllers/PostController.php index 238be13e..adc0752b 100644 --- a/src/Controllers/PostController.php +++ b/src/Controllers/PostController.php @@ -8,6 +8,8 @@ class PostController $callback(); } + + /** * @route /posts * @route /posts/{query} @@ -31,23 +33,32 @@ class PostController $page = 1; $params = []; - $params[':limit'] = 20; - $params[':offset'] = ($page - 1) * $params[':limit']; + $allowedSafety = array_filter(PostSafety::getAll(), function($safety) + { + return PrivilegesHelper::confirm($this->context->user, Privilege::ListPosts, PostSafety::toString($safety)); + }); //todo safety [user choice] - //todo safety [user privileges] + + $whereSql = 'WHERE safety IN (' . R::genSlots($allowedSafety) . ')'; + $params = array_merge($params, $allowedSafety); + //todo construct WHERE based on filters - $whereSql = ''; //todo construct ORDER based on filers $orderSql = 'ORDER BY upload_date DESC'; - $limitSql = 'LIMIT :limit OFFSET :offset'; + $limitSql = 'LIMIT ? OFFSET ?'; + $postsPerPage = intval($this->config->browsing->postsPerPage); + $params[] = $postsPerPage; + $params[] = ($page - 1) * $postsPerPage; $posts = R::findAll('post', sprintf('%s %s %s', $whereSql, $orderSql, $limitSql), $params); $this->context->transport->posts = $posts; } + + /** * @route /post/upload */ @@ -123,12 +134,12 @@ class PostController move_uploaded_file($suppliedFile['tmp_name'], $path); R::store($dbPost); - //todo: generate thumbnail - $this->context->transport->success = true; } } + + /** * Action that decorates the page containing the post. * @route /post/{id} @@ -146,6 +157,82 @@ class PostController $this->context->transport->post = $post; } + + + /** + * Action that renders the thumbnail of the requested file and sends it to user. + * @route /post/thumb/{id} + */ + public function thumbAction($id) + { + $this->context->layoutName = 'layout-file'; + + $post = R::findOne('post', 'id = ?', [$id]); + if (!$post) + throw new SimpleException('Invalid post ID "' . $id . '"'); + + PrivilegesHelper::confirmWithException($this->context->user, Privilege::ViewPost); + PrivilegesHelper::confirmWithException($this->context->user, Privilege::ViewPost, PostSafety::toString($post->safety)); + + $path = $this->config->main->thumbsPath . DIRECTORY_SEPARATOR . $post->name . '.png'; + if (!file_exists($path)) + { + $srcPath = $this->config->main->thumbsPath . DIRECTORY_SEPARATOR . $post->name; + $dstPath = $path; + $dstWidth = $this->config->browsing->thumbWidth; + $dstHeight = $this->config->browsing->thumbHeight; + + switch($post->mime_type) + { + case 'image/jpeg': + $srcImage = imagecreatefromjpeg($srcPath); + break; + case 'image/png': + $srcImage = imagecreatefrompng($srcPath); + break; + case 'image/gif': + $srcImage = imagecreatefromgif($srcPath); + break; + case 'application/x-shockwave-flash': + $path = $this->config->main->mediaPath . DIRECTORY_SEPARATOR . 'img' . DIRECTORY_SEPARATOR . 'thumb-swf.png'; + break; + default: + $path = $this->config->main->mediaPath . DIRECTORY_SEPARATOR . 'img' . DIRECTORY_SEPARATOR . 'thumb.png'; + break; + } + + if (isset($srcImage)) + { + switch ($this->config->browsing->thumbStyle) + { + case 'outside': + $dstImage = ThumbnailHelper::cropOutside($srcImage, $dstWidth, $dstHeight); + break; + case 'inside': + $dstImage = ThumbnailHelper::cropInside($srcImage, $dstWidth, $dstHeight); + break; + default: + throw new SimpleException('Unknown thumbnail crop style'); + } + + imagepng($dstImage, $dstPath); + imagedestroy($srcImage); + imagedestroy($dstImage); + } + } + if (!is_readable($path)) + throw new SimpleException('Thumbnail file is not readable'); + + \Chibi\HeadersHelper::set('Pragma', 'public'); + \Chibi\HeadersHelper::set('Cache-Control', 'max-age=86400'); + \Chibi\HeadersHelper::set('Expires', gmdate('D, d M Y H:i:s \G\M\T', time() + 86400)); + + $this->context->transport->mimeType = 'image/png'; + $this->context->transport->filePath = $path; + } + + + /** * Action that renders the requested file itself and sends it to user. * @route /post/retrieve/{name} @@ -171,6 +258,8 @@ class PostController $this->context->transport->filePath = $path; } + + /** * @route /favorites */ diff --git a/src/Helpers/ThumbnailHelper.php b/src/Helpers/ThumbnailHelper.php new file mode 100644 index 00000000..4f9d1ccf --- /dev/null +++ b/src/Helpers/ThumbnailHelper.php @@ -0,0 +1,47 @@ + ($srcHeight / $srcWidth)) + { + $h = $srcHeight; + $w = $h * $dstWidth / $dstHeight; + } + else + { + $w = $srcWidth; + $h = $w * $dstHeight / $dstWidth; + } + $x = ($srcWidth - $w) / 2; + $y = ($srcHeight - $h) / 2; + + $dstImage = imagecreatetruecolor($dstWidth, $dstHeight); + imagecopyresampled($dstImage, $srcImage, 0, 0, $x, $y, $dstWidth, $dstHeight, $w, $h); + return $dstImage; + } + + public static function cropInside($srcImage, $dstWidth, $dstHeight) + { + $srcWidth = imagesx($srcImage); + $srcHeight = imagesy($srcImage); + + if (($dstHeight / $dstWidth) < ($srcHeight / $srcWidth)) + { + $h = $dstHeight; + $w = $h * $srcWidth / $srcHeight; + } + else + { + $w = $dstWidth; + $h = $w * $srcHeight / $srcWidth; + } + + $dstImage = imagecreatetruecolor($w, $h); + imagecopyresampled($dstImage, $srcImage, 0, 0, 0, 0, $w, $h, $srcWidth, $srcHeight); + return $dstImage; + } +} diff --git a/src/Views/post-list.phtml b/src/Views/post-list.phtml index bfec607c..207e1fba 100644 --- a/src/Views/post-list.phtml +++ b/src/Views/post-list.phtml @@ -3,7 +3,7 @@ context->transport->posts as $post): ?> - Post id; ?> + @<?php echo $post->id ?> diff --git a/thumbs/.gitignore b/thumbs/.gitignore new file mode 100644 index 00000000..d6b7ef32 --- /dev/null +++ b/thumbs/.gitignore @@ -0,0 +1,2 @@ +* +!.gitignore