Compare commits
4 Commits
e7940a21ee
...
d6cd33019d
Author | SHA1 | Date |
---|---|---|
Hugo Sales | d6cd33019d | |
Hugo Sales | 5662210a2d | |
Hugo Sales | b1fbf7d6ef | |
Hugo Sales | 9f11d270f4 |
|
@ -40,7 +40,7 @@ class Directory extends FeedController
|
||||||
* Function responsible for displaying a list of actors of a given
|
* Function responsible for displaying a list of actors of a given
|
||||||
* $actor_type, sorted by the `order_by` GET parameter, if given
|
* $actor_type, sorted by the `order_by` GET parameter, if given
|
||||||
*/
|
*/
|
||||||
private function impl(Request $request, string $template, int $actor_type): array
|
private function impl(Request $request, int $actor_type, string $title, string $empty_message): array
|
||||||
{
|
{
|
||||||
if ($actor_type !== Actor::PERSON && $actor_type !== Actor::GROUP) {
|
if ($actor_type !== Actor::PERSON && $actor_type !== Actor::GROUP) {
|
||||||
throw new BugFoundException("Unimplemented for actor type: {$actor_type}");
|
throw new BugFoundException("Unimplemented for actor type: {$actor_type}");
|
||||||
|
@ -56,10 +56,10 @@ class Directory extends FeedController
|
||||||
$order_by_op = mb_substr($order_by_qs, -1);
|
$order_by_op = mb_substr($order_by_qs, -1);
|
||||||
if (\in_array($order_by_op, ['^', '<'])) {
|
if (\in_array($order_by_op, ['^', '<'])) {
|
||||||
$order_by_field = mb_substr($order_by_qs, 0, -1);
|
$order_by_field = mb_substr($order_by_qs, 0, -1);
|
||||||
$order_by_op = 'ASC';
|
$order_by_op = 'DESC';
|
||||||
} elseif (\in_array($order_by_op, ['v', '>'])) {
|
} elseif (\in_array($order_by_op, ['v', '>'])) {
|
||||||
$order_by_field = mb_substr($order_by_qs, 0, -1);
|
$order_by_field = mb_substr($order_by_qs, 0, -1);
|
||||||
$order_by_op = 'DESC';
|
$order_by_op = 'ASC';
|
||||||
} else {
|
} else {
|
||||||
$order_by_field = $order_by_qs;
|
$order_by_field = $order_by_qs;
|
||||||
$order_by_op = 'ASC';
|
$order_by_op = 'ASC';
|
||||||
|
@ -77,17 +77,17 @@ class Directory extends FeedController
|
||||||
|
|
||||||
// -------- Query builder for selecting actors joined with another table, namely activity and group_inbox --------
|
// -------- Query builder for selecting actors joined with another table, namely activity and group_inbox --------
|
||||||
$general_query_fn_fn = function (string $func, string $order) use ($limit, $offset) {
|
$general_query_fn_fn = function (string $func, string $order) use ($limit, $offset) {
|
||||||
return fn (string $table, string $join_field) => fn (int $actor_type) => DB::sql(
|
return fn (string $table, string $join_field, string $aggregate_field) => fn (int $actor_type) => DB::sql(
|
||||||
<<<EOQ
|
<<<EOQ
|
||||||
select {select}
|
select {select}
|
||||||
from actor actr
|
from actor actr
|
||||||
join (
|
join (
|
||||||
select tbl.{$join_field}, {$func}(tbl.created) as created
|
select tbl.{$join_field}, {$func}(tbl.{$aggregate_field}) as aggr
|
||||||
from {$table} tbl
|
from {$table} tbl
|
||||||
group by tbl.{$join_field}
|
group by tbl.{$join_field}
|
||||||
) actor_activity on actr.id = actor_activity.{$join_field}
|
) actor_activity on actr.id = actor_activity.{$join_field}
|
||||||
where actr.type = :type
|
where actr.type = :type
|
||||||
order by actor_activity.{$order}
|
order by actor_activity.aggr {$order}
|
||||||
limit :limit offset :offset
|
limit :limit offset :offset
|
||||||
EOQ,
|
EOQ,
|
||||||
[
|
[
|
||||||
|
@ -102,8 +102,8 @@ class Directory extends FeedController
|
||||||
|
|
||||||
// -------- Start setting up the queries --------
|
// -------- Start setting up the queries --------
|
||||||
$actor_query_fn = fn (int $actor_type) => DB::findBy(Actor::class, ['type' => $actor_type], order_by: $order_by, limit: $limit, offset: $offset);
|
$actor_query_fn = fn (int $actor_type) => DB::findBy(Actor::class, ['type' => $actor_type], order_by: $order_by, limit: $limit, offset: $offset);
|
||||||
$modified_query_fn = $general_query_fn_fn(func: $order_by_op === 'ASC' ? 'MAX' : 'MIN', order: "created {$order_by_op}");
|
$minmax_query_fn = $general_query_fn_fn(func: $order_by_op === 'ASC' ? 'MAX' : 'MIN', order: $order_by_op);
|
||||||
$activity_query_fn = $general_query_fn_fn(func: 'COUNT', order: "created {$order_by_op}");
|
$count_query_fn = $general_query_fn_fn(func: 'COUNT', order: $order_by_op);
|
||||||
// -------- *** --------
|
// -------- *** --------
|
||||||
|
|
||||||
// -------- Figure out the final query --------
|
// -------- Figure out the final query --------
|
||||||
|
@ -111,33 +111,55 @@ class Directory extends FeedController
|
||||||
'nickname', 'created' => $actor_query_fn, // select only from actors
|
'nickname', 'created' => $actor_query_fn, // select only from actors
|
||||||
|
|
||||||
'modified' => match ($actor_type) { // select by most/least recent activity
|
'modified' => match ($actor_type) { // select by most/least recent activity
|
||||||
Actor::PERSON => $modified_query_fn(table: 'activity', join_field: 'actor_id'),
|
Actor::PERSON => $minmax_query_fn(table: 'activity', join_field: 'actor_id', aggregate_field: 'created'),
|
||||||
Actor::GROUP => $modified_query_fn(table: 'group_inbox', join_field: 'group_id'),
|
Actor::GROUP => $minmax_query_fn(table: 'group_inbox', join_field: 'group_id', aggregate_field: 'created'),
|
||||||
},
|
},
|
||||||
|
|
||||||
'activity' => match ($actor_type) { // select by most/least activity amount
|
'activity' => match ($actor_type) { // select by most/least activity amount
|
||||||
Actor::PERSON => $activity_query_fn(table: 'activity', join_field: 'actor_id'),
|
Actor::PERSON => $count_query_fn(table: 'activity', join_field: 'actor_id', aggregate_field: 'created'),
|
||||||
Actor::GROUP => $activity_query_fn(table: 'group_inbox', join_field: 'group_id'),
|
Actor::GROUP => $count_query_fn(table: 'group_inbox', join_field: 'group_id', aggregate_field: 'created'),
|
||||||
|
},
|
||||||
|
|
||||||
|
'subscribers' => match ($actor_type) { // select by actors with most/least subscribers/members
|
||||||
|
Actor::PERSON => $count_query_fn(table: 'subscription', join_field: 'subscribed', aggregate_field: 'subscriber'),
|
||||||
|
Actor::GROUP => $count_query_fn(table: 'group_member', join_field: 'group_id', aggregate_field: 'actor_id'),
|
||||||
},
|
},
|
||||||
|
|
||||||
default => throw new BugFoundException("Unkown order by found, but should have been validated: {$order_by_field}"),
|
default => throw new BugFoundException("Unkown order by found, but should have been validated: {$order_by_field}"),
|
||||||
};
|
};
|
||||||
// -------- *** --------
|
// -------- *** --------
|
||||||
|
|
||||||
|
$sort_options = [];
|
||||||
|
foreach (self::ALLOWED_FIELDS as $al) {
|
||||||
|
$sort_options[] = [
|
||||||
|
'active' => false,
|
||||||
|
'url' => '?order_by=' . $al . '^',
|
||||||
|
'label' => _m('{order_by} ascending', ['{order_by}' => ucfirst($al)]),
|
||||||
|
];
|
||||||
|
$sort_options[] = [
|
||||||
|
'active' => false,
|
||||||
|
'url' => '?order_by=' . $al . 'v',
|
||||||
|
'label' => _m('{order_by} descending', ['{order_by}' => ucfirst($al)]),
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
return [
|
return [
|
||||||
'_template' => $template,
|
'_template' => 'directory/actors.html.twig',
|
||||||
'actors' => $query_fn($actor_type),
|
'actors' => $query_fn($actor_type),
|
||||||
|
'title' => $title,
|
||||||
|
'empty_message' => $empty_message,
|
||||||
|
'sort_options' => $sort_options,
|
||||||
'page' => $page,
|
'page' => $page,
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
public function people(Request $request): array
|
public function people(Request $request): array
|
||||||
{
|
{
|
||||||
return $this->impl($request, 'directory/people.html.twig', Actor::PERSON);
|
return $this->impl($request, Actor::PERSON, title: _m('People'), empty_message: _m('No people here'));
|
||||||
}
|
}
|
||||||
|
|
||||||
public function groups(Request $request): array
|
public function groups(Request $request): array
|
||||||
{
|
{
|
||||||
return $this->impl($request, 'directory/groups.html.twig', Actor::GROUP);
|
return $this->impl($request, Actor::GROUP, title: _m('Groups'), empty_message: _m('No groups here'));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,10 +1,17 @@
|
||||||
{% extends 'stdgrid.html.twig' %}
|
{% extends 'stdgrid.html.twig' %}
|
||||||
|
|
||||||
{% block title %}Actors{% endblock %}
|
{% block title %}{{ title }}{% endblock %}
|
||||||
|
|
||||||
{% block body %}
|
{% block body %}
|
||||||
<section class="section-widget section-padding">
|
<section class="section-widget section-padding">
|
||||||
<h2 class="section-title">{{ "Actors" | trans }}</h2>
|
<h2 class="section-title">{{ title }}</h2>
|
||||||
|
|
||||||
|
<div>
|
||||||
|
<p>{% trans %}Sort by:{% endtrans %}</p>
|
||||||
|
{% for option in sort_options %}
|
||||||
|
<a {{ option.active ? 'class="active"' : '' }} href="{{ option.url }}">{{ option.label }}</a>
|
||||||
|
{% endfor %}
|
||||||
|
</div>
|
||||||
|
|
||||||
<div class="section-padding">
|
<div class="section-padding">
|
||||||
{% if actors is defined and actors is not empty %}
|
{% if actors is defined and actors is not empty %}
|
||||||
|
@ -12,8 +19,9 @@
|
||||||
{% block profile_view %}{% include 'cards/profile/view.html.twig' %}{% endblock profile_view %}
|
{% block profile_view %}{% include 'cards/profile/view.html.twig' %}{% endblock profile_view %}
|
||||||
<hr>
|
<hr>
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
|
<p>{% trans %}Page: %page%{% endtrans %}</p>
|
||||||
{% else %}
|
{% else %}
|
||||||
<h1>{% trans %}No actors here.{% endtrans %}</h1>
|
<h3>{{ empty_message }}</h3>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
</div>
|
</div>
|
||||||
</section>
|
</section>
|
|
@ -1,20 +0,0 @@
|
||||||
{% extends 'stdgrid.html.twig' %}
|
|
||||||
|
|
||||||
{% block title %}Groups{% endblock %}
|
|
||||||
|
|
||||||
{% block body %}
|
|
||||||
<section class="section-widget section-padding">
|
|
||||||
<h2 class="section-title">{{ "Groups" | trans }}</h2>
|
|
||||||
|
|
||||||
<div class="section-padding">
|
|
||||||
{% if groups is defined and groups is not empty %}
|
|
||||||
{% for actor in groups %}
|
|
||||||
{% block profile_view %}{% include 'cards/profile/view.html.twig' %}{% endblock profile_view %}
|
|
||||||
<hr>
|
|
||||||
{% endfor %}
|
|
||||||
{% else %}
|
|
||||||
<h1>{% trans %}No groups here.{% endtrans %}</h1>
|
|
||||||
{% endif %}
|
|
||||||
</div>
|
|
||||||
</section>
|
|
||||||
{% endblock body %}
|
|
Loading…
Reference in New Issue