Favorites; gravatar support

This commit is contained in:
Marcin Kurczewski 2013-10-12 14:53:47 +02:00
parent 67dcc7c4f8
commit 7c5d1b7e34
10 changed files with 244 additions and 39 deletions

View file

@ -44,6 +44,7 @@ listPosts=anonymous
listPosts.sketchy=registered listPosts.sketchy=registered
listPosts.unsafe=registered listPosts.unsafe=registered
listUsers=registered listUsers=registered
favoritePost=registered
listComments=registered listComments=registered
retrievePost=anonymous retrievePost=anonymous
listTags=anonymous listTags=anonymous

View file

@ -87,8 +87,8 @@ body {
} }
#sidebar .sidebar-unit { #sidebar .sidebar-unit {
margin: 0 0 2em 0; margin: 0 0 1.5em 0;
padding: 1em; padding: 0.75em;
border: 1px solid #eee; border: 1px solid #eee;
padding-left: 0; padding-left: 0;
border-left: 0; border-left: 0;

View file

@ -1,5 +1,7 @@
#sidebar { #sidebar {
width: 200px; width: 200px;
line-height: 1.33em;
font-size: 90%;
} }
.post-wrapper { .post-wrapper {
@ -71,9 +73,24 @@ i.icon-dl {
content: ', '; content: ', ';
} }
.details {
line-height: 1.33em;
}
.details .key { .details .key {
margin-right: 0.5em; 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;
}

View file

@ -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();
}
});
});
});

View file

@ -24,7 +24,6 @@ class Bootstrap
public function workWrapper($workCallback) public function workWrapper($workCallback)
{ {
$this->config->chibi->baseUrl = 'http://' . rtrim($_SERVER['HTTP_HOST'], '/') . '/'; $this->config->chibi->baseUrl = 'http://' . rtrim($_SERVER['HTTP_HOST'], '/') . '/';
R::setup('sqlite:' . $this->config->main->dbPath);
session_start(); session_start();
$this->context->title = $this->config->main->title; $this->context->title = $this->config->main->title;

View file

@ -188,10 +188,11 @@ class PostController
$dbPost->mime_type = $mimeType; $dbPost->mime_type = $mimeType;
$dbPost->safety = $suppliedSafety; $dbPost->safety = $suppliedSafety;
$dbPost->upload_date = time(); $dbPost->upload_date = time();
$dbPost->sharedTag = $dbTags;
$dbPost->user = $this->context->user;
$dbPost->image_width = $imageWidth; $dbPost->image_width = $imageWidth;
$dbPost->image_height = $imageHeight; $dbPost->image_height = $imageHeight;
$dbPost->uploader = $this->context->user;
$dbPost->ownFavoritee = [];
$dbPost->sharedTag = $dbTags;
move_uploaded_file($suppliedFile['tmp_name'], $path); move_uploaded_file($suppliedFile['tmp_name'], $path);
R::store($dbPost); 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) public function viewAction($id)
{ {
$post = R::findOne('post', 'id = ?', [$id]); $post = self::locatePost($id);
if (!$post) R::preload($post, ['favoritee' => 'user', 'uploader' => 'user', 'tag']);
throw new SimpleException('Invalid post ID "' . $id . '"');
R::preload($post, ['user', 'tag']);
$prevPost = R::findOne('post', 'id < ? ORDER BY id DESC LIMIT 1', [$id]); $prevPost = R::findOne('post', 'id < ? ORDER BY id DESC LIMIT 1', [$id]);
$nextPost = R::findOne('post', 'id > ? ORDER BY id ASC 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);
PrivilegesHelper::confirmWithException($this->context->user, Privilege::ViewPost, PostSafety::toString($post->safety)); 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 = R::$f->begin();
$dbQuery->select('tag.name, COUNT(1) AS count'); $dbQuery->select('tag.name, COUNT(1) AS count');
$dbQuery->from('tag'); $dbQuery->from('tag');
@ -234,9 +287,10 @@ class PostController
$this->context->transport->tagDistribution[$row['name']] = $row['count']; $this->context->transport->tagDistribution[$row['name']] = $row['count'];
$this->context->stylesheets []= 'post-view.css'; $this->context->stylesheets []= 'post-view.css';
$this->context->scripts []= 'post-view.js';
$this->context->subTitle = 'showing @' . $post->id; $this->context->subTitle = 'showing @' . $post->id;
$this->context->favorite = $favorite;
$this->context->transport->post = $post; $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->prevPostId = $prevPost ? $prevPost->id : null;
$this->context->transport->nextPostId = $nextPost ? $nextPost->id : null; $this->context->transport->nextPostId = $nextPost ? $nextPost->id : null;
} }
@ -250,10 +304,7 @@ class PostController
public function thumbAction($id) public function thumbAction($id)
{ {
$this->context->layoutName = 'layout-file'; $this->context->layoutName = 'layout-file';
$post = self::locatePost($id);
$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);
PrivilegesHelper::confirmWithException($this->context->user, Privilege::ViewPost, PostSafety::toString($post->safety)); PrivilegesHelper::confirmWithException($this->context->user, Privilege::ViewPost, PostSafety::toString($post->safety));
@ -324,10 +375,7 @@ class PostController
public function retrieveAction($name) public function retrieveAction($name)
{ {
$this->context->layoutName = 'layout-file'; $this->context->layoutName = 'layout-file';
$post = self::locatePost($name);
$post = R::findOne('post', 'name = ?', [$name]);
if (!$post)
throw new SimpleException('Invalid post name "' . $name . '"');
PrivilegesHelper::confirmWithException($this->context->user, Privilege::RetrievePost); PrivilegesHelper::confirmWithException($this->context->user, Privilege::RetrievePost);
PrivilegesHelper::confirmWithException($this->context->user, Privilege::RetrievePost, PostSafety::toString($post->safety)); PrivilegesHelper::confirmWithException($this->context->user, Privilege::RetrievePost, PostSafety::toString($post->safety));
@ -354,4 +402,21 @@ class PostController
$this->listAction('favmin:1', $page); $this->listAction('favmin:1', $page);
$this->context->viewName = 'post-list'; $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;
}
} }

13
src/Models/Model_User.php Normal file
View file

@ -0,0 +1,13 @@
<?php
class Model_User extends RedBean_SimpleModel
{
public function avatarUrl($size = 32)
{
$subject = !empty($this->email)
? $this->email
: $this->name;
$hash = md5(strtolower(trim($subject)));
$url = 'http://www.gravatar.com/avatar/' . $hash . '?s=' . $size . '&d=retro';
return $url;
}
}

View file

@ -5,7 +5,8 @@ class Privilege extends Enum
const UploadPost = 2; const UploadPost = 2;
const ViewPost = 3; const ViewPost = 3;
const RetrievePost = 4; const RetrievePost = 4;
const ListUsers = 5; const FavoritePost = 5;
const ListComments = 6; const ListUsers = 6;
const ListTags = 7; const ListComments = 7;
const ListTags = 8;
} }

