Closed #58
This commit is contained in:
parent
6fadc612fd
commit
5e30253789
10 changed files with 122 additions and 1 deletions
|
@ -75,6 +75,7 @@ hidePost.all=moderator
|
|||
deletePost.own=moderator
|
||||
deletePost.all=moderator
|
||||
featurePost=moderator
|
||||
scorePost=registered
|
||||
|
||||
listUsers=registered
|
||||
viewUser=registered
|
||||
|
|
|
@ -65,6 +65,10 @@ embed {
|
|||
color: #df4b0d;
|
||||
}
|
||||
|
||||
#sidebar .score .selected {
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
|
||||
i.icon-prev {
|
||||
background-position: -12px -1px;
|
||||
|
|
|
@ -550,6 +550,35 @@ class PostController
|
|||
|
||||
|
||||
|
||||
/**
|
||||
* @route /post/{id}/score/{score}
|
||||
* @validate score -1|0|1
|
||||
*/
|
||||
public function scoreAction($id, $score)
|
||||
{
|
||||
$post = Model_Post::locate($id);
|
||||
PrivilegesHelper::confirmWithException(Privilege::ScorePost);
|
||||
|
||||
if (InputHelper::get('submit'))
|
||||
{
|
||||
if (!$this->context->loggedIn)
|
||||
throw new SimpleException('Not logged in');
|
||||
|
||||
$p = R::findOne('post_score', 'post_id = ? AND user_id = ?', [$id, $this->context->user->id]);
|
||||
if (!$p)
|
||||
{
|
||||
$p = R::dispense('post_score');
|
||||
$p->post = $post;
|
||||
$p->user = $this->context->user;
|
||||
}
|
||||
$p->score = $score;
|
||||
R::store($p);
|
||||
$this->context->transport->success = true;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @route /post/{id}/feature
|
||||
*/
|
||||
|
@ -612,16 +641,24 @@ class PostController
|
|||
$nextPost = $nextPostQuery->get('row');
|
||||
|
||||
$favorite = false;
|
||||
$score = null;
|
||||
if ($this->context->loggedIn)
|
||||
{
|
||||
foreach ($post->ownFavoritee as $fav)
|
||||
if ($fav->user->id == $this->context->user->id)
|
||||
$favorite = true;
|
||||
|
||||
$s = R::findOne('post_score', 'post_id = ? AND user_id = ?', [$post->id, $this->context->user->id]);
|
||||
if ($s)
|
||||
$score = intval($s->score);
|
||||
}
|
||||
|
||||
$this->context->stylesheets []= 'post-view.css';
|
||||
$this->context->stylesheets []= 'comment-small.css';
|
||||
$this->context->scripts []= 'post-view.js';
|
||||
$this->context->subTitle = 'showing @' . $post->id . ' – ' . join(', ', array_map(function($x) { return $x['name']; }, $post->sharedTag));
|
||||
$this->context->favorite = $favorite;
|
||||
$this->context->score = $score;
|
||||
$this->context->transport->post = $post;
|
||||
$this->context->transport->prevPostId = $prevPost ? $prevPost['id'] : null;
|
||||
$this->context->transport->nextPostId = $nextPost ? $nextPost['id'] : null;
|
||||
|
|
|
@ -91,6 +91,16 @@ class Model_Post_QueryBuilder implements AbstractQueryBuilder
|
|||
$dbQuery->addSql('id <= ?')->put(intval($val));
|
||||
}
|
||||
|
||||
protected static function filterTokenScoreMin($dbQuery, $val)
|
||||
{
|
||||
$dbQuery->addSql('score >= ?')->put(intval($val));
|
||||
}
|
||||
|
||||
protected static function filterTokenScoreMax($dbQuery, $val)
|
||||
{
|
||||
$dbQuery->addSql('score <= ?')->put(intval($val));
|
||||
}
|
||||
|
||||
protected static function filterTokenTagMin($dbQuery, $val)
|
||||
{
|
||||
$dbQuery->addSql('tag_count >= ?')->put(intval($val));
|
||||
|
@ -273,6 +283,10 @@ class Model_Post_QueryBuilder implements AbstractQueryBuilder
|
|||
case 'favcount':
|
||||
$orderColumn = 'fav_count';
|
||||
break;
|
||||
case 'score':
|
||||
$orderDir *= -1;
|
||||
$orderColumn = 'score';
|
||||
break;
|
||||
case 'tag':
|
||||
case 'tags':
|
||||
case 'tagcount':
|
||||
|
|
|
@ -14,6 +14,7 @@ class Privilege extends Enum
|
|||
const HidePost = 9;
|
||||
const DeletePost = 10;
|
||||
const FeaturePost = 25;
|
||||
const ScorePost = 31;
|
||||
|
||||
const ListUsers = 11;
|
||||
const ViewUser = 12;
|
||||
|
|
30
src/Upgrades/Upgrade4.sql
Normal file
30
src/Upgrades/Upgrade4.sql
Normal file
|
@ -0,0 +1,30 @@
|
|||
ALTER TABLE post ADD COLUMN score INTEGER NOT NULL DEFAULT 0;
|
||||
|
||||
UPDATE post SET score = 0;
|
||||
|
||||
CREATE TABLE post_score
|
||||
(
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
post_id INTEGER,
|
||||
user_id INTEGER,
|
||||
score INTEGER,
|
||||
FOREIGN KEY(post_id) REFERENCES post(id) ON DELETE CASCADE ON UPDATE SET NULL,
|
||||
FOREIGN KEY(user_id) REFERENCES post(id) ON DELETE CASCADE ON UPDATE SET NULL
|
||||
);
|
||||
CREATE INDEX idx_fk_post_score_post_id ON post_score(post_id);
|
||||
CREATE INDEX idx_fk_post_score_user_id ON post_score(user_id);
|
||||
|
||||
CREATE TRIGGER post_score_update AFTER UPDATE ON post_score FOR EACH ROW
|
||||
BEGIN
|
||||
UPDATE post SET score = post.score - old.score + new.score WHERE post.id = new.post_id;
|
||||
END;
|
||||
|
||||
CREATE TRIGGER post_score_insert AFTER INSERT ON post_score FOR EACH ROW
|
||||
BEGIN
|
||||
UPDATE post SET score = post.score + new.score WHERE post.id = new.post_id;
|
||||
END;
|
||||
|
||||
CREATE TRIGGER post_score_delete BEFORE DELETE ON post_score FOR EACH ROW
|
||||
BEGIN
|
||||
UPDATE post SET score = post.score - old.score WHERE post.id = old.post_id;
|
||||
END;
|
|
@ -22,6 +22,7 @@
|
|||
<li>favorited by David: <a href="<?php echo \Chibi\UrlHelper::route('post', 'list', ['query' => 'fav:David']) ?>"><code>fav:David</code></a></li>
|
||||
<li>favorited by at least four users: <a href="<?php echo \Chibi\UrlHelper::route('post', 'list', ['query' => 'favmin:4']) ?>"><code>favmin:4</code></a></li>
|
||||
<li>commented by at least three users: <a href="<?php echo \Chibi\UrlHelper::route('post', 'list', ['query' => 'commentmin:3']) ?>"><code>commentmin:3</code></a></li>
|
||||
<li>having minimum score of 4: <a href="<?php echo \Chibi\UrlHelper::route('post', 'list', ['query' => 'scoremin:4']) ?>"><code>scoremin:4</code></a></li>
|
||||
<li>tagged with at least seven tags: <a href="<?php echo \Chibi\UrlHelper::route('post', 'list', ['query' => 'tagmin:7']) ?>"><code>tagmin:7</code></a></li>
|
||||
<li>exactly from the specified date: <a href="<?php echo \Chibi\UrlHelper::route('post', 'list', ['query' => 'date:2001']) ?>"><code>date:2001</code></a><span class="comma">, </span><a href="<?php echo \Chibi\UrlHelper::route('post', 'list', ['query' => 'date:2012-09-29']) ?>"><code>date:2012-09-29</code></a> (yyyy-mm-dd format)</li>
|
||||
<li>from the specified date onwards: <a href="<?php echo \Chibi\UrlHelper::route('post', 'list', ['query' => 'datemin:2001-01-01']) ?>"><code>datemin:2001-01-01</code></a></li>
|
||||
|
@ -40,7 +41,8 @@
|
|||
<li>newest to oldest: <a href="<?php echo \Chibi\UrlHelper::route('post', 'list', ['query' => 'order:date']) ?>"><code>order:date</code></a> (pretty much default browse view)</li>
|
||||
<li>oldest to newest: <a href="<?php echo \Chibi\UrlHelper::route('post', 'list', ['query' => '-order:date']) ?>"><code>-order:date</code></a></li>
|
||||
<li>most commented first: <a href="<?php echo \Chibi\UrlHelper::route('post', 'list', ['query' => 'order:comments']) ?>"><code>order:comments</code></a></li>
|
||||
<li>loved by most: <a href="<?php echo \Chibi\UrlHelper::route('post', 'list', ['query' => 'order:favs']) ?>"><code>order:favs</code></a></li>
|
||||
<li>loved by most: <a href="<?php echo \Chibi\UrlHelper::route('post', 'list', ['query' => 'order:favs']) ?>"><code>order:favs</code></a></li>
|
||||
<li>highest scored: <a href="<?php echo \Chibi\UrlHelper::route('post', 'list', ['query' => 'order:score']) ?>"><code>order:score</code></a></li>
|
||||
</ul>
|
||||
|
||||
<p>As shown with <a href="<?php echo \Chibi\UrlHelper::route('post', 'list', ['query' => '-order:date']) ?>"><code>-order:date</code></a><span class="comma">, </span>any of them can be reversed in the same way as negating other tags: by placing a dash before the tag.</p>
|
||||
|
|
|
@ -70,6 +70,36 @@
|
|||
</span>
|
||||
</div>
|
||||
|
||||
<div class="key-value score">
|
||||
<span class="key">Score:</span>
|
||||
<span class="value">
|
||||
<?php echo $this->context->transport->post->score ?>
|
||||
|
||||
<?php if (PrivilegesHelper::confirm(Privilege::ScorePost)): ?>
|
||||
[
|
||||
<?php $scoreLink = \Chibi\UrlHelper::route('post', 'score', ['id' => $this->context->transport->post->id, 'score' => '{score}']) ?>
|
||||
|
||||
<?php if ($this->context->score === 1): ?>
|
||||
<a class="simple-action selected" href="<?php echo TextHelper::replaceTokens($scoreLink, ['score' => 0]) ?>">
|
||||
<?php else: ?>
|
||||
<a class="simple-action" href="<?php echo TextHelper::replaceTokens($scoreLink, ['score' => 1]) ?>">
|
||||
<?php endif ?>
|
||||
up
|
||||
</a>
|
||||
|
||||
|
|
||||
|
||||
<?php if ($this->context->score === -1): ?>
|
||||
<a class="simple-action selected" href="<?php echo TextHelper::replaceTokens($scoreLink, ['score' => 0]) ?>">
|
||||
<?php else: ?>
|
||||
<a class="simple-action" href="<?php echo TextHelper::replaceTokens($scoreLink, ['score' => -1]) ?>">
|
||||
<?php endif ?>
|
||||
down
|
||||
</a>]
|
||||
<?php endif ?>
|
||||
</span>
|
||||
</div>
|
||||
|
||||
<div class="key-value date">
|
||||
<span class="key">Date:</span>
|
||||
<span class="value" title="<?php echo $val = date('Y-m-d H:i', $this->context->transport->post->upload_date) ?>">
|
||||
|
|
|
@ -48,6 +48,7 @@ $config = configFactory();
|
|||
R::setup('sqlite:' . $config->main->dbPath);
|
||||
R::freeze(true);
|
||||
R::dependencies(['tag' => ['post'], 'favoritee' => ['post', 'user'], 'comment' => ['post', 'user']]);
|
||||
R::setStrictTyping(false);
|
||||
|
||||
//wire models
|
||||
\Chibi\AutoLoader::init([__DIR__ . '/../' . $config->chibi->userCodeDir, __DIR__]);
|
||||
|
|
|
@ -17,6 +17,7 @@ foreach ($upgrades as $upgradePath)
|
|||
{
|
||||
printf('Executing %s...' . PHP_EOL, $upgradePath);
|
||||
$upgradeSql = file_get_contents($upgradePath);
|
||||
$upgradeSql = preg_replace('/^[ \t]+(.*);/m', '\0--', $upgradeSql);
|
||||
$queries = preg_split('/;\s*[\r\n]+/s', $upgradeSql);
|
||||
$queries = array_map('trim', $queries);
|
||||
foreach ($queries as $query)
|
||||
|
|
Loading…
Reference in a new issue