2013-10-27 01:06:58 +02:00
|
|
|
<?php
|
|
|
|
class PoolController extends ApplicationController
|
|
|
|
{
|
|
|
|
protected function init()
|
|
|
|
{
|
|
|
|
$this->helper('Post');
|
|
|
|
}
|
|
|
|
|
|
|
|
protected function filters()
|
|
|
|
{
|
|
|
|
return [
|
|
|
|
'before' => [
|
|
|
|
'user_can_see_posts' => ['only' => ['zip']],
|
|
|
|
'member_only' => ['only' => ['destroy', 'update', 'add_post', 'remove_post', 'import', 'zip']],
|
2014-03-08 18:27:33 +01:00
|
|
|
'post_member_only' => ['only' => ['create']],
|
2013-10-27 01:06:58 +02:00
|
|
|
'contributor_only' => ['only' => ['copy', 'transfer_metadata']]
|
|
|
|
]
|
|
|
|
];
|
|
|
|
}
|
|
|
|
|
|
|
|
public function index()
|
|
|
|
{
|
|
|
|
$this->set_title('Pools');
|
|
|
|
|
|
|
|
$sql_query = Pool::none()->page($this->page_number())->perPage(CONFIG()->pool_index_default_limit);
|
|
|
|
|
|
|
|
$order = $this->params()->order ?: 'id';
|
|
|
|
|
|
|
|
$search_tokens = array();
|
|
|
|
|
|
|
|
if ($this->params()->query) {
|
|
|
|
$this->set_title($this->params()->query . " - Pools");
|
|
|
|
// $query = array_map(function($v){return addslashes($v);}, explode($this->params()->query);
|
|
|
|
// $query = Tokenize.tokenize_with_quotes($this->params[:query] || "")
|
|
|
|
$query = explode(' ', addslashes($this->params()->query));
|
|
|
|
|
|
|
|
foreach ($query as &$token) {
|
|
|
|
if (preg_match('/^(order|limit|posts):(.+)$/', $token, $m)) {
|
|
|
|
if ($m[1] == "order") {
|
|
|
|
$order = $m[2];
|
|
|
|
} elseif ($m[1] == "limit") {
|
|
|
|
$sql_query->perPage(min((int)$m[2], 100));
|
|
|
|
} elseif ($m[1] == "posts") {
|
|
|
|
Post::generate_sql_range_helper(Tag::parse_helper($m[2]), "post_count", $sql_query);
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
// # TODO: removing ^\w- from token.
|
|
|
|
// $token = preg_replace('~[^\w-]~', '', $token);
|
|
|
|
$search_tokens[] = $token;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!empty($search_tokens)) {
|
|
|
|
// $value_index_query = QueryParser.escape_for_tsquery($search_tokens);
|
|
|
|
$value_index_query = implode('_', $search_tokens);
|
|
|
|
if ($value_index_query) {
|
|
|
|
# If a search keyword contains spaces, then it was quoted in the search query
|
|
|
|
# and we should only match adjacent words. tsquery won't do this for us; we need
|
|
|
|
# to filter results where the words aren't adjacent.
|
|
|
|
#
|
|
|
|
# This has a side-effect: any stopwords, stemming, parsing, etc. rules performed
|
|
|
|
# by to_tsquery won't be done here. We need to perform the same processing as
|
|
|
|
# is used to generate search_index. We don't perform all of the stemming rules, so
|
|
|
|
# although "jump" may match "jumping", "jump beans" won't match "jumping beans" because
|
|
|
|
# we'll filter it out.
|
|
|
|
#
|
|
|
|
# This also doesn't perform tokenization, so some obscure cases won't match perfectly;
|
|
|
|
# for example, "abc def" will match "xxxabc def abc" when it probably shouldn't. Doing
|
|
|
|
# this more correctly requires Postgresql support that doesn't exist right now.
|
|
|
|
foreach ($query as $q) {
|
|
|
|
# Don't do this if there are no spaces in the query, so we don't turn off tsquery
|
|
|
|
# parsing when we don't need to.
|
|
|
|
// if (!strstr($q, ' ')) continue;
|
|
|
|
$sql_query->where("(position(LOWER(?) IN LOWER(REPLACE(name, '_', ' '))) > 0 OR position(LOWER(?) IN LOWER(description)) > 0)",
|
|
|
|
$q,
|
|
|
|
$q);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (empty($order))
|
|
|
|
$order = empty($search_tokens) ? 'date' : 'name';
|
|
|
|
|
|
|
|
switch ($order) {
|
|
|
|
case "name":
|
|
|
|
$sql_query->order("name asc");
|
|
|
|
break;
|
|
|
|
|
|
|
|
case "date":
|
|
|
|
$sql_query->order("created_at desc");
|
|
|
|
|
|
|
|
case "updated":
|
|
|
|
$sql_query->order("updated_at desc");
|
|
|
|
break;
|
|
|
|
|
|
|
|
case "id":
|
|
|
|
$sql_query->order("id desc");
|
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
|
|
|
$sql_query->order("created_at desc");
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
$this->pools = $sql_query->paginate();
|
|
|
|
|
|
|
|
$samples = [];
|
|
|
|
foreach($this->pools as $p) {
|
|
|
|
if (!$post = $p->get_sample())
|
|
|
|
continue;
|
|
|
|
$p_id = (string)$p->id;
|
|
|
|
$samples[$p_id] = $post;
|
|
|
|
}
|
|
|
|
$this->samples = $samples;
|
|
|
|
|
|
|
|
$this->respond_to_list('pools');
|
|
|
|
}
|
|
|
|
|
|
|
|
public function show()
|
|
|
|
{
|
|
|
|
if (isset($this->params()->samples) && $this->params()->samples == 0)
|
|
|
|
unset($this->params()->samples);
|
|
|
|
|
|
|
|
$this->pool = Pool::find($this->params()->id);
|
|
|
|
|
|
|
|
$this->browse_mode = current_user()->pool_browse_mode;
|
|
|
|
|
|
|
|
$q = [];
|
|
|
|
$q['pool'] = (int)$this->params()->id;
|
|
|
|
$q['show_deleted_only'] = false;
|
|
|
|
if ($this->browse_mode == 1) {
|
|
|
|
$q['limit'] = 1000;
|
|
|
|
$q['order'] = "portrait_pool";
|
|
|
|
} else {
|
|
|
|
$q['limit'] = 24;
|
|
|
|
}
|
|
|
|
$page = (int)$this->page_number() > 0 ? (int)$this->page_number() : 1;
|
|
|
|
$offset = ($page-1)*$q['limit'];
|
|
|
|
|
|
|
|
list($sql, $params) = Post::generate_sql($q, array('from_api' => true, 'offset' => $offset, 'limit' => $q['limit']));
|
|
|
|
|
2014-05-26 15:06:35 +02:00
|
|
|
# Stringify query so it can be passed to fast_count.
|
|
|
|
$tag_query = [];
|
|
|
|
foreach ($q as $tag => $value) {
|
|
|
|
if ($tag == 'show_deleted_only') {
|
|
|
|
$tag = 'deleted';
|
|
|
|
$value = 'all';
|
|
|
|
}
|
|
|
|
$tag_query[] = $tag . ':' . $value;
|
|
|
|
}
|
|
|
|
$count = Post::fast_count(implode(' ', $tag_query));
|
2013-10-27 01:06:58 +02:00
|
|
|
|
2014-05-26 15:06:35 +02:00
|
|
|
$posts = Post::findBySql($sql, $params);
|
|
|
|
$this->posts = new Rails\ActiveRecord\Collection($posts->members(), ['page' => $page, 'perPage' => $q['limit'], 'offset' => $offset, 'totalRows' => $count]);
|
2013-10-27 01:06:58 +02:00
|
|
|
$this->set_title($this->pool->pretty_name());
|
|
|
|
|
|
|
|
# iTODO:
|
|
|
|
$this->respondTo([
|
|
|
|
'html',
|
|
|
|
// 'xml' => function() {
|
|
|
|
// $builder = new Builder_XmlMarkup(['indent' => 2]);
|
|
|
|
// $builder->instruct();
|
|
|
|
|
|
|
|
// $xml = $this->pool->to_xml(['builder' => $builder, 'skip_instruct' => true], function() {
|
|
|
|
// $builder->posts(function() use ($builder) {
|
|
|
|
// foreach ($this->posts as $post)
|
|
|
|
// $post->to_xml(['builder' => $builder, 'skip_instruct' => true]);
|
|
|
|
// })
|
|
|
|
// });
|
|
|
|
// $this->render(['xml' => $xml]);
|
|
|
|
// },
|
|
|
|
'json' => function() {
|
2014-01-14 15:18:16 +01:00
|
|
|
$this->render(['json' => json_encode(array_merge($this->pool->asJson(), ['posts' => $this->posts->asJson()]))]);
|
2013-10-27 01:06:58 +02:00
|
|
|
}
|
|
|
|
]);
|
|
|
|
}
|
|
|
|
|
|
|
|
public function update()
|
|
|
|
{
|
|
|
|
$this->pool = Pool::find($this->params()->id);
|
|
|
|
|
|
|
|
if (!$this->pool->can_be_updated_by(current_user())) {
|
|
|
|
$this->access_denied();
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if ($this->request()->isPost()) {
|
|
|
|
$this->pool->updateAttributes($this->params()->pool);
|
|
|
|
$this->respond_to_success("Pool updated", array(array('#show', 'id' => $this->params()->id)));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
public function create()
|
|
|
|
{
|
|
|
|
if ($this->request()->isPost()) {
|
|
|
|
$pool = Pool::create(array_merge($this->params()->pool, array('user_id' => current_user()->id)));
|
|
|
|
|
|
|
|
if ($pool->errors()->blank())
|
|
|
|
$this->respond_to_success("Pool created", array(array('#show', 'id' => $pool->id)));
|
|
|
|
else
|
|
|
|
$this->respond_to_error($pool, "#index");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
public function copy()
|
|
|
|
{
|
|
|
|
$this->old_pool = Pool::find($this->params()->id);
|
|
|
|
|
|
|
|
$name = $this->params()->name ?: $this->old_pool->name . ' (copy)';
|
|
|
|
$this->new_pool = new Pool(['user_id' => $this->current_user->id, 'name' => $name, 'description' => $this->old_pool->description]);
|
|
|
|
|
|
|
|
if ($this->request()->isPost()) {
|
|
|
|
$this->new_pool->save();
|
|
|
|
|
|
|
|
if ($this->new_pool->errors()->any()) {
|
|
|
|
$this->respond_to_error($this->new_pool, ['#index']);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
foreach ($this->old_pool->pool_posts as $pp) {
|
|
|
|
$this->new_pool->add_post($pp->post_id, ['sequence' => $pp->sequence]);
|
|
|
|
}
|
|
|
|
|
|
|
|
$this->respond_to_success("Pool created", ['#show', 'id' => $this->new_pool->id]);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
public function destroy()
|
|
|
|
{
|
|
|
|
$this->pool = Pool::find($this->params()->id);
|
|
|
|
|
|
|
|
if ($this->request()->isPost()) {
|
|
|
|
if ($this->pool->can_be_updated_by(current_user())) {
|
|
|
|
$this->pool->destroy();
|
|
|
|
$this->respond_to_success("Pool deleted", "#index");
|
|
|
|
} else
|
|
|
|
$this->access_denied();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
public function addPost()
|
|
|
|
{
|
|
|
|
if ($this->request()->isPost()) {
|
|
|
|
# iMod
|
|
|
|
if ($this->request()->format() == 'json') {
|
|
|
|
try {
|
|
|
|
$pool = Pool::find($this->params()->pool_id);
|
|
|
|
} catch (Rails\ActiveRecord\Exception\RecordNotFoundException $e) {
|
|
|
|
$this->render(['json' => ['reason' => 'Pool not found']]);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
} else
|
|
|
|
$pool = Pool::find($this->params()->pool_id);
|
|
|
|
|
|
|
|
$this->session()->last_pool_id = $pool->id;
|
|
|
|
|
|
|
|
if (isset($this->params()->pool) && !empty($this->params()->pool['sequence']))
|
|
|
|
$sequence = $this->params()->pool['sequence'];
|
|
|
|
else
|
|
|
|
$sequence = null;
|
|
|
|
|
|
|
|
try {
|
|
|
|
$pool->add_post($this->params()->post_id, array('sequence' => $sequence, 'user' => current_user()));
|
|
|
|
$this->respond_to_success('Post added', array(array('post#show', 'id' => $this->params()->post_id)));
|
|
|
|
} catch (Pool_PostAlreadyExistsError $e) {
|
|
|
|
$this->respond_to_error("Post already exists", array('post#show', 'id' => $this->params()->post_id), array('status' => 423));
|
|
|
|
} catch (Pool_AccessDeniedError $e) {
|
|
|
|
$this->access_denied();
|
|
|
|
} catch (Exception $e) {
|
|
|
|
$this->respond_to_error(get_class($e), array('post#show', 'id' => $this->params()->post_id));
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
if (current_user()->is_anonymous)
|
|
|
|
$pools = Pool::where("is_active = TRUE AND is_public = TRUE")->order("name")->take();
|
|
|
|
else
|
|
|
|
$pools = Pool::where("is_active = TRUE AND (is_public = TRUE OR user_id = ?)", current_user()->id)->order("name")->take();
|
|
|
|
|
|
|
|
$post = Post::find($this->params()->post_id);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
public function removePost()
|
|
|
|
{
|
|
|
|
$pool = Pool::find($this->params()->pool_id);
|
|
|
|
$post = Post::find($this->params()->post_id);
|
|
|
|
|
|
|
|
if ($this->request()->isPost()) {
|
|
|
|
try {
|
|
|
|
$pool->remove_post($this->params()->post_id, array('user' => current_user()));
|
|
|
|
} catch (Exception $e) {
|
|
|
|
if ($e->getMessage() == 'Access Denied')
|
|
|
|
$this->access_denied();
|
|
|
|
}
|
|
|
|
|
|
|
|
$api_data = Post::batch_api_data(array($post));
|
|
|
|
|
|
|
|
$this->response()->headers()->add("X-Post-Id", $this->params()->post_id);
|
|
|
|
$this->respond_to_success("Post removed", array('post#show', 'id' => $this->params()->post_id), array('api' => $api_data));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
public function order()
|
|
|
|
{
|
|
|
|
$this->pool = Pool::find($this->params()->id);
|
|
|
|
|
|
|
|
if (!$this->pool->can_be_updated_by(current_user()))
|
|
|
|
$this->access_denied();
|
|
|
|
|
|
|
|
if ($this->request()->isPost()) {
|
|
|
|
foreach ($this->params()->pool_post_sequence as $i => $seq)
|
|
|
|
PoolPost::update($i, array('sequence' => $seq));
|
|
|
|
|
|
|
|
$this->pool->reload();
|
|
|
|
$this->pool->update_pool_links();
|
|
|
|
|
|
|
|
$this->notice("Ordering updated");
|
|
|
|
$this->redirectTo(array('#show', 'id' => $this->params()->id));
|
|
|
|
} else
|
|
|
|
$this->pool_posts = $this->pool->pool_posts;
|
|
|
|
}
|
|
|
|
|
|
|
|
public function select()
|
|
|
|
{
|
|
|
|
if (current_user()->is_anonymous())
|
|
|
|
$this->pools = Pool::where("is_active = TRUE AND is_public = TRUE")->order("name")->take();
|
|
|
|
else
|
|
|
|
$this->pools = Pool::where("is_active = TRUE AND (is_public = TRUE OR user_id = ?)", current_user()->id)->order("name")->take();
|
|
|
|
|
|
|
|
$options = array('(000) DO NOT ADD' => 0);
|
|
|
|
|
|
|
|
foreach ($this->pools as $p) {
|
|
|
|
$options[str_replace('_', ' ', $p->name)] = $p->id;
|
|
|
|
}
|
|
|
|
$this->options = $options;
|
|
|
|
$this->last_pool_id = $this->session()->last_pool_id;
|
|
|
|
$this->setLayout(false);
|
|
|
|
}
|
|
|
|
|
|
|
|
public function zip()
|
|
|
|
{
|
|
|
|
if (!CONFIG()->pool_zips)
|
|
|
|
throw new Rails\ActiveRecord\Exception\RecordNotFoundException();
|
|
|
|
|
|
|
|
$pool = Pool::find($this->params()->id);
|
|
|
|
$files = $pool->get_zip_data($this->params()->all());
|
|
|
|
|
|
|
|
$zip = new ZipStream($pool->pretty_name() . '.zip');
|
|
|
|
|
|
|
|
foreach ($files as $file) {
|
|
|
|
list($path, $filename) = $file;
|
|
|
|
$zip->addLargeFile($path, $filename);
|
|
|
|
}
|
|
|
|
|
|
|
|
$zip->finalize();
|
|
|
|
$this->render(['nothing' => true]);
|
|
|
|
}
|
|
|
|
|
|
|
|
public function transferMetadata()
|
|
|
|
{
|
|
|
|
$this->to = Pool::find($this->params()->to);
|
|
|
|
|
|
|
|
if (!$this->params()->from) {
|
|
|
|
$this->from = null;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
$this->from = Pool::find($this->params()->from);
|
|
|
|
|
|
|
|
$from_posts = $this->from->pool_posts;
|
|
|
|
$to_posts = $this->to->pool_posts;
|
|
|
|
|
|
|
|
if ($from_posts->size() == $to_posts->size()) {
|
|
|
|
$this->truncated = false;
|
|
|
|
} else {
|
|
|
|
$this->truncated = true;
|
|
|
|
$min_posts = min($from_posts->size(), $to_posts->size());
|
|
|
|
$from_posts = $from_posts->slice(0, $min_posts);
|
|
|
|
$to_posts = $to_posts->slice(0, $min_posts);
|
|
|
|
}
|
|
|
|
|
|
|
|
$this->posts = Post::emptyCollection();
|
|
|
|
foreach ($from_posts as $k => $v) {
|
|
|
|
$data = [];
|
|
|
|
$from = $v->post;
|
|
|
|
$to = $to_posts[$k]->post;
|
|
|
|
$data['from'] = $from;
|
|
|
|
$data['to'] = $to;
|
|
|
|
|
|
|
|
$from_tags = $from->tags;
|
|
|
|
$to_tags = $to->tags;
|
|
|
|
|
|
|
|
$tags = $from_tags;
|
|
|
|
|
|
|
|
if ($from->rating != $to->rating) {
|
|
|
|
$tags[] = 'rating:' . $to->rating;
|
|
|
|
}
|
|
|
|
|
|
|
|
if ($from->is_shown_in_index != $to->is_shown_in_index) {
|
|
|
|
$tags[] = $from->is_shown_in_index ? 'show' : 'hide';
|
|
|
|
}
|
|
|
|
|
|
|
|
if ($from->parent_id != $to->id) {
|
|
|
|
$tags[] = 'child:' . $from->id;
|
|
|
|
}
|
|
|
|
|
|
|
|
$data['tags'] = implode(' ', $tags);
|
|
|
|
|
|
|
|
$this->posts[] = $data;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|