View file

@ -30,7 +30,7 @@
</nav> </nav>
<div class="sidebar-unit tags"> <div class="sidebar-unit tags">
<h1>tags</h1> <h1>tags (<?php echo count($this->context->transport->post->sharedTag) ?>)</h1>
<!-- todo: edit tags --> <!-- todo: edit tags -->
<ul> <ul>
<?php foreach ($this->context->transport->post->sharedTag as $tag): ?> <?php foreach ($this->context->transport->post->sharedTag as $tag): ?>
@ -57,8 +57,8 @@
<div class="uploader"> <div class="uploader">
<span class="key">Uploader:</span> <span class="key">Uploader:</span>
<span class="value"> <span class="value">
<a href="<?php echo \Chibi\UrlHelper::route('user', 'view', ['id' => $this->context->transport->post->user->id]) ?>"> <a href="<?php echo \Chibi\UrlHelper::route('user', 'view', ['name' => $this->context->transport->post->uploader->id]) ?>">
<?php echo $this->context->transport->post->user->name ?> <?php echo $this->context->transport->post->uploader->name ?>
</a> </a>
</span> </span>
</div> </div>
@ -90,9 +90,84 @@
</div> </div>
</div> </div>
<!-- todo: favorites --> <div class="sidebar-unit favorites">
<?php if (count($this->context->transport->post->ownFavoritee) == 0): ?>
<h1>favorites</h1>
<p>None yet.</p>
<?php else: ?>
<h1>favorites (<?php echo count($this->context->transport->post->ownFavoritee) ?>)</h1>
<ul>
<?php foreach ($this->context->transport->post->via('favoritee')->sharedUser as $user): ?>
<li>
<a href="<?php echo \Chibi\UrlHelper::route('user', 'view', ['name' => $user->name]) ?>">
<img src="<?php echo $user->avatarUrl() ?>" alt="<?php echo $user->name ?>">
</a>
</li>
<?php endforeach ?>
</ul>
<?php endif ?>
</div>
<!-- todo: control --> <div class="sidebar-unit options">
<h1>options</h1>
<nav>
<ul>
<?php if (PrivilegesHelper::confirm($this->context->user, Privilege::FavoritePost)): ?>
<?php if (!$this->context->favorite): ?>
<li class="add-fav">
<a href="<?php echo \Chibi\UrlHelper::route('post', 'add-favorite', ['id' => $this->context->transport->post->id]) ?>">
Add to favorites
</a>
</li>
<?php else: ?>
<li class="rem-fav">
<a href="<?php echo \Chibi\UrlHelper::route('post', 'rem-favorite', ['id' => $this->context->transport->post->id]) ?>">
Remove from favorites
</a>
</li>
<?php endif ?>
<?php endif ?>
<!--
<li>
<a href="#">
Edit tags
</a>
</li>
<li>
<a href="#">
Change safety
</a>
</li>
<li>
<a href="#">
Show on main page
</a>
</li>
<li>
<a href="#">
Hide from main page
</a>
</li>
<li>
<a href="#">
Remove
</a>
</li>
-->
</ul>
</nav>
<script type="text/javascript">
if (!$('.options ul li').length)
$('.options').hide();
</script>
</div>
</div> </div>
<div id="inner-content"> <div id="inner-content">

View file

@ -8,18 +8,32 @@ define('DS', DIRECTORY_SEPARATOR);
function configFactory() function configFactory()
{ {
$config = new \Chibi\Config(); static $config = null;
$configPaths =
[
__DIR__ . DS . '../config.ini',
__DIR__ . DS . '../local.ini'
];
$configPaths = array_filter($configPaths, 'file_exists');
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; 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);