ghost
1 year ago
18 changed files with 1113 additions and 77 deletions
@ -0,0 +1,37 @@
@@ -0,0 +1,37 @@
|
||||
<?php |
||||
|
||||
declare(strict_types=1); |
||||
|
||||
namespace DoctrineMigrations; |
||||
|
||||
use Doctrine\DBAL\Schema\Schema; |
||||
use Doctrine\Migrations\AbstractMigration; |
||||
|
||||
/** |
||||
* Auto-generated Migration: Please modify to your needs! |
||||
*/ |
||||
final class Version20231103235504 extends AbstractMigration |
||||
{ |
||||
public function getDescription(): string |
||||
{ |
||||
return ''; |
||||
} |
||||
|
||||
public function up(Schema $schema): void |
||||
{ |
||||
// this up() migration is auto-generated, please modify it to your needs |
||||
$this->addSql('CREATE TABLE torrent_categories (id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, torrent_id INTEGER NOT NULL, user_id INTEGER NOT NULL, added INTEGER NOT NULL, value CLOB NOT NULL --(DC2Type:simple_array) |
||||
, approved BOOLEAN NOT NULL)'); |
||||
$this->addSql('ALTER TABLE user ADD COLUMN categories CLOB DEFAULT "other"'); |
||||
$this->addSql('ALTER TABLE torrent ADD COLUMN categories CLOB DEFAULT "other"'); |
||||
$this->addSql('UPDATE user SET categories = "movie,series,tv,animation,music,game,audiobook,podcast,book,archive,picture,software,other"'); |
||||
} |
||||
|
||||
public function down(Schema $schema): void |
||||
{ |
||||
// this down() migration is auto-generated, please modify it to your needs |
||||
$this->addSql('DROP TABLE torrent_categories'); |
||||
$this->addSql('ALTER TABLE user DROP COLUMN categories'); |
||||
$this->addSql('ALTER TABLE torrent DROP COLUMN categories'); |
||||
} |
||||
} |
@ -0,0 +1,103 @@
@@ -0,0 +1,103 @@
|
||||
<?php |
||||
|
||||
namespace App\Entity; |
||||
|
||||
use App\Repository\TorrentCategoriesRepository; |
||||
use Doctrine\DBAL\Types\Types; |
||||
use Doctrine\ORM\Mapping as ORM; |
||||
|
||||
#[ORM\Entity(repositoryClass: TorrentCategoriesRepository::class)] |
||||
class TorrentCategories |
||||
{ |
||||
#[ORM\Id] |
||||
#[ORM\GeneratedValue] |
||||
#[ORM\Column] |
||||
private ?int $id = null; |
||||
|
||||
#[ORM\Column] |
||||
private ?int $torrentId = null; |
||||
|
||||
#[ORM\Column] |
||||
private ?int $userId = null; |
||||
|
||||
#[ORM\Column] |
||||
private ?int $added = null; |
||||
|
||||
#[ORM\Column(type: Types::SIMPLE_ARRAY)] |
||||
private array $value = []; |
||||
|
||||
#[ORM\Column] |
||||
private ?bool $approved = null; |
||||
|
||||
public function getId(): ?int |
||||
{ |
||||
return $this->id; |
||||
} |
||||
|
||||
public function setId(string $id): static |
||||
{ |
||||
$this->id = $id; |
||||
|
||||
return $this; |
||||
} |
||||
|
||||
public function getTorrentId(): ?int |
||||
{ |
||||
return $this->torrentId; |
||||
} |
||||
|
||||
public function setTorrentId(int $torrentId): static |
||||
{ |
||||
$this->torrentId = $torrentId; |
||||
|
||||
return $this; |
||||
} |
||||
|
||||
public function getUserId(): ?int |
||||
{ |
||||
return $this->userId; |
||||
} |
||||
|
||||
public function setUserId(int $userId): static |
||||
{ |
||||
$this->userId = $userId; |
||||
|
||||
return $this; |
||||
} |
||||
|
||||
public function getAdded(): ?int |
||||
{ |
||||
return $this->added; |
||||
} |
||||
|
||||
public function setAdded(int $added): static |
||||
{ |
||||
$this->added = $added; |
||||
|
||||
return $this; |
||||
} |
||||
|
||||
public function getValue(): array |
||||
{ |
||||
return $this->value; |
||||
} |
||||
|
||||
public function setValue(array $value): static |
||||
{ |
||||
$this->value = $value; |
||||
|
||||
return $this; |
||||
} |
||||
|
||||
public function isApproved(): ?bool |
||||
{ |
||||
return $this->approved; |
||||
} |
||||
|
||||
public function setApproved(bool $approved): static |
||||
{ |
||||
$this->approved = $approved; |
||||
|
||||
return $this; |
||||
} |
||||
} |
@ -0,0 +1,23 @@
@@ -0,0 +1,23 @@
|
||||
<?php |
||||
|
||||
namespace App\Repository; |
||||
|
||||
use App\Entity\TorrentCategories; |
||||
use Doctrine\Bundle\DoctrineBundle\Repository\ServiceEntityRepository; |
||||
use Doctrine\Persistence\ManagerRegistry; |
||||
|
||||
/** |
||||
* @extends ServiceEntityRepository<TorrentCategories> |
||||
* |
||||
* @method TorrentCategories|null find($id, $lockMode = null, $lockVersion = null) |
||||
* @method TorrentCategories|null findOneBy(array $criteria, array $orderBy = null) |
||||
* @method TorrentCategories[] findAll() |
||||
* @method TorrentCategories[] findBy(array $criteria, array $orderBy = null, $limit = null, $offset = null) |
||||
*/ |
||||
class TorrentCategoriesRepository extends ServiceEntityRepository |
||||
{ |
||||
public function __construct(ManagerRegistry $registry) |
||||
{ |
||||
parent::__construct($registry, TorrentCategories::class); |
||||
} |
||||
} |
@ -0,0 +1,109 @@
@@ -0,0 +1,109 @@
|
||||
{% extends 'default/layout.html.twig' %} |
||||
{% block title %}{{'Edit categories'|trans }} - {{'Torrent'|trans }} #{{ torrentId }} - {{ name }}{% endblock %} |
||||
{% block main_content %} |
||||
<div class="padding-24-px margin-y-8-px border-radius-3-px background-color-night"> |
||||
<div class="margin-b-16-px padding-b-16-px border-bottom-default"> |
||||
<h1> |
||||
{{'Edit categories for torrent' | trans }} |
||||
<a href="{{ path('torrent_info', { torrentId : torrentId }) }}">#{{ torrentId }}</a> |
||||
</h1> |
||||
</div> |
||||
<form name="categories" method="post" action="{{ path('torrent_categories_edit', { torrentId : torrentId }) }}"> |
||||
<div class="margin-y-16-px"> |
||||
<label for="categories"> |
||||
{{'Content category'|trans }} |
||||
</label> |
||||
<sub class="opacity-0 parent-hover-opacity-09" title="{{ 'This torrent have selected categories' | trans }}"> |
||||
<svg xmlns="http://www.w3.org/2000/svg" width="13" height="13" fill="currentColor" viewBox="0 0 16 16"> |
||||
<path d="M8 16A8 8 0 1 0 8 0a8 8 0 0 0 0 16zm.93-9.412-1 4.705c-.07.34.029.533.304.533.194 0 .487-.07.686-.246l-.088.416c-.287.346-.92.598-1.465.598-.703 0-1.002-.422-.808-1.319l.738-3.468c.064-.293.006-.399-.287-.47l-.451-.081.082-.381 2.29-.287zM8 5.5a1 1 0 1 1 0-2 1 1 0 0 1 0 2z"/> |
||||
</svg> |
||||
</sub> |
||||
{% for error in form.categories.error %} |
||||
<div class="text-color-red margin-y-8-px"> |
||||
{{ error }} |
||||
</div> |
||||
{% endfor %} |
||||
<div class="margin-t-8-px margin-b-16-px"> |
||||
{% for category in categories | sort %} |
||||
<div class="margin-t-8-px margin-b-4-px margin-r-8-px display-inline-block min-width-120-px"> |
||||
{% if category in form.categories.attribute.value %} |
||||
<input type="checkbox" name="categories[]" id="{{ category }}" value="{{ category }}" checked="checked" /> |
||||
{% else %} |
||||
<input type="checkbox" name="categories[]" id="{{ category }}" value="{{ category }}" /> |
||||
{% endif %} |
||||
<label class="margin-l-4-px" for="{{ category }}"> |
||||
{{ category | u.title }} |
||||
</label> |
||||
</div> |
||||
{% endfor %} |
||||
{# |
||||
<option class="padding-x-8-px padding-y-8-px" value="other"> |
||||
{{'Other...'|trans }} |
||||
</option> |
||||
#} |
||||
</div> |
||||
<div class="margin-b-16-px border-bottom-default"></div> |
||||
</div> |
||||
<div class="text-right"> |
||||
<a class="margin-r-8-px" href="{{ path('torrent_info', { torrentId : torrentId }) }}"> |
||||
{{'cancel'|trans }} |
||||
</a> |
||||
<input class="button-green" type="submit" value="{{'Submit'|trans }}" /> |
||||
</div> |
||||
</form> |
||||
</div> |
||||
{% for edition in editions %} |
||||
<div class="padding-x-24-px padding-y-16-px margin-y-8-px border-radius-3-px {% if edition.active %}background-color-night-light{% else %}background-color-night{% endif %} "> |
||||
{% if edition.active %} |
||||
{{ edition.added | format_ago }} |
||||
{% else %} |
||||
<a href="{{ path('torrent_categories_edit', { torrentId : torrentId, torrentCategoriesId : edition.id }) }}"> |
||||
{{ edition.added | format_ago }} |
||||
</a> |
||||
{% endif %} |
||||
{{ 'by'|trans }} |
||||
<a href="{{ path('user_info', { userId : edition.user.id }) }}"> |
||||
<img class="border-radius-50 border-color-default vertical-align-middle" src="{{ edition.user.identicon }}" alt="{{'identicon'|trans }}" /> |
||||
</a> |
||||
<div class="float-right"> |
||||
{% if session.moderator or session.owner %} |
||||
<a class="margin-r-8-px text-color-red" href="{{ path('torrent_categories_delete', { torrentId : torrentId, torrentCategoriesId : edition.id }) }}" title="{{ 'Delete' | trans }}"> |
||||
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-x-circle" viewBox="0 0 16 16"> |
||||
<path d="M8 15A7 7 0 1 1 8 1a7 7 0 0 1 0 14zm0 1A8 8 0 1 0 8 0a8 8 0 0 0 0 16z"/> |
||||
<path d="M4.646 4.646a.5.5 0 0 1 .708 0L8 7.293l2.646-2.647a.5.5 0 0 1 .708.708L8.707 8l2.647 2.646a.5.5 0 0 1-.708.708L8 8.707l-2.646 2.647a.5.5 0 0 1-.708-.708L7.293 8 4.646 5.354a.5.5 0 0 1 0-.708z"/> |
||||
</svg> |
||||
</a> |
||||
{% endif %} |
||||
{% if edition.approved %} |
||||
{% if session.moderator %} |
||||
<a href="{{ path('torrent_categories_approve', { torrentId : torrentId, torrentCategoriesId : edition.id }) }}" title="{{ 'Disapprove' | trans }}"> |
||||
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" viewBox="0 0 16 16"> |
||||
<path d="M16 8A8 8 0 1 1 0 8a8 8 0 0 1 16 0zm-3.97-3.03a.75.75 0 0 0-1.08.022L7.477 9.417 5.384 7.323a.75.75 0 0 0-1.06 1.06L6.97 11.03a.75.75 0 0 0 1.079-.02l3.992-4.99a.75.75 0 0 0-.01-1.05z"/> |
||||
</svg> |
||||
</a> |
||||
{% else %} |
||||
<span title="{{ 'Approved' | trans }}"> |
||||
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" viewBox="0 0 16 16"> |
||||
<path d="M16 8A8 8 0 1 1 0 8a8 8 0 0 1 16 0zm-3.97-3.03a.75.75 0 0 0-1.08.022L7.477 9.417 5.384 7.323a.75.75 0 0 0-1.06 1.06L6.97 11.03a.75.75 0 0 0 1.079-.02l3.992-4.99a.75.75 0 0 0-.01-1.05z"/> |
||||
</svg> |
||||
</span> |
||||
{% endif %} |
||||
{% else %} |
||||
{% if session.moderator %} |
||||
<a href="{{ path('torrent_categories_approve', { torrentId : torrentId, torrentCategoriesId : edition.id }) }}" title="{{ 'Approve' | trans }}"> |
||||
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-hourglass" viewBox="0 0 16 16"> |
||||
<path d="M2 1.5a.5.5 0 0 1 .5-.5h11a.5.5 0 0 1 0 1h-1v1a4.5 4.5 0 0 1-2.557 4.06c-.29.139-.443.377-.443.59v.7c0 .213.154.451.443.59A4.5 4.5 0 0 1 12.5 13v1h1a.5.5 0 0 1 0 1h-11a.5.5 0 1 1 0-1h1v-1a4.5 4.5 0 0 1 2.557-4.06c.29-.139.443-.377.443-.59v-.7c0-.213-.154-.451-.443-.59A4.5 4.5 0 0 1 3.5 3V2h-1a.5.5 0 0 1-.5-.5zm2.5.5v1a3.5 3.5 0 0 0 1.989 3.158c.533.256 1.011.791 1.011 1.491v.702c0 .7-.478 1.235-1.011 1.491A3.5 3.5 0 0 0 4.5 13v1h7v-1a3.5 3.5 0 0 0-1.989-3.158C8.978 9.586 8.5 9.052 8.5 8.351v-.702c0-.7.478-1.235 1.011-1.491A3.5 3.5 0 0 0 11.5 3V2h-7z"/> |
||||
</svg> |
||||
</a> |
||||
{% else %} |
||||
<span title="{{ 'Waiting for approve' | trans }}"> |
||||
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-hourglass" viewBox="0 0 16 16"> |
||||
<path d="M2 1.5a.5.5 0 0 1 .5-.5h11a.5.5 0 0 1 0 1h-1v1a4.5 4.5 0 0 1-2.557 4.06c-.29.139-.443.377-.443.59v.7c0 .213.154.451.443.59A4.5 4.5 0 0 1 12.5 13v1h1a.5.5 0 0 1 0 1h-11a.5.5 0 1 1 0-1h1v-1a4.5 4.5 0 0 1 2.557-4.06c.29-.139.443-.377.443-.59v-.7c0-.213-.154-.451-.443-.59A4.5 4.5 0 0 1 3.5 3V2h-1a.5.5 0 0 1-.5-.5zm2.5.5v1a3.5 3.5 0 0 0 1.989 3.158c.533.256 1.011.791 1.011 1.491v.702c0 .7-.478 1.235-1.011 1.491A3.5 3.5 0 0 0 4.5 13v1h7v-1a3.5 3.5 0 0 0-1.989-3.158C8.978 9.586 8.5 9.052 8.5 8.351v-.702c0-.7.478-1.235 1.011-1.491A3.5 3.5 0 0 0 11.5 3V2h-7z"/> |
||||
</svg> |
||||
</span> |
||||
{% endif %} |
||||
{% endif %} |
||||
</div> |
||||
</div> |
||||
{% endfor %} |
||||
{% endblock %} |
Loading…
Reference in new issue