From 7c5d1b7e3462bc6a685ba27aa486eee1b2b562be Mon Sep 17 00:00:00 2001 From: Marcin Kurczewski Date: Sat, 12 Oct 2013 14:53:47 +0200 Subject: [PATCH] Favorites; gravatar support --- config.ini | 1 + public_html/media/css/core.css | 4 +- public_html/media/css/post-view.css | 23 ++++++- public_html/media/js/post-view.js | 20 ++++++ src/Bootstrap.php | 1 - src/Controllers/PostController.php | 95 ++++++++++++++++++++++++----- src/Models/Model_User.php | 13 ++++ src/Models/Privilege.php | 7 ++- src/Views/post-view.phtml | 85 ++++++++++++++++++++++++-- src/core.php | 34 ++++++++--- 10 files changed, 244 insertions(+), 39 deletions(-) create mode 100644 public_html/media/js/post-view.js create mode 100644 src/Models/Model_User.php diff --git a/config.ini b/config.ini index 50d7159a..2c6b9770 100644 --- a/config.ini +++ b/config.ini @@ -44,6 +44,7 @@ listPosts=anonymous listPosts.sketchy=registered listPosts.unsafe=registered listUsers=registered +favoritePost=registered listComments=registered retrievePost=anonymous listTags=anonymous diff --git a/public_html/media/css/core.css b/public_html/media/css/core.css index 9f791da9..29b68317 100644 --- a/public_html/media/css/core.css +++ b/public_html/media/css/core.css @@ -87,8 +87,8 @@ body { } #sidebar .sidebar-unit { - margin: 0 0 2em 0; - padding: 1em; + margin: 0 0 1.5em 0; + padding: 0.75em; border: 1px solid #eee; padding-left: 0; border-left: 0; diff --git a/public_html/media/css/post-view.css b/public_html/media/css/post-view.css index 26a466d1..01087b7a 100644 --- a/public_html/media/css/post-view.css +++ b/public_html/media/css/post-view.css @@ -1,5 +1,7 @@ #sidebar { width: 200px; + line-height: 1.33em; + font-size: 90%; } .post-wrapper { @@ -71,9 +73,24 @@ i.icon-dl { content: ', '; } -.details { - line-height: 1.33em; -} .details .key { margin-right: 0.5em; } + +.options nav ul { + list-style-type: none; + margin: 0; + padding: 0; +} + +.favorites ul { + list-style-type: none; + margin: 0; + padding: 0; +} +.favorites li { + display: inline-block; +} +.favorites a { + margin: 2px; +} diff --git a/public_html/media/js/post-view.js b/public_html/media/js/post-view.js new file mode 100644 index 00000000..d3021213 --- /dev/null +++ b/public_html/media/js/post-view.js @@ -0,0 +1,20 @@ +$(function() +{ + $('.add-fav a, .rem-fav a').click(function(e) + { + e.preventDefault(); + var url = $(this).attr('href'); + url += '?json'; + $.get(url, function(data) + { + if (data['errorMessage']) + { + alert(data['errorMessage']); + } + else + { + window.location.reload(); + } + }); + }); +}); diff --git a/src/Bootstrap.php b/src/Bootstrap.php index 771a14ed..85508ce1 100644 --- a/src/Bootstrap.php +++ b/src/Bootstrap.php @@ -24,7 +24,6 @@ class Bootstrap public function workWrapper($workCallback) { $this->config->chibi->baseUrl = 'http://' . rtrim($_SERVER['HTTP_HOST'], '/') . '/'; - R::setup('sqlite:' . $this->config->main->dbPath); session_start(); $this->context->title = $this->config->main->title; diff --git a/src/Controllers/PostController.php b/src/Controllers/PostController.php index 279c25e1..8e3e515d 100644 --- a/src/Controllers/PostController.php +++ b/src/Controllers/PostController.php @@ -188,10 +188,11 @@ class PostController $dbPost->mime_type = $mimeType; $dbPost->safety = $suppliedSafety; $dbPost->upload_date = time(); - $dbPost->sharedTag = $dbTags; - $dbPost->user = $this->context->user; $dbPost->image_width = $imageWidth; $dbPost->image_height = $imageHeight; + $dbPost->uploader = $this->context->user; + $dbPost->ownFavoritee = []; + $dbPost->sharedTag = $dbTags; move_uploaded_file($suppliedFile['tmp_name'], $path); R::store($dbPost); @@ -200,6 +201,54 @@ class PostController } } + /** + * @route /post/add-fav/{id} + * @route /post/fav-add/{id} + */ + public function addFavoriteAction($id) + { + $post = self::locatePost($id); + R::preload($post, ['favoritee' => 'user']); + + if (!$this->context->loggedIn) + throw new SimpleException('Not logged in'); + + foreach ($post->via('favoritee')->sharedUser as $fav) + if ($fav->id == $this->context->user->id) + throw new SimpleException('Already in favorites'); + + PrivilegesHelper::confirmWithException($this->context->user, Privilege::FavoritePost); + $post->link('favoritee')->user = $this->context->user; + R::store($post); + $this->context->transport->success = true; + } + + /** + * @route /post/rem-fav/{id} + * @route /post/fav-rem/{id} + */ + public function remFavoriteAction($id) + { + $post = self::locatePost($id); + R::preload($post, ['favoritee' => 'user']); + + PrivilegesHelper::confirmWithException($this->context->user, Privilege::FavoritePost); + if (!$this->context->loggedIn) + throw new SimpleException('Not logged in'); + + $finalKey = null; + foreach ($post->ownFavoritee as $key => $fav) + if ($fav->user->id == $this->context->user->id) + $finalKey = $key; + + if ($finalKey === null) + throw new SimpleException('Not in favorites'); + + unset ($post->ownFavoritee[$key]); + R::store($post); + $this->context->transport->success = true; + } + /** @@ -208,10 +257,8 @@ class PostController */ public function viewAction($id) { - $post = R::findOne('post', 'id = ?', [$id]); - if (!$post) - throw new SimpleException('Invalid post ID "' . $id . '"'); - R::preload($post, ['user', 'tag']); + $post = self::locatePost($id); + R::preload($post, ['favoritee' => 'user', 'uploader' => 'user', 'tag']); $prevPost = R::findOne('post', 'id < ? ORDER BY id DESC LIMIT 1', [$id]); $nextPost = R::findOne('post', 'id > ? ORDER BY id ASC LIMIT 1', [$id]); @@ -219,6 +266,12 @@ class PostController PrivilegesHelper::confirmWithException($this->context->user, Privilege::ViewPost); PrivilegesHelper::confirmWithException($this->context->user, Privilege::ViewPost, PostSafety::toString($post->safety)); + $favorite = false; + if ($this->context->loggedIn) + foreach ($post->ownFavoritee as $fav) + if ($fav->user->id == $this->context->user->id) + $favorite = true; + $dbQuery = R::$f->begin(); $dbQuery->select('tag.name, COUNT(1) AS count'); $dbQuery->from('tag'); @@ -234,9 +287,10 @@ class PostController $this->context->transport->tagDistribution[$row['name']] = $row['count']; $this->context->stylesheets []= 'post-view.css'; + $this->context->scripts []= 'post-view.js'; $this->context->subTitle = 'showing @' . $post->id; + $this->context->favorite = $favorite; $this->context->transport->post = $post; - $this->context->transport->uploader = R::load('user', $post->user_id); $this->context->transport->prevPostId = $prevPost ? $prevPost->id : null; $this->context->transport->nextPostId = $nextPost ? $nextPost->id : null; } @@ -250,10 +304,7 @@ class PostController public function thumbAction($id) { $this->context->layoutName = 'layout-file'; - - $post = R::findOne('post', 'id = ?', [$id]); - if (!$post) - throw new SimpleException('Invalid post ID "' . $id . '"'); + $post = self::locatePost($id); PrivilegesHelper::confirmWithException($this->context->user, Privilege::ViewPost); PrivilegesHelper::confirmWithException($this->context->user, Privilege::ViewPost, PostSafety::toString($post->safety)); @@ -324,10 +375,7 @@ class PostController public function retrieveAction($name) { $this->context->layoutName = 'layout-file'; - - $post = R::findOne('post', 'name = ?', [$name]); - if (!$post) - throw new SimpleException('Invalid post name "' . $name . '"'); + $post = self::locatePost($name); PrivilegesHelper::confirmWithException($this->context->user, Privilege::RetrievePost); PrivilegesHelper::confirmWithException($this->context->user, Privilege::RetrievePost, PostSafety::toString($post->safety)); @@ -354,4 +402,21 @@ class PostController $this->listAction('favmin:1', $page); $this->context->viewName = 'post-list'; } + + public static function locatePost($key) + { + if (is_numeric($key)) + { + $post = R::findOne('post', 'id = ?', [$key]); + if (!$post) + throw new SimpleException('Invalid post ID "' . $key . '"'); + } + else + { + $post = R::findOne('post', 'name = ?', [$key]); + if (!$post) + throw new SimpleException('Invalid post name "' . $key . '"'); + } + return $post; + } } diff --git a/src/Models/Model_User.php b/src/Models/Model_User.php new file mode 100644 index 00000000..1deb59ae --- /dev/null +++ b/src/Models/Model_User.php @@ -0,0 +1,13 @@ +email) + ? $this->email + : $this->name; + $hash = md5(strtolower(trim($subject))); + $url = 'http://www.gravatar.com/avatar/' . $hash . '?s=' . $size . '&d=retro'; + return $url; + } +} diff --git a/src/Models/Privilege.php b/src/Models/Privilege.php index fed7b6ac..4925e5d1 100644 --- a/src/Models/Privilege.php +++ b/src/Models/Privilege.php @@ -5,7 +5,8 @@ class Privilege extends Enum const UploadPost = 2; const ViewPost = 3; const RetrievePost = 4; - const ListUsers = 5; - const ListComments = 6; - const ListTags = 7; + const FavoritePost = 5; + const ListUsers = 6; + const ListComments = 7; + const ListTags = 8; } diff --git a/src/Views/post-view.phtml b/src/Views/post-view.phtml index d3790aab..1a1266ed 100644 --- a/src/Views/post-view.phtml +++ b/src/Views/post-view.phtml @@ -30,7 +30,7 @@ - + - +
diff --git a/src/core.php b/src/core.php index 51fc6eda..a6f5e5af 100644 --- a/src/core.php +++ b/src/core.php @@ -8,18 +8,32 @@ define('DS', DIRECTORY_SEPARATOR); function configFactory() { - $config = new \Chibi\Config(); - $configPaths = - [ - __DIR__ . DS . '../config.ini', - __DIR__ . DS . '../local.ini' - ]; - $configPaths = array_filter($configPaths, 'file_exists'); + static $config = null; - foreach ($configPaths as $path) + if ($config === null) { - $config->loadIni($path); - } + $config = new \Chibi\Config(); + $configPaths = + [ + __DIR__ . DS . '../config.ini', + __DIR__ . DS . '../local.ini' + ]; + $configPaths = array_filter($configPaths, 'file_exists'); + foreach ($configPaths as $path) + { + $config->loadIni($path); + } + + } return $config; } + +$config = configFactory(); +R::setup('sqlite:' . $config->main->dbPath); + +//wire models +\Chibi\AutoLoader::init([$config->chibi->userCodeDir, __DIR__]); +foreach (\Chibi\AutoLoader::getAllIncludablePaths() as $path) + if (preg_match('/Model/', $path)) + \Chibi\AutoLoader::safeInclude($path);