Test implementation of torrent data reading. Entities, repositories, templates.

This commit is contained in:
Alexey Skobkin 2018-06-20 22:30:00 +03:00
parent 7c97b7821b
commit 0fe7910fd3
9 changed files with 319 additions and 0 deletions

View file

@ -1,3 +1,7 @@
#index:
# path: /
# controller: App\Controller\DefaultController::index
test:
path: /
controller: App\Controller\TestController::test

0
public/css/style.css Normal file
View file

BIN
public/favicon.ico Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

View file

@ -0,0 +1,18 @@
<?php
namespace App\Controller;
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use Symfony\Component\HttpFoundation\Response;
class TestController extends Controller
{
public function test(\App\Repository\Torrent $torrentRepo)
{
$torrents = $torrentRepo->getLastTorrents(10);
return $this->render('torrent_list.html.twig', [
'torrents' => $torrents,
]);
}
}

64
src/Entity/File.php Normal file
View file

@ -0,0 +1,64 @@
<?php
namespace App\Entity;
use Doctrine\ORM\Mapping as ORM;
/**
* @ORM\Table(name="files", indexes={
* @ORM\Index(name="file_info_hash_index", columns={"torrent_id"})
* })
* @ORM\Entity(readOnly=true)
*/
class File
{
/**
* @var int
*
* @ORM\Column(name="id", type="integer")
* @ORM\Id
*/
private $id;
/**
* @var int
*
* @ORM\ManyToOne(targetEntity="App\Entity\Torrent", inversedBy="files")
* @ORM\JoinColumn(name="torrent_id")
*/
private $torrent;
/**
* @var int
*
* @ORM\Column(name="size", type="integer", nullable=false)
*/
private $size;
/**
* @var string
*
* @ORM\Column(name="path", type="text", nullable=false)
*/
private $path;
public function getId(): int
{
return $this->id;
}
public function getTorrent(): int
{
return $this->torrent;
}
public function getSize(): int
{
return $this->size;
}
public function getPath(): string
{
return $this->path;
}
}

97
src/Entity/Torrent.php Normal file
View file

@ -0,0 +1,97 @@
<?php
namespace App\Entity;
use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\ORM\Mapping as ORM;
/**
* @ORM\Table(name="torrents", indexes={
* @ORM\Index(name="discovered_on_index", columns={"discovered_on"}),
* @ORM\Index(name="info_hash_index", columns={"info_hash"})
* })
* @ORM\Entity(readOnly=true)
*/
class Torrent
{
/**
* @var int
*
* @ORM\Column(name="id", type="integer")
* @ORM\Id
*/
private $id;
/**
* @var string
*
* @ORM\Column(name="info_hash", type="blob", nullable=false)
*/
private $infoHash;
/**
* @var string
*
* @ORM\Column(name="name", type="text", nullable=false)
*/
private $name;
/**
* @var int
*
* @ORM\Column(name="total_size", type="integer", nullable=false)
*/
private $totalSize;
/**
* @var int
*
* @ORM\Column(name="discovered_on", type="integer", nullable=false)
*/
private $discoveredOn;
/**
* @var File[]|ArrayCollection
*
* @ORM\OneToMany(targetEntity="App\Entity\File", fetch="EXTRA_LAZY", mappedBy="torrent")
*/
private $files;
public function getId(): int
{
return $this->id;
}
public function getInfoHash()
{
return $this->infoHash;
}
public function getInfoHashAsHex()
{
return bin2hex(stream_get_contents($this->infoHash));
}
public function getName(): string
{
return $this->name;
}
public function getTotalSize(): int
{
return $this->totalSize;
}
public function getDiscoveredOn(): int
{
return $this->discoveredOn;
}
/**
* @return File[]|ArrayCollection
*/
public function getFiles(): iterable
{
return $this->files;
}
}

View file

@ -0,0 +1,24 @@
<?php
namespace App\Repository;
use Doctrine\Bundle\DoctrineBundle\Repository\ServiceEntityRepository;
use Symfony\Bridge\Doctrine\RegistryInterface;
class Torrent extends ServiceEntityRepository
{
public function __construct(RegistryInterface $registry)
{
parent::__construct($registry, \App\Entity\Torrent::class);
}
public function getLastTorrents(int $number): array
{
$qb = $this->createQueryBuilder('t')
->orderBy('t.discoveredOn', 'DESC')
->setMaxResults($number)
;
return $qb->getQuery()->getResult();
}
}

