[PLUGINS][Repeat] Added note_repeat entity, fixed visual discrepancies, and completed the expected functionality.
[ENTITY][Note] Removed repeat_off from table. It is now part of the Repeat plugin.
This commit is contained in:
parent
73e772e576
commit
cf09b48e92
|
@ -34,6 +34,7 @@ use App\Util\Exception\InvalidFormException;
|
|||
use App\Util\Exception\NoLoggedInUser;
|
||||
use App\Util\Exception\NoSuchNoteException;
|
||||
use App\Util\Exception\RedirectException;
|
||||
use Plugin\Repeat\Entity\NoteRepeat;
|
||||
use Symfony\Component\Form\Extension\Core\Type\SubmitType;
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
use function App\Core\I18n\_m;
|
||||
|
@ -52,7 +53,7 @@ class Repeat extends Controller
|
|||
{
|
||||
$user = Common::ensureLoggedIn();
|
||||
$opts = ['actor_id' => $user->getId(), 'repeat_of' => $id];
|
||||
$note_already_repeated = DB::count('note', $opts) >= 1;
|
||||
$note_already_repeated = DB::count('note_repeat', $opts) >= 1;
|
||||
if (is_null($note_already_repeated)) {
|
||||
throw new NoSuchNoteException();
|
||||
}
|
||||
|
@ -71,15 +72,38 @@ class Repeat extends Controller
|
|||
|
||||
$form_add_to_repeat->handleRequest($request);
|
||||
if ($form_add_to_repeat->isSubmitted()) {
|
||||
|
||||
if (!is_null($note)) {
|
||||
DB::persist(Note::create([
|
||||
'actor_id' => $user->getId(),
|
||||
'repeat_of' => $note->getId(),
|
||||
'content' => $note->getContent(),
|
||||
$actor_id = $user->getId();
|
||||
$content = $note->getContent();
|
||||
|
||||
// Create a new note with the same content as the original
|
||||
$repeat = Note::create([
|
||||
'actor_id' => $actor_id,
|
||||
'content' => $content,
|
||||
'content_type' => $note->getContentType(),
|
||||
'rendered' => $note->getRendered(),
|
||||
'is_local' => true,
|
||||
]);
|
||||
DB::persist($repeat);
|
||||
|
||||
// Update DB
|
||||
DB::flush();
|
||||
|
||||
// Find the id of the note we just created
|
||||
$repeat_id = $repeat->getId();
|
||||
$og_id = $note->getId();
|
||||
|
||||
// Add it to note_repeat table
|
||||
if (!is_null($repeat_id)) {
|
||||
DB::persist(NoteRepeat::create([
|
||||
'id' => $repeat_id,
|
||||
'actor_id' => $actor_id,
|
||||
'repeat_of' => $og_id
|
||||
]));
|
||||
}
|
||||
|
||||
// Update DB one last time
|
||||
DB::flush();
|
||||
}
|
||||
|
||||
|
@ -106,7 +130,7 @@ class Repeat extends Controller
|
|||
public function repeatRemoveNote(Request $request, int $id): array
|
||||
{
|
||||
$user = Common::ensureLoggedIn();
|
||||
$opts = ['note_id' => $id, 'actor_id' => $user->getId()];
|
||||
$opts = ['id' => $id];
|
||||
$remove_repeat_note = DB::find('note', $opts);
|
||||
if (is_null($remove_repeat_note)) {
|
||||
throw new NoSuchNoteException();
|
||||
|
|
92
plugins/Repeat/Entity/NoteRepeat.php
Normal file
92
plugins/Repeat/Entity/NoteRepeat.php
Normal file
|
@ -0,0 +1,92 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
// {{{ License
|
||||
|
||||
// This file is part of GNU social - https://www.gnu.org/software/social
|
||||
//
|
||||
// GNU social is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU Affero General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// GNU social is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU Affero General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Affero General Public License
|
||||
// along with GNU social. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
// }}}
|
||||
|
||||
namespace Plugin\Repeat\Entity;
|
||||
|
||||
use App\Core\Entity;
|
||||
|
||||
/**
|
||||
* Entity for notices
|
||||
*
|
||||
* @category DB
|
||||
* @package GNUsocial
|
||||
*
|
||||
* @author Eliseu Amaro <mail@eliseuama.ro>
|
||||
* @copyright 2020-2021 Free Software Foundation, Inc http://www.fsf.org
|
||||
* @license https://www.gnu.org/licenses/agpl.html GNU AGPL v3 or later
|
||||
*/
|
||||
class NoteRepeat extends Entity
|
||||
{
|
||||
private int $id;
|
||||
private int $actor_id;
|
||||
private int $repeat_of;
|
||||
|
||||
public function setId(int $id): self
|
||||
{
|
||||
$this->id = $id;
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getId(): int
|
||||
{
|
||||
return $this->id;
|
||||
}
|
||||
|
||||
public function setActorId(int $actor_id): self
|
||||
{
|
||||
$this->actor_id = $actor_id;
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getActorId(): ?int
|
||||
{
|
||||
return $this->actor_id;
|
||||
}
|
||||
|
||||
public function setRepeatOf(int $repeat_of): self
|
||||
{
|
||||
$this->repeat_of = $repeat_of;
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getRepeatOf(): int
|
||||
{
|
||||
return $this->repeat_of;
|
||||
}
|
||||
|
||||
public static function schemaDef(): array
|
||||
{
|
||||
return [
|
||||
'name' => 'note_repeat',
|
||||
'fields' => [
|
||||
'id' => ['type' => 'int', 'not null' => true, 'description' => 'The id of the repeat itself'],
|
||||
'actor_id' => ['type' => 'int', 'not null' => true, 'foreign key' => true, 'target' => 'Actor.id', 'multiplicity' => 'one to one', 'description' => 'Who made this repeat'],
|
||||
'repeat_of' => ['type' => 'int', 'not null' => true, 'foreign key' => true, 'target' => 'Note.id', 'multiplicity' => 'one to one', 'description' => 'Note this is a repeat of'],
|
||||
],
|
||||
'primary key' => ['id'],
|
||||
'foreign keys' => [
|
||||
'note_repeat_of_id_fkey' => ['note', ['repeat_of' => 'id']],
|
||||
],
|
||||
];
|
||||
}
|
||||
}
|
|
@ -25,11 +25,13 @@ use App\Core\DB\DB;
|
|||
use App\Core\Event;
|
||||
use App\Core\Router\RouteLoader;
|
||||
use App\Core\Router\Router;
|
||||
use App\Util\Exception\DuplicateFoundException;
|
||||
use App\Util\Exception\InvalidFormException;
|
||||
use App\Util\Exception\NoSuchNoteException;
|
||||
use App\Core\Modules\NoteHandlerPlugin;
|
||||
use App\Entity\Note;
|
||||
use App\Util\Common;
|
||||
use App\Util\Exception\NotFoundException;
|
||||
use App\Util\Exception\RedirectException;
|
||||
use App\Util\Formatting;
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
|
@ -53,21 +55,30 @@ class Repeat extends NoteHandlerPlugin
|
|||
return Event::next;
|
||||
}
|
||||
|
||||
// If note is repeat, "is_repeated" is 1
|
||||
$opts = ['actor_id' => $user->getId(), 'repeat_of' => $note->getId()];
|
||||
$is_repeated = DB::count('note', $opts) >= 1;
|
||||
// If note is repeated, "is_repeated" is 1
|
||||
$opts = ['repeat_of' => $note->getId()];
|
||||
try {
|
||||
if (DB::findOneBy('note_repeat', $opts)) {
|
||||
return Event::next;
|
||||
}
|
||||
} catch (DuplicateFoundException $e) {
|
||||
} catch (NotFoundException $e) {
|
||||
}
|
||||
|
||||
$is_repeat = DB::count('note_repeat', ['id' => $note->getId()]) >= 1;
|
||||
|
||||
|
||||
// Generating URL for repeat action route
|
||||
$args = ['id' => $note->getId()];
|
||||
$type = Router::ABSOLUTE_PATH;
|
||||
$repeat_action_url = $is_repeated ?
|
||||
$repeat_action_url = $is_repeat ?
|
||||
Router::url('repeat_remove', $args, $type) :
|
||||
Router::url('repeat_add', $args, $type);
|
||||
|
||||
// Concatenating get parameter to redirect the user to where he came from
|
||||
$repeat_action_url .= '?from=' . substr($request->getQueryString(), 2);
|
||||
|
||||
$extra_classes = $is_repeated ? "note-actions-set" : "note-actions-unset";
|
||||
$extra_classes = $is_repeat ? "note-actions-set" : "note-actions-unset";
|
||||
$repeat_action = [
|
||||
"url" => $repeat_action_url,
|
||||
"classes" => "button-container repeat-button-container $extra_classes",
|
||||
|
@ -89,6 +100,17 @@ class Repeat extends NoteHandlerPlugin
|
|||
return Event::next;
|
||||
}
|
||||
|
||||
public function onGetAdditionalTemplateVars(array $vars, array &$result)
|
||||
{
|
||||
$note_id = $vars['note_id'];
|
||||
|
||||
$opts = ['id' => $note_id];
|
||||
$is_repeat = DB::count('note_repeat', $opts) >= 1;
|
||||
|
||||
$result = ['is_repeat' => (bool)$is_repeat];
|
||||
return Event::stop;
|
||||
}
|
||||
|
||||
public function onAddRoute(RouteLoader $r): bool
|
||||
{
|
||||
// Add/remove note to/from repeats
|
||||
|
|
|
@ -1,16 +1,31 @@
|
|||
{% extends '/cards/note/view.html.twig' %}
|
||||
|
||||
{% block note_author_repeated %}
|
||||
{# Microformat's h-card properties indicates a face icon is a "u-logo" #}
|
||||
<a href="{{ actor_url }}" class="note-author u-url">
|
||||
<strong class="note-author-fullname">
|
||||
{% if fullname is not null %}
|
||||
{{ fullname }}
|
||||
{% else %}
|
||||
{{ nickname }}
|
||||
{% endif %}
|
||||
</strong>
|
||||
<em class="note-author-nickname">{{ nickname }} {{ "repeated the following note" | trans }}</em>
|
||||
</a>
|
||||
{% endblock note_author_repeated %}
|
||||
|
||||
{% macro macro_note(note, replies) %}
|
||||
{% set nickname = note.getActorNickname() %}
|
||||
{% set fullname = note.getActorFullname() %}
|
||||
{% set actor_url = note.getActor().getUrl() %}
|
||||
{% set repeat_of = note.getRepeatOf() %}
|
||||
{% set additional_vars = handle_event('GetAdditionalTemplateVars', {'note_id': note.getId(), 'actor_id': note.getActorId()}) %}
|
||||
|
||||
{% if additional_vars['is_repeat'] %}
|
||||
<article class="h-entry hentry note">
|
||||
{{ block('note_sidebar') }}
|
||||
<div class="note-wrapper">
|
||||
<div tabindex="0" title="{{ 'Begin a note by the user: ' | trans }} {{ nickname }}." class="note-info">
|
||||
{{ block('note_author') }}
|
||||
{{ block('note_author_repeated') }}
|
||||
{{ block('note_actions') }}
|
||||
</div>
|
||||
<section tabindex="0" role="dialog" class="e-content entry-content note-content">
|
||||
|
@ -19,4 +34,21 @@
|
|||
{{ block('note_replies') }}
|
||||
</div>
|
||||
</article>
|
||||
{% else %}
|
||||
<article class="h-entry hentry note">
|
||||
{{ block('note_sidebar') }}
|
||||
<div class="note-wrapper">
|
||||
<div tabindex="0" title="{{ 'Begin a note by the user: ' | trans }} {{ nickname }}." class="note-info">
|
||||
{{ block('note_author') }}
|
||||
{{ block('note_actions') }}
|
||||
</div>
|
||||
<section tabindex="0" role="dialog" class="e-content entry-content note-content">
|
||||
{{ block('note_text') }}
|
||||
{{ block('note_attachments') }}
|
||||
{{ block('note_links') }}
|
||||
</section>
|
||||
{{ block('note_replies') }}
|
||||
</div>
|
||||
</article>
|
||||
{% endif %}
|
||||
{% endmacro macro_note %}
|
|
@ -13,7 +13,7 @@
|
|||
<div class="page">
|
||||
<div class="main">
|
||||
{{ noteView.macro_note_minimal(note) }}
|
||||
{{ form(remove_favourite) }}
|
||||
{{ form(remove_repeat) }}
|
||||
</div>
|
||||
</div>
|
||||
{% endblock body %}
|
||||
|
|
|
@ -162,7 +162,7 @@ class Note extends Entity
|
|||
return $this->conversation;
|
||||
}
|
||||
|
||||
public function setRepeatOf(?int $repeat_of): self
|
||||
/* public function setRepeatOf(?int $repeat_of): self
|
||||
{
|
||||
$this->repeat_of = $repeat_of;
|
||||
return $this;
|
||||
|
@ -171,7 +171,7 @@ class Note extends Entity
|
|||
public function getRepeatOf(): ?int
|
||||
{
|
||||
return $this->repeat_of;
|
||||
}
|
||||
}*/
|
||||
|
||||
public function setScope(int $scope): self
|
||||
{
|
||||
|
@ -349,7 +349,7 @@ class Note extends Entity
|
|||
'is_local' => ['type' => 'bool', 'description' => 'was this note generated by a local actor'],
|
||||
'source' => ['type' => 'varchar', 'foreign key' => true, 'length' => 32, 'target' => 'NoteSource.code', 'multiplicity' => 'many to one', 'description' => 'fkey to source of note, like "web", "im", or "clientname"'],
|
||||
'conversation' => ['type' => 'int', 'foreign key' => true, 'target' => 'Conversation.id', 'multiplicity' => 'one to one', 'description' => 'the local conversation id'],
|
||||
'repeat_of' => ['type' => 'int', 'foreign key' => true, 'target' => 'Note.id', 'multiplicity' => 'one to one', 'description' => 'note this is a repeat of'],
|
||||
// 'repeat_of' => ['type' => 'int', 'foreign key' => true, 'target' => 'Note.id', 'multiplicity' => 'one to one', 'description' => 'note this is a repeat of'],
|
||||
'scope' => ['type' => 'int', 'not null' => true, 'default' => VisibilityScope::PUBLIC, 'description' => 'bit map for distribution scope; 0 = everywhere; 1 = this server only; 2 = addressees; 4 = groups; 8 = followers; 16 = messages; null = default'],
|
||||
'url' => ['type' => 'text', 'description' => 'Permalink to Note'],
|
||||
'language' => ['type' => 'int', 'foreign key' => true, 'target' => 'Language.id', 'multiplicity' => 'one to many', 'description' => 'The language for this note'],
|
||||
|
@ -361,7 +361,7 @@ class Note extends Entity
|
|||
'note_created_id_is_local_idx' => ['created', 'is_local'],
|
||||
'note_actor_created_idx' => ['actor_id', 'created'],
|
||||
'note_is_local_created_actor_idx' => ['is_local', 'created', 'actor_id'],
|
||||
'note_repeat_of_created_idx' => ['repeat_of', 'created'],
|
||||
// 'note_repeat_of_created_idx' => ['repeat_of', 'created'],
|
||||
'note_conversation_created_idx' => ['conversation', 'created'],
|
||||
'note_reply_to_idx' => ['reply_to'],
|
||||
],
|
||||
|
|
|
@ -134,6 +134,15 @@ class Runtime implements RuntimeExtensionInterface, EventSubscriberInterface
|
|||
return $result;
|
||||
}
|
||||
|
||||
public function getAdditionalTemplateVars(array $vars): array
|
||||
{
|
||||
$result = [];
|
||||
if (Event::handle('GetAdditionalTemplateVars', [$vars, &$result]) !== Event::stop) {
|
||||
return [];
|
||||
}
|
||||
return $result;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------
|
||||
|
||||
/**
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
{% extends 'stdgrid.html.twig' %}
|
||||
|
||||
{% set override_import = handle_override_template_import('/network/feed.html.twig', '/cards/note/view.html.twig') %}
|
||||
{% import override_import as noteView %}
|
||||
|
||||
|
|
Loading…
Reference in New Issue
Block a user