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.own=moderator
|
||||||
deletePost.all=moderator
|
deletePost.all=moderator
|
||||||
featurePost=moderator
|
featurePost=moderator
|
||||||
|
scorePost=registered
|
||||||
|
|
||||||
listUsers=registered
|
listUsers=registered
|
||||||
viewUser=registered
|
viewUser=registered
|
||||||
|
|
|
@ -65,6 +65,10 @@ embed {
|
||||||
color: #df4b0d;
|
color: #df4b0d;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#sidebar .score .selected {
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
i.icon-prev {
|
i.icon-prev {
|
||||||
background-position: -12px -1px;
|
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
|
* @route /post/{id}/feature
|
||||||
*/
|
*/
|
||||||
|
@ -612,16 +641,24 @@ class PostController
|
||||||
$nextPost = $nextPostQuery->get('row');
|
$nextPost = $nextPostQuery->get('row');
|
||||||
|
|
||||||
$favorite = false;
|
$favorite = false;
|
||||||
|
$score = null;
|
||||||
if ($this->context->loggedIn)
|
if ($this->context->loggedIn)
|
||||||
|
{
|
||||||
foreach ($post->ownFavoritee as $fav)
|
foreach ($post->ownFavoritee as $fav)
|
||||||
if ($fav->user->id == $this->context->user->id)
|
if ($fav->user->id == $this->context->user->id)
|
||||||
$favorite = true;
|
$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 []= 'post-view.css';
|
||||||
$this->context->stylesheets []= 'comment-small.css';
|
$this->context->stylesheets []= 'comment-small.css';
|
||||||
$this->context->scripts []= 'post-view.js';
|
$this->context->scripts []= 'post-view.js';
|
||||||
$this->context->subTitle = 'showing @' . $post->id . ' – ' . join(', ', array_map(function($x) { return $x['name']; }, $post->sharedTag));
|
$this->context->subTitle = 'showing @' . $post->id . ' – ' . join(', ', array_map(function($x) { return $x['name']; }, $post->sharedTag));
|
||||||
$this->context->favorite = $favorite;
|
$this->context->favorite = $favorite;
|
||||||
|
$this->context->score = $score;
|
||||||
$this->context->transport->post = $post;
|
$this->context->transport->post = $post;
|
||||||
$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;
|
||||||
|
|
|
@ -91,6 +91,16 @@ class Model_Post_QueryBuilder implements AbstractQueryBuilder
|
||||||
$dbQuery->addSql('id <= ?')->put(intval($val));
|
$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)
|
protected static function filterTokenTagMin($dbQuery, $val)
|
||||||
{
|
{
|
||||||
$dbQuery->addSql('tag_count >= ?')->put(intval($val));
|
$dbQuery->addSql('tag_count >= ?')->put(intval($val));
|
||||||
|
@ -273,6 +283,10 @@ class Model_Post_QueryBuilder implements AbstractQueryBuilder
|
||||||
case 'favcount':
|
case 'favcount':
|
||||||
$orderColumn = 'fav_count';
|
$orderColumn = 'fav_count';
|
||||||
break;
|
break;
|
||||||
|
case 'score':
|
||||||
|
$orderDir *= -1;
|
||||||
|
$orderColumn = 'score';
|
||||||
|
break;
|
||||||
case 'tag':
|
case 'tag':
|
||||||
case 'tags':
|
case 'tags':
|
||||||
case 'tagcount':
|
case 'tagcount':
|
||||||
|
|
|
@ -14,6 +14,7 @@ class Privilege extends Enum
|
||||||
const HidePost = 9;
|
const HidePost = 9;
|
||||||
const DeletePost = 10;
|
const DeletePost = 10;
|
||||||
const FeaturePost = 25;
|
const FeaturePost = 25;
|
||||||
|
const ScorePost = 31;
|
||||||
|
|
||||||
const ListUsers = 11;
|
const ListUsers = 11;
|
||||||
const ViewUser = 12;
|
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 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>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>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>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>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>
|
<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>
|
||||||
|
@ -41,6 +42,7 @@
|
||||||
<li>oldest to newest: <a href="<?php echo \Chibi\UrlHelper::route('post', 'list', ['query' => '-order:date']) ?>"><code>-order:date</code></a></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>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>
|
</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>
|
<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>
|
</span>
|
||||||
</div>
|
</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">
|
<div class="key-value date">
|
||||||
<span class="key">Date:</span>
|
<span class="key">Date:</span>
|
||||||
<span class="value" title="<?php echo $val = date('Y-m-d H:i', $this->context->transport->post->upload_date) ?>">
|
<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::setup('sqlite:' . $config->main->dbPath);
|
||||||
R::freeze(true);
|
R::freeze(true);
|
||||||
R::dependencies(['tag' => ['post'], 'favoritee' => ['post', 'user'], 'comment' => ['post', 'user']]);
|
R::dependencies(['tag' => ['post'], 'favoritee' => ['post', 'user'], 'comment' => ['post', 'user']]);
|
||||||
|
R::setStrictTyping(false);
|
||||||
|
|
||||||
//wire models
|
//wire models
|
||||||
\Chibi\AutoLoader::init([__DIR__ . '/../' . $config->chibi->userCodeDir, __DIR__]);
|
\Chibi\AutoLoader::init([__DIR__ . '/../' . $config->chibi->userCodeDir, __DIR__]);
|
||||||
|
|
|
@ -17,6 +17,7 @@ foreach ($upgrades as $upgradePath)
|
||||||
{
|
{
|
||||||
printf('Executing %s...' . PHP_EOL, $upgradePath);
|
printf('Executing %s...' . PHP_EOL, $upgradePath);
|
||||||
$upgradeSql = file_get_contents($upgradePath);
|
$upgradeSql = file_get_contents($upgradePath);
|
||||||
|
$upgradeSql = preg_replace('/^[ \t]+(.*);/m', '\0--', $upgradeSql);
|
||||||
$queries = preg_split('/;\s*[\r\n]+/s', $upgradeSql);
|
$queries = preg_split('/;\s*[\r\n]+/s', $upgradeSql);
|
||||||
$queries = array_map('trim', $queries);
|
$queries = array_map('trim', $queries);
|
||||||
foreach ($queries as $query)
|
foreach ($queries as $query)
|
||||||
|
|
Loading…
Reference in a new issue