Fully enabled tag subscriptions.
This commit is contained in:
parent
1bd69c151e
commit
827072db46
63
app/controllers/TagSubscriptionController.php
Executable file
63
app/controllers/TagSubscriptionController.php
Executable file
@ -0,0 +1,63 @@
|
||||
<?php
|
||||
class TagSubscriptionController extends ApplicationController
|
||||
{
|
||||
protected function filters()
|
||||
{
|
||||
return [
|
||||
'before' => [
|
||||
'member_only' => ['except' => ['index']],
|
||||
'no_anonymous'
|
||||
]
|
||||
];
|
||||
}
|
||||
|
||||
public function create()
|
||||
{
|
||||
$this->response()->headers()->setContentType('text/javascript');
|
||||
$this->setLayout(false);
|
||||
|
||||
if ($this->request()->isPost()) {
|
||||
if (current_user()->tag_subscriptions->size() >= CONFIG()->max_tag_subscriptions) {
|
||||
$this->tag_subscription = null;
|
||||
} else {
|
||||
$this->tag_subscription = TagSubscription::create(['user_id' => current_user()->id, 'tag_query' => '']);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public function update()
|
||||
{
|
||||
if ($this->request()->isPost()) {
|
||||
if (is_array($this->params()->tag_subscription)) {
|
||||
foreach ($this->params()->tag_subscription as $tag_subscription_id => $ts) {
|
||||
$tag_subscription = TagSubscription::find($tag_subscription_id);
|
||||
if ($tag_subscription->user_id == current_user()->id) {
|
||||
$tag_subscription->updateAttributes($ts);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$this->notice("Tag subscriptions updated");
|
||||
$this->redirectTo('user#edit');
|
||||
}
|
||||
|
||||
public function index()
|
||||
{
|
||||
$this->tag_subscriptions = current_user()->tag_subscriptions;
|
||||
}
|
||||
|
||||
public function destroy()
|
||||
{
|
||||
$this->response()->headers()->setContentType('text/javascript');
|
||||
$this->setLayout(false);
|
||||
|
||||
if ($this->request()->isPost()) {
|
||||
$this->tag_subscription = TagSubscription::find($this->params()->id);
|
||||
|
||||
if (current_user()->has_permission($this->tag_subscription)) {
|
||||
$this->tag_subscription->destroy();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
20
app/helpers/TagSubscriptionHelper.php
Executable file
20
app/helpers/TagSubscriptionHelper.php
Executable file
@ -0,0 +1,20 @@
|
||||
<?php
|
||||
class TagSubscriptionHelper extends Rails\ActionView\Helper
|
||||
{
|
||||
public function tag_subscription_listing($user)
|
||||
{
|
||||
$html = [];
|
||||
foreach ($user->tag_subscriptions as $tag_subscription) {
|
||||
$h = '<span class="group"><strong>' . $this->linkTo($tag_subscription->name, ["post#", 'tags' => "sub:" . $user->name . ":" . $tag_subscription->name]) . "</strong>:";
|
||||
$tags = preg_split('/\s+/', $tag_subscription->tag_query);
|
||||
sort($tags);
|
||||
$group = [];
|
||||
foreach ($tags as $tag) {
|
||||
$group[] = $this->linkTo($tag, ['post#', 'tags' => $tag]);
|
||||
}
|
||||
$h .= join(' ', $group);
|
||||
$html[] = $h;
|
||||
}
|
||||
return join(' ', $html);
|
||||
}
|
||||
}
|
@ -42,9 +42,9 @@ class JobTask extends Rails\ActiveRecord\Base
|
||||
return "start: " . $ti->predicate->name . ", result: " . $ti->consequent->name;
|
||||
break;
|
||||
|
||||
// case "calculate_tag_subscriptions"
|
||||
// last_run = data["last_run"]
|
||||
// "last run:#{last_run}"
|
||||
case "calculate_tag_subscriptions":
|
||||
return "last run: " . $this->data->last_run;
|
||||
break;
|
||||
|
||||
// case "upload_posts_to_mirrors"
|
||||
// ret = ""
|
||||
@ -255,6 +255,16 @@ class JobTask extends Rails\ActiveRecord\Base
|
||||
$ti->approve($updater_id, $updater_ip_addr);
|
||||
}
|
||||
|
||||
public function execute_calculate_tag_subscriptions()
|
||||
{
|
||||
if (Rails::cache()->read("delay-tag-sub-calc")) {
|
||||
return;
|
||||
}
|
||||
Rails::cache()->write("delay-tag-sub-calc", ['expires_in' => '360 minutes']);
|
||||
TagSubscription::process_all();
|
||||
$this->updateAttributes(['data' => ['last_run' => date('Y-m-d H:i')]]);
|
||||
}
|
||||
|
||||
protected function init()
|
||||
{
|
||||
$this->setData($this->data_as_json ? json_decode($this->data_as_json) : new stdClass());
|
||||
|
@ -164,18 +164,19 @@ trait PostSqlMethods
|
||||
$cond_params[] = $q['source'];
|
||||
}
|
||||
|
||||
// if (is_string($q['subscriptions'])) {
|
||||
// preg_match('/^(.+?):(.+)$/', $q['subscriptions'], $m);
|
||||
// $username = $m[1] || $q['subscriptions'];
|
||||
// $subscription_name = $m[2];
|
||||
// $user = new User('find_by_name', $username);
|
||||
if (isset($q['subscriptions'])) {
|
||||
preg_match('/^(.+?):(.+)$/', $q['subscriptions'], $m);
|
||||
$username = $m[1] ?: $q['subscriptions'];
|
||||
$subscription_name = $m[2];
|
||||
$user = User::find_by_name($username);
|
||||
|
||||
// if ($user) {
|
||||
// $paramsost_ids = TagSubscription.find_post_ids(user.id, subscription_name)
|
||||
// $conds[] = "p.id IN (?)"
|
||||
// $cond_params[] = post_ids
|
||||
// }
|
||||
// }
|
||||
if ($user) {
|
||||
if ($post_ids = TagSubscription::find_post_ids($user->id, $subscription_name)) {
|
||||
$conds[] = 'p.id IN (?)';
|
||||
$cond_params[] = $post_ids;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (is_string($q['fav'])) {
|
||||
$joins[] = "JOIN favorites f ON f.post_id = p.id JOIN users fu ON f.user_id = fu.id";
|
||||
|
112
app/models/TagSubscription.php
Executable file
112
app/models/TagSubscription.php
Executable file
@ -0,0 +1,112 @@
|
||||
<?php
|
||||
class TagSubscription extends Rails\ActiveRecord\Base
|
||||
{
|
||||
protected function associations()
|
||||
{
|
||||
return [
|
||||
'belongs_to' => [
|
||||
'user'
|
||||
]
|
||||
];
|
||||
}
|
||||
|
||||
protected function callbacks()
|
||||
{
|
||||
return [
|
||||
'before_save' => [
|
||||
'normalize_name'
|
||||
],
|
||||
'before_create' => [
|
||||
'initialize_post_ids'
|
||||
]
|
||||
];
|
||||
}
|
||||
|
||||
protected function scopes()
|
||||
{
|
||||
return [
|
||||
'visible' => function() {
|
||||
$this->where(['is_visible_on_profile' => true]);
|
||||
}
|
||||
];
|
||||
}
|
||||
|
||||
public function normalize_name()
|
||||
{
|
||||
/**
|
||||
* MI: \P{Word} doesn't exist in PHP so I used \P{L}, which matches a single letter.
|
||||
* In order for \P{L} to work, I had to use mb_conver_encoding
|
||||
* which splits a single mb character into two, thus the second replace.
|
||||
*/
|
||||
$this->name = preg_replace(['/\P{L}/', '/_{2,}/'], '_', mb_convert_encoding($this->name, 'ISO-8859-2'));
|
||||
}
|
||||
|
||||
public function initialize_post_ids()
|
||||
{
|
||||
if ($this->user->is_privileged_or_higher()) {
|
||||
$this->cached_post_ids = join(',', array_unique(Post::find_by_tags($this->tag_query, ['limit' => ceil(CONFIG()->tag_subscription_post_limit / 3), 'select' => 'p.id', 'order' => 'p.id desc'])->getAttributes('id')));
|
||||
}
|
||||
}
|
||||
|
||||
static public function find_post_ids($user_id, $name = null, $limit = null)
|
||||
{
|
||||
if (!$limit) {
|
||||
$limit = CONFIG()->tag_subscription_post_limit;
|
||||
}
|
||||
|
||||
$post_ids = self::select('cached_post_ids')->where(['user_id' => $user_id]);
|
||||
if ($name) {
|
||||
$post_ids->where('name LIKE ?', $name . '%');
|
||||
}
|
||||
$post_ids = $post_ids->take();
|
||||
|
||||
$parsed_ids = [];
|
||||
foreach ($post_ids as $subs) {
|
||||
$ids = explode(',', $subs->cached_post_ids);
|
||||
foreach ($ids as &$id) {
|
||||
$id = (int)$id;
|
||||
}
|
||||
$parsed_ids = array_merge($parsed_ids, $ids);
|
||||
}
|
||||
sort($parsed_ids);
|
||||
|
||||
return array_slice(array_reverse(array_unique($parsed_ids)), 0, $limit);
|
||||
}
|
||||
|
||||
static public function find_posts($user_id, $name = null, $limit = null)
|
||||
{
|
||||
return Post::available()->where('id IN (?)', self::find_post_ids($user_id, $name, $limit))->order('id DESC')->take();
|
||||
}
|
||||
|
||||
static public function process_all()
|
||||
{
|
||||
foreach (self::all() as $tag_subscription) {
|
||||
if ($tag_subscription->user->is_privileged_or_higher()) {
|
||||
try {
|
||||
self::transaction(function() use ($tag_subscription) {
|
||||
$tags = preg_split('/\s+/', $tag_subscription->tag_query);
|
||||
$post_ids = [];
|
||||
foreach ($tags as $tag) {
|
||||
$post_ids = array_merge(
|
||||
$post_ids,
|
||||
Post::find_by_tags(
|
||||
$tag,
|
||||
[
|
||||
'limit' => ceil(CONFIG()->tag_subscription_post_limit / 3),
|
||||
'select' => 'p.id',
|
||||
'order' => 'p.id desc'
|
||||
]
|
||||
)->getAttributes('id')
|
||||
);
|
||||
}
|
||||
sort($post_ids);
|
||||
$tag_subscription->updateAttribute('cached_post_ids', join(',', array_unique(array_slice(array_reverse($post_ids), 0, CONFIG()->tag_subscription_post_limit))));
|
||||
});
|
||||
} catch (Exception $e) {
|
||||
# fail silently
|
||||
}
|
||||
sleep(1);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -18,11 +18,6 @@ class User extends Rails\ActiveRecord\Base
|
||||
*/
|
||||
public $ip_addr;
|
||||
|
||||
/**
|
||||
* iTODO: Temp property while tag subs aren't enabled.
|
||||
*/
|
||||
public $tag_subscriptions;
|
||||
|
||||
protected $post_count;
|
||||
|
||||
static public function set_current_user(User $user)
|
||||
@ -638,9 +633,10 @@ class User extends Rails\ActiveRecord\Base
|
||||
// tag_subscriptions_text.map(&:tag_query).sort.join(" ")
|
||||
// end
|
||||
|
||||
// def tag_subscription_posts(limit, name)
|
||||
// TagSubscription.find_posts(id, name, limit)
|
||||
// end
|
||||
public function tag_subscription_posts($limit, $name)
|
||||
{
|
||||
return TagSubscription::find_posts($this->id, $name, $limit);
|
||||
}
|
||||
# }
|
||||
|
||||
# UserLanguageMethods {
|
||||
|
24
app/views/tag_subscription/_listing.php
Executable file
24
app/views/tag_subscription/_listing.php
Executable file
@ -0,0 +1,24 @@
|
||||
<thead>
|
||||
<tr>
|
||||
<th></th>
|
||||
<th width="15%"><?=$this->t('sub_name') ?></th>
|
||||
<th width="70%"><?=$this->t('sub_tags') ?></th>
|
||||
<th width="10%"><?=$this->t('sub_vis') ?></th>
|
||||
</tr>
|
||||
</thead>
|
||||
|
||||
<tfoot>
|
||||
<tr>
|
||||
<td></td>
|
||||
<td colspan="3">
|
||||
<?= $this->submitTag($this->t('sub_save')) ?>
|
||||
<input onclick="new Ajax.Request('<?= $this->urlFor(['tag_subscription#create', 'format' => 'js']) ?>', {asynchronous:true, evalScripts:true});" type="button" value="<?= $this->t('sub_add') ?>">
|
||||
</td>
|
||||
</tr>
|
||||
</tfoot>
|
||||
|
||||
<tbody id="tag-subscription-body">
|
||||
<?php foreach ($this->tag_subscriptions as $tag_subscription) : ?>
|
||||
<?= $this->partial("listing_row", ['tag_subscription' => $tag_subscription]) ?>
|
||||
<?php endforeach ?>
|
||||
</tbody>
|
8
app/views/tag_subscription/_listing_row.php
Executable file
8
app/views/tag_subscription/_listing_row.php
Executable file
@ -0,0 +1,8 @@
|
||||
<tr id="tag-subscription-row-<?= $this->tag_subscription->id ?>">
|
||||
<td><input onclick="new Ajax.Request('<?= $this->urlFor(['tag_subscription#destroy', 'id' => $this->tag_subscription->id, 'format' => 'js']) ?>', {asynchronous:true, evalScripts:true});" type="button" value="<?= '-' ?>"></td>
|
||||
<td><?= $this->textFieldTag("tag_subscription[".$this->tag_subscription->id."][name]", $this->tag_subscription->name, ['size' => 20]) ?></td>
|
||||
<td><?= $this->textFieldTag("tag_subscription[".$this->tag_subscription->id."][tag_query]", $this->tag_subscription->tag_query, ['size' => 70]) ?></td>
|
||||
<td>
|
||||
<?= $this->selectTag("tag_subscription[".$this->tag_subscription->id."][is_visible_on_profile]", $this->optionsForSelect(["Visible" => 1, "Hidden" => 0], $this->tag_subscription->is_visible_on_profile)) ?>
|
||||
</td>
|
||||
</tr>
|
@ -1,7 +1,7 @@
|
||||
<?php if (empty($this->user->tag_subscriptions)) : ?>
|
||||
<?php if ($this->user->tag_subscriptions->none()) : ?>
|
||||
<?= $this->t('sub_none') ?>
|
||||
<?php else: ?>
|
||||
<?= $this->tag_subscription_listing($user) ?>
|
||||
<?= $this->tag_subscription_listing($this->user) ?>
|
||||
<?php endif ?>
|
||||
|
||||
<?php if (current_user()->id == $this->user->id) : ?>
|
||||
|
5
app/views/tag_subscription/create.js.php
Executable file
5
app/views/tag_subscription/create.js.php
Executable file
@ -0,0 +1,5 @@
|
||||
<?php if ($this->tag_subscription) : ?>
|
||||
$('tag-subscription-body').insert({ bottom: '<?= $this->escapeJavascript($this->partial('listing_row', ['tag_subscription' => $this->tag_subscription])) ?>'});
|
||||
<?php else: ?>
|
||||
notice('<?= "You can only create up to " . CONFIG()->max_tag_subscriptions . " tag subscriptions" ?>');
|
||||
<?php endif ?>
|
2
app/views/tag_subscription/destroy.js.php
Executable file
2
app/views/tag_subscription/destroy.js.php
Executable file
@ -0,0 +1,2 @@
|
||||
$('<?= $this->escapeJavascript("tag-subscription-row-" . $this->tag_subscription->id) ?>').remove();
|
||||
notice('Tag subscription deleted');
|
10
app/views/tag_subscription/index.php
Executable file
10
app/views/tag_subscription/index.php
Executable file
@ -0,0 +1,10 @@
|
||||
<?= $this->formTag("#update", function() { ?>
|
||||
<h4><?= $this->t('sub_edit') ?></h4>
|
||||
<div style="margin-bottom: 1em;">
|
||||
<?=$this->t('sub_text') ?><?= CONFIG()->max_tag_subscriptions ?><?=$this->t('sub_text2') ?>
|
||||
</div>
|
||||
|
||||
<table width="100%" class="highlightable">
|
||||
<?= $this->partial("listing", ['tag_subscriptions' => $this->tag_subscriptions]) ?>
|
||||
</table>
|
||||
<?php }) ?>
|
@ -1,3 +1,8 @@
|
||||
<?php
|
||||
// vpe(
|
||||
// $this->user->tag_subscriptions->select(function($x) { return (bool)$x->is_visible_on_profile; })
|
||||
// )
|
||||
?>
|
||||
<?php if ($this->user->has_avatar()) : ?>
|
||||
<div style="width: 25em; height: <?= max($this->user->avatar_height, 80) ?>px; position: relative;">
|
||||
<div style="position: absolute; bottom: 0;">
|
||||
@ -143,14 +148,12 @@
|
||||
</table>
|
||||
</div>
|
||||
|
||||
<?php /*
|
||||
<?php $this->user->tag_subscriptions.visible.each do |tag_subscription| ?>
|
||||
<?php foreach($this->user->tag_subscriptions->select(function($x) { return (bool)$x->is_visible_on_profile; }) as $tag_subscription) : ?>
|
||||
<div style="margin-bottom: 1em; float: left; clear: both;">
|
||||
<h4><?= $this->t('user_sub2') ?><?= tag_subscription.name ?> <?= $this->linkTo("»", 'post#index', 'tags' => 'sub:#array($this->user->name}:#{tag_subscription.name)' ?></h4>
|
||||
<?= $this->partial("post/posts", array('posts' => $this->user->tag_subscription_posts(5, tag_subscription.name).select array(|x| CONFIG()->can_see_post.call(current_user(), x)))) ?>
|
||||
<h4><?= $this->t('user_sub2') ?><?= $tag_subscription->name ?> <?= $this->linkTo("»", ['post#index', 'tags' => 'sub:' . $this->user->name . ':' . $tag_subscription->name]) ?></h4>
|
||||
<?= $this->partial("post/posts", array('posts' => $this->user->tag_subscription_posts(5, $tag_subscription->name)->select(function($x) { return CONFIG()->can_see_post(current_user(), $x); }))) ?>
|
||||
</div>
|
||||
<?php end ?>
|
||||
*/ ?>
|
||||
<?php endforeach ?>
|
||||
|
||||
<div style="margin-bottom: 1em; float: left; clear: both;">
|
||||
<h4><?= $this->linkTo($this->t('user_fav3'), array('post#index', 'tags' => 'vote:3:'.$this->user->name.' order:vote')) ?></h4>
|
||||
|
@ -260,6 +260,12 @@ abstract class DefaultConfig
|
||||
# Use this config to enable Google Analytics. Fill in the GA Tracking ID (like 'UA-XXXXX-X')
|
||||
public $ga_tracking_id = '';
|
||||
|
||||
# Max number of posts to cache
|
||||
public $tag_subscription_post_limit = 200;
|
||||
|
||||
# Max number of fav tags per user
|
||||
public $max_tag_subscriptions = 5;
|
||||
|
||||
/**
|
||||
* *******************************
|
||||
* MyImouto-specific configuration
|
||||
@ -305,6 +311,7 @@ abstract class DefaultConfig
|
||||
'upload_batch_posts',
|
||||
'approve_tag_implication',
|
||||
'approve_tag_alias',
|
||||
'calculate_tag_subscriptions'
|
||||
];
|
||||
|
||||
# Javascripts assets manifest files.
|
||||
@ -500,4 +507,12 @@ abstract class DefaultConfig
|
||||
return 'https://yande.re/post/show/'.$m[1];
|
||||
}
|
||||
}
|
||||
|
||||
public $external_storage = null;
|
||||
|
||||
public function es_create($model)
|
||||
{
|
||||
$className = $this->external_storage . '\Models\\' . get_class($model);
|
||||
$className::create($model);
|
||||
}
|
||||
}
|
||||
|
13
db/migrate/20140112113211_insert_tag_sub_job_task.php
Executable file
13
db/migrate/20140112113211_insert_tag_sub_job_task.php
Executable file
@ -0,0 +1,13 @@
|
||||
<?php
|
||||
class InsertTagSubJobTask extends Rails\ActiveRecord\Migration\Base
|
||||
{
|
||||
public function up()
|
||||
{
|
||||
JobTask::create([
|
||||
'task_type' => "calculate_tag_subscriptions",
|
||||
'data_as_json' => '{}',
|
||||
'status' => "pending",
|
||||
'repeat_count' => -1
|
||||
]);
|
||||
}
|
||||
}
|
8
db/migrate/20140112120043_add_user_id_fk_to_tag_subs.php
Executable file
8
db/migrate/20140112120043_add_user_id_fk_to_tag_subs.php
Executable file
@ -0,0 +1,8 @@
|
||||
<?php
|
||||
class AddUserIdFkToTagSubs extends Rails\ActiveRecord\Migration\Base
|
||||
{
|
||||
public function up()
|
||||
{
|
||||
$this->execute("ALTER TABLE tag_subscriptions ADD CONSTRAINT fk_tag_subs__user_id FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE");
|
||||
}
|
||||
}
|
8
db/migrate/20140112125639_change_tag_subs_charset.php
Executable file
8
db/migrate/20140112125639_change_tag_subs_charset.php
Executable file
@ -0,0 +1,8 @@
|
||||
<?php
|
||||
class ChangeTagSubsCharset extends Rails\ActiveRecord\Migration\Base
|
||||
{
|
||||
public function up()
|
||||
{
|
||||
$this->execute("ALTER TABLE `tag_subscriptions` CHANGE `tag_query` `tag_query` TEXT CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL, CHANGE `cached_post_ids` `cached_post_ids` TEXT CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL, CHANGE `name` `name` VARCHAR( 32 ) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL");
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user