79
templates/base.html.twig Normal file
View file

@ -0,0 +1,79 @@
<!doctype html>
<html lang="en">
<head>
{% block meta %}
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<meta name="description" content="">
<meta name="author" content="">
{% endblock %}
<!--<link rel="icon" href="images/favicon.ico">-->
<title>{% block title %}Magnetoco Web{% endblock %}</title>
{% block css %}
<!-- Bootstrap core CSS -->
<link href="https://stackpath.bootstrapcdn.com/bootstrap/4.1.1/css/bootstrap.min.css" rel="stylesheet">
<!-- Custom styles for this template -->
<!--<link href="starter-template.css" rel="stylesheet">-->
{% endblock %}
</head>
<body>
<nav class="navbar navbar-expand-md navbar-dark bg-dark fixed-top">
<a class="navbar-brand" href="#">Navbar</a>
<button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#navbarsExampleDefault" aria-controls="navbarsExampleDefault" aria-expanded="false" aria-label="Toggle navigation">
<span class="navbar-toggler-icon"></span>
</button>
<div class="collapse navbar-collapse" id="navbarsExampleDefault">
<ul class="navbar-nav mr-auto">
<li class="nav-item active">
<a class="nav-link" href="#">Home <span class="sr-only">(current)</span></a>
</li>
<li class="nav-item">
<a class="nav-link" href="#">Link</a>
</li>
<li class="nav-item">
<a class="nav-link disabled" href="#">Disabled</a>
</li>
<li class="nav-item dropdown">
<a class="nav-link dropdown-toggle" href="https://example.com" id="dropdown01" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">Dropdown</a>
<div class="dropdown-menu" aria-labelledby="dropdown01">
{% block navbar_menu_items %}
<a class="dropdown-item" href="#">Action</a>
<a class="dropdown-item" href="#">Another action</a>
<a class="dropdown-item" href="#">Something else here</a>
{% endblock %}
</div>
</li>
</ul>
<form class="form-inline my-2 my-lg-0">
<input class="form-control mr-sm-2" type="text" placeholder="Search" aria-label="Search">
<button class="btn btn-outline-success my-2 my-sm-0" type="submit">Search</button>
</form>
</div>
</nav>
<main role="main" class="container">
{% block content %}
<div class="well">
<h1>Bootstrap starter template</h1>
<p class="lead">Use this document as a way to quickly start any new project.<br> All you get is this text and a mostly barebones HTML document.</p>
</div>
{% endblock %}
</main><!-- /.container -->
{% block javascript %}
<!-- Bootstrap core JavaScript
================================================== -->
<!-- Placed at the end of the document so the pages load faster -->
<script src="https://code.jquery.com/jquery-3.3.1.slim.min.js"></script>
<script>window.jQuery || document.write('<script src="../../assets/js/vendor/jquery-slim.min.js"><\/script>')</script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.14.3/umd/popper.min.js"></script>
<script src="https://stackpath.bootstrapcdn.com/bootstrap/4.1.1/js/bootstrap.min.js"></script>
{% endblock %}
</body>
</html>

View file

@ -0,0 +1,33 @@
{% extends 'base.html.twig' %}
{% block content %}
<table class="table">
<thead>
<th scope="col">ID</th>
<th scope="col">Name</th>
<th scope="col">Size</th>
<th scope="col">Discovered</th>
<th scope="col">Files</th>
</thead>
{# @var torrent \App\Entity\\App\Entity\Torrent #}
{% for torrent in torrents %}
<tr>
<td>{{ torrent.id }}</td>
<td>
<a href="magnet:?xt=urn:btih:{{ torrent.infoHashAsHex }}&dn={{ torrent.name|url_encode }}">{{ torrent.name }}</a>
</td>
<td>{{ torrent.totalSize }}</td>
<td>{{ torrent.discoveredOn }}</td>
<td>
{#
<ul>
{% for file in torrent.files %}
<li>{{ file.path }}</li>
{% endfor %}
</ul>
#}
</td>
</tr>
{% endfor %}
</table>
{% endblock %}