<?php
namespace App\Controller;
use App\Entity\Post;
use App\Form\PostType;
// use App\Form\PostFormType;
use Doctrine\ORM\EntityManagerInterface;
use App\Repository\PostRepository;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\Routing\Annotation\Route;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\IsGranted;
use Symfony\Component\HttpFoundation\RedirectResponse;
use Doctrine\Persistence\ManagerRegistry;
use Doctrine\DBAL\Types\Types;
use Symfony\Component\HttpFoundation\RequestStack;
use Knp\Component\Pager\PaginatorInterface;
use Symfony\Component\HttpFoundation\File\Exception\FileException;
use Imagine\Gd\Imagine;
use Symfony\Component\HttpFoundation\File\File;
use Imagine\Image\Box;
use Imagine\Image\ManipulatorInterface;
use Symfony\Component\Filesystem\Filesystem;
class PostController extends AbstractController
{
private $entityManager;
private $doctrine;
private $requestStack;
public function __construct(EntityManagerInterface $entityManager, ManagerRegistry $doctrine, RequestStack $requestStack)
{
$this->entityManager = $entityManager;
$this->doctrine = $doctrine;
$this->requestStack = $requestStack;
}
#[Route('/', name: 'home', methods: ['GET'])]
public function home(PostRepository $postRepository): Response
{
$posts = $postRepository->findAll();
return $this->render('post/home.html.twig', [
'posts' => $posts,
]);
}
#[Route('/posts/{id<\d+>}', name: 'post_by_id', methods: ['GET'])]
public function byId(int $id, PostRepository $postRepository): Response
{
$post = $postRepository->find($id);
if (!$post) {
throw $this->createNotFoundException('Статья не найдена.');
}
$photo = $post->getPhoto();
return $this->render('post/by-id.html.twig', [
'post' => $post,
'photo' => $photo,
'description' => $post->getTitle(),
]);
}
#[Route('/posts/genre/{genre}', name: 'post_by_genre', methods: ['GET'])]
public function byGenre(string $genre, PostRepository $postRepository, PaginatorInterface $paginator, Request $request): Response
{
$query = $postRepository->createQueryBuilder('p')
->where('p.genre = :genre')
->andWhere('p.genre != :excludedGenre')
->setParameter('genre', $genre)
->setParameter('excludedGenre', 'non-genre')
->getQuery();
$page = $request->query->getInt('page', 1);
$pageSize = 6; // Количество постов на странице
$pagination = $paginator->paginate($query, $page, $pageSize);
$genreCounts = $this->getPostCountByGenre($postRepository);
return $this->render('post/by-genre.html.twig', [
'posts' => $pagination,
'genre' => $genre,
'genreCounts' => $genreCounts,
'pagination' => $pagination,
]);
}
#[Route('/admin/posts', name: 'app_admin_posts')]
#[IsGranted('ROLE_ADMIN')]
public function index(PostRepository $postRepository): Response
{
$posts = $postRepository->findAll();
return $this->render('admin/posts.html.twig', [
'posts' => $posts,
]);
}
#[Route('/admin/posts/{id}/edit', name: 'app_admin_post_edit')]
#[IsGranted('ROLE_ADMIN')]
public function edit(Request $request, Post $post, EntityManagerInterface $entityManager): Response
{
$form = $this->createForm(PostType::class, $post);
$form->handleRequest($request);
// Получение ссылки на текущую фотографию
$currentPhoto = $post->getPhoto();
if ($form->isSubmitted() && $form->isValid()) {
$epigraph = $form->get('epigraph')->getData();
$post->setEpigraph($epigraph);
// Получение значения поля "photoFile" из формы
$photoFile = $form->get('photoFile')->getData();
// Загрузка новой фотографии, если она была выбрана
if ($photoFile) {
// Удаление старой фотографии, если она существует
if ($post->getPhoto()) {
$oldPhotoPath = $this->getParameter('photos_directory') . '/' . $post->getPhoto();
if (file_exists($oldPhotoPath)) {
unlink($oldPhotoPath);
}
}
// Создаем временную папку, если она не существует
$tempDir = $this->getParameter('kernel.project_dir') . '/tmp';
if (!file_exists($tempDir)) {
mkdir($tempDir);
}
$newFilename = 'img-post' . $post->getId() . '.' . $photoFile->guessExtension();
// Создаем полный путь к временному файлу
$tempFilename = $tempDir . '/' . $newFilename;
// Создаем новый объект класса Imagine и получаем фото
$imagine = new Imagine();
$image = $imagine->open($photoFile->getPathname());
$maxWidth = 800;
$maxHeight = 800;
$image->resize($image->getSize()->widen($maxWidth)->heighten($maxHeight));
// Сохраняем сжатое изображение во временный файл
$tempFilename = sys_get_temp_dir() . '/' . $newFilename;
$image->save($tempFilename, ['jpeg_quality' => 80]);
// Создаем новый экземпляр файла из временного файла
$compressedPhoto = new File($tempFilename);
// Перемещаем файл в каталог назначения и сохраняем сжатую фотографию
try {
$photoFile->move(
$this->getParameter('photos_directory') . '/post-img',
$newFilename
);
// Обновление ссылки на фотографию в объекте Post
$post->setPhoto('post-img/' . $newFilename);
} catch (FileException $e) {
$this->addFlash('error', 'An error occurred while uploading the photo.');
return $this->redirectToRoute('app_admin');
}
}
$entityManager->flush();
$this->addFlash('success', 'Post updated successfully!');
return new RedirectResponse($this->generateUrl('app_admin_posts'));
}
return $this->render('admin/post_edit.html.twig', [
'form' => $form->createView(),
'currentPhoto' => $currentPhoto,
'post' => $post,
]);
}
#[Route('/admin/posts/{id}/delete', name: 'app_admin_post_delete')]
#[IsGranted('ROLE_ADMIN')]
public function delete(Request $request, Post $post, EntityManagerInterface $entityManager, Filesystem $filesystem): Response
{
if ($this->isCsrfTokenValid('delete_post_' . $post->getId(), $request->request->get('_token'))) {
$photo = $post->getPhoto();
if ($photo) {
// Полный путь к файлу
$filePath = $this->getParameter('photos_directory') . '/' . $photo;
if ($filesystem->exists($filePath)) {
$filesystem->remove($filePath);
}
}
$entityManager->remove($post);
$entityManager->flush();
$this->addFlash('success', 'Post deleted successfully!');
}
return new RedirectResponse($this->generateUrl('app_admin_posts'));
}
#[Route('/admin/posts/new', name: 'app_admin_post_new')]
#[IsGranted('ROLE_ADMIN')]
public function new(Request $request): Response
{
$post = new Post();
$form = $this->createForm(PostType::class, $post);
$form->handleRequest($request);
if ($form->isSubmitted() && $form->isValid()) {
$epigraph = $form->get('epigraph')->getData();
$post->setEpigraph($epigraph);
// Получение значения поля "photoFile" из формы
$photoFile = $form->get('photoFile')->getData();
// Загрузка фотографии, если она была выбрана
if ($photoFile) {
$newFilename = uniqid() . '.' . $photoFile->guessExtension();
// Создается новый объект класса Imagine и получаем фото
$imagine = new Imagine();
$image = $imagine->open($photoFile->getPathname());
// Изменение размера и сжатие изображения
$maxWidth = 800;
$maxHeight = 800;
$image->resize($image->getSize()->widen($maxWidth)->heighten($maxHeight));
// Создайте временную папку, если она не существует
$tempDir = $this->getParameter('kernel.project_dir') . '/tmp';
if (!file_exists($tempDir)) {
mkdir($tempDir);
}
// Сохраните сжатое изображение во временный файл
$tempFilename = $tempDir . '/' . $newFilename;
$image->save($tempFilename, ['jpeg_quality' => 80]);
// Создайте новый экземпляр файла из временного файла
$compressedPhoto = new File($tempFilename);
// Переместите файл в каталог назначения и сохраните сжатую фотографию
try {
$compressedPhoto->move(
$this->getParameter('photos_directory') . '/post-img',
$newFilename
);
// Установка ссылки на фотографию в объекте Post
$post->setPhoto('post-img/' . $newFilename);
} catch (FileException $e) {
$this->addFlash('error', 'An error occurred while uploading the photo.');
return $this->redirectToRoute('app_admin');
}
}
$this->entityManager->persist($post);
$this->entityManager->flush();
$this->addFlash('success', 'Post created successfully!');
return $this->redirectToRoute('app_admin_posts');
}
return $this->render('admin/post_new.html.twig', [
'form' => $form->createView(),
]);
}
#[Route('/posts', name: 'app_posts')]
public function posts(Request $request, PostRepository $postRepository, PaginatorInterface $paginator): Response
{
$genres = $postRepository->getDistinctGenres();
// Получить выбранный жанр из запроса
$selectedGenre = $request->query->get('genre');
// Получить все посты или посты определенного жанра
$query = $postRepository->createQueryBuilder('p');
// Определить текущую страницу
$page = $request->query->getInt('page', 1);
$pageSize = 6; // Number of posts per page
if ($selectedGenre) {
$query->andWhere('p.genre = :genre')
->setParameter('genre', $selectedGenre);
}
$query = $query->getQuery();
// применяем пагинацию
$pagination = $paginator->paginate($query, $page, $pageSize);
// Получить общее количество элементов в определенной категории
$totalItems = $pagination->getTotalItemCount();
// Рассчитать общее количество страниц
$totalPages = ceil($totalItems / $pageSize);
$genreCounts = $this->getPostCountByGenre($postRepository);
return $this->render('post/all_posts.html.twig', [
'genres' => $genres,
'pagination' => $pagination,
'genreCounts' => $genreCounts,
'totalPages' => $totalPages,
'currentPage' => $page,
'selectedGenre' => $selectedGenre, // Передать выбранный жанр в шаблон
]);
}
public function getPostCountByGenre(PostRepository $postRepository): array
{
// Получаем список уникальных жанров
$genres = $postRepository->findDistinctGenres();
// Получаем количество постов для каждого жанра
$postCounts = $postRepository->countPostsByGenre();
// Создаем массив для хранения количества постов по жанрам
$genreCounts = [];
// Проходим по каждому жанру и сохраняем количество постов для этого жанра
foreach ($genres as $genre) {
$genreCounts[$genre['genre']] = $postCounts[$genre['genre']] ?? 0;
}
// Возвращаем массив с количеством постов для каждого жанра
return $genreCounts;
}
}