<?php
namespace App\Controller;
use App\Form\AssetSearchSimpleType;
use App\Form\ChangePasswordFormType;
use App\Form\AccountFormType;
use App\Repository\AssetLogRepository;
use App\Repository\AssetRepository;
use App\Repository\LanguageRepository;
use App\Repository\ProductRepository;
use App\Repository\UserRepository;
use App\Service\UserAccessService;
use Doctrine\ORM\NonUniqueResultException;
use Doctrine\ORM\NoResultException;
use FilesystemIterator;
use imagick;
use RecursiveIteratorIterator;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\IsGranted;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\Finder\Iterator\RecursiveDirectoryIterator;
use Symfony\Component\HttpFoundation\BinaryFileResponse;
use Symfony\Component\HttpFoundation\JsonResponse;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpFoundation\ResponseHeaderBag;
use Symfony\Component\Routing\Annotation\Route;
use Symfony\Component\Security\Core\Encoder\UserPasswordEncoderInterface;
class AppController extends AbstractController
{
private $assetRepository;
private $userRepository;
private $accessService;
private $assetLogRepository;
private $languageRepository;
private $productRepository;
/**
* AppController constructor.
* @param AssetRepository $assetRepository
* @param UserRepository $userRepository
* @param UserAccessService $accessService
* @param AssetLogRepository $assetLogRepository
* @param LanguageRepository $languageRepository
* @param ProductRepository $productRepository
*/
public function __construct(
AssetRepository $assetRepository,
UserRepository $userRepository,
UserAccessService $accessService,
AssetLogRepository $assetLogRepository,
LanguageRepository $languageRepository,
ProductRepository $productRepository
)
{
$this->assetRepository = $assetRepository;
$this->userRepository = $userRepository;
$this->accessService = $accessService;
$this->assetLogRepository = $assetLogRepository;
$this->languageRepository = $languageRepository;
$this->productRepository = $productRepository;
}
/**
* @Route("/", name="home")
* @IsGranted("IS_AUTHENTICATED_REMEMBERED")
*/
public function index(Request $request): Response
{
$user = $this->getUser();
$filterData = $this->accessService->getUserAccessFilterData();
$assets = $this->assetRepository->findLatestByUser($filterData);
$products = $this->productRepository->findLatestByUser($filterData);
// Smarthub statistics
if($this->isGranted("ROLE_SMART_STAFF")) {
$generalTotals = $this->getGeneralTotals();
$userTotals = $this->getUserTotals();
$languageTotals = $this->getLanguageData();
}
// Subscribe to newsletter form
$accountForm = $this->createForm(AccountFormType::class, $user);
$accountForm->handleRequest($request);
if ($accountForm->isSubmitted() && $accountForm->isValid()) {
$user->setIsSubscribed(
$accountForm->get('isSubscribed')->getData()
);
$this->getDoctrine()->getManager()->flush();
$this->addFlash(
'success',
"Successfully saved settings."
);
return $this->redirectToRoute('home');
}
// Quick search
$filterData = $this->accessService->getUserAccessFilterData();
$assetSearchSimpleForm = $this->createForm(AssetSearchSimpleType::class, null, [
'category' => $filterData['category']
]);
$assetSearchSimpleForm->handleRequest($request);
if ($assetSearchSimpleForm->isSubmitted() && $assetSearchSimpleForm->isValid()) {
$product = $assetSearchSimpleForm->get('product')->getData();
return $this->redirectToRoute('asset_index', ['product' => $product->getId()]);
}
return $this->render('app/index.html.twig', [
'products' => $products,
'assets' => array_splice($assets, 0,6),
'generalTotals' => $generalTotals ?? null,
'userTotals' => $userTotals ?? null,
'languageTotals' => $languageTotals ?? null,
'notices' => $this->getNotices(),
'accountForm' => $accountForm->createView(),
'assetSearchSimpleForm' => $assetSearchSimpleForm->createView(),
]);
}
/**
* @Route("/list", name="smarthub_stats_list", options={"expose"="true"}, methods={"GET","POST"})
* @param Request $request
* @return Response
*/
public function list(Request $request): Response
{
if(!$this->isGranted("ROLE_SMART_STAFF")) {
return new JsonResponse();
}
$start = $request->query->get('start');
$end = $request->query->get('end');
$totalsThisYear = $this->getGeneralData($start, $end);
$topUsers = $this->getTopUsers($start, $end);
$topDownloads = $this->assetLogRepository->getPopularDownloads($start, $end);
$topAssets = $this->assetRepository->findTopDownloadsById(array_column($topDownloads, 'id'));
$ids = array_column($topDownloads, 'logs', 'id');
foreach($topAssets as &$asset) {
$asset['thumbnail'] = $asset[0]->getThumbnail();
$values = $asset[0]->getType()->getValues();
$v = [];
foreach($values as $value) {
$v[] = $value->getName();
}
$id = $asset[0]->getId();
$asset['types'] = $v;
$asset['logs'] = $ids[$id];
foreach($asset[0]->getFiles() as $file) {
if(!$file->getDeleted()) {
$asset['route'] = $this->generateUrl('file_download', [
'id' =>$file->getId(),
]);
}
}
}
usort($topAssets, function($a, $b) {
return $a['logs'] < $b['logs'];
});
$response = new JsonResponse();
$response->setData(
[
'topDownloads' => $topAssets,
'totalsThisYear' => $totalsThisYear,
'topUsers' => $topUsers,
]
);
return $response;
}
/**
* @return array
* @throws NoResultException
* @throws NonUniqueResultException
*/
private function getGeneralTotals(): array
{
$totalAssets = $this->assetRepository->getTotal();
$totalUploadFiles = $this->assetRepository->getTotalFileType();
$totalTextFiles = $this->assetRepository->getTotalTextType();
$totalDownloads = $this->assetLogRepository->getTotalDownloads();
return [
'Total Assets' => $totalAssets,
'Total Files' => $totalUploadFiles,
'Total Texts' => $totalTextFiles,
'Total Downloads' => $totalDownloads,
'Assets Filesize' => 'N/A',
'Archive Filesize' => 'N/A',
];
}
/**
* @return array
* @throws NoResultException
* @throws NonUniqueResultException
*/
private function getLanguageData(): array
{
$languages = $this->languageRepository->findAll();
$totalDownloadsForLanguage = [];
foreach ($languages as $language) {
$totalDownloadsForLanguage[$language->getName()] = $this->assetLogRepository->getTotalDownloadsForLanguage($language->getId());
}
return $totalDownloadsForLanguage;
}
/**
* @param $start
* @param $end
* @return array
* @throws NoResultException
* @throws NonUniqueResultException
*/
private function getGeneralData($start, $end): array
{
$data = [];
$data[0] = $this->assetRepository->getTotalForDates($start, $end);
$data[1] = $this->assetLogRepository->getTotalDownloadsForDates($start, $end);
$data[2] = $this->userRepository->getTotalForDates($start, $end);
return $data;
}
/**
* @return array
*/
private function getUserTotals(): array
{
$totalUsers = $this->userRepository->getTotal();
$totalVerifiedUsers = $this->userRepository->getTotalVerified();
$totalSubscribed = $this->userRepository->getTotalSubscribed();
return [
'Total Users' => $totalUsers,
'Total Verified Users' => $totalVerifiedUsers,
'Total Subscribed' => $totalSubscribed,
];
}
/**
* @param $start
* @param $end
* @return array
*/
private function getTopUsers($start, $end): array
{
$topExternalDownloaded = $this->assetLogRepository->getPopularExternalDownloaders($start, $end);
$topSmartDownloaded = $this->assetLogRepository->getPopularSmartDownloaders($start, $end);
return [
'Top Users (External)' => $topExternalDownloaded,
'Top Users (Smart)' => $topSmartDownloaded,
];
}
/**
* @Route("/account", name="account")
* @IsGranted("IS_AUTHENTICATED_FULLY")
* @param Request $request
* @param UserPasswordEncoderInterface $passwordEncoder
* @return Response
*/
public function account(Request $request, UserPasswordEncoderInterface $passwordEncoder): Response
{
$user = $this->getUser();
$passwordform = $this->createForm(ChangePasswordFormType::class);
$accountform = $this->createForm(AccountFormType::class, $user);
$passwordform->handleRequest($request);
if ($passwordform->isSubmitted() && $passwordform->isValid()) {
$encodedPassword = $passwordEncoder->encodePassword(
$user,
$passwordform->get('plainPassword')->getData()
);
$user->setPassword($encodedPassword);
$this->getDoctrine()->getManager()->flush();
$this->addFlash(
'success',
"Password successfully changed."
);
return $this->redirectToRoute('home');
}
$accountform->handleRequest($request);
if ($accountform->isSubmitted() && $accountform->isValid()) {
$user->setIsSubscribed(
$accountform->get('isSubscribed')->getData()
);
$this->getDoctrine()->getManager()->flush();
$this->addFlash(
'success',
"Successfully saved settings."
);
return $this->redirectToRoute('home');
}
return $this->render('user/account.html.twig', [
'user' => $user,
'passwordform' => $passwordform->createView(),
'accountform' => $accountform->createView(),
]);
}
/**
* @Route("/phpinfo", name="phpinfo")
* @IsGranted("ROLE_SUPER_ADMIN")
*/
public function phpinfo(): Response
{
phpinfo();
exit(0);
}
/**
* @param $path
* @return int
*/
private function getDirectorySize($path): int
{
return 0; // Deprecated due to S3 usage
}
/**
* @param $bytes
* @param int $precision
* @return string
*/
function formatBytes($bytes, $precision = 2): string
{
$units = array('B', 'KB', 'MB', 'GB', 'TB');
$bytes = max($bytes, 0);
$pow = floor(($bytes ? log($bytes) : 0) / log(1024));
$pow = min($pow, count($units) - 1);
$bytes /= pow(1024, $pow);
return round($bytes, $precision) . ' ' . $units[$pow];
}
/**
* @Route("/userguide", name="userguide")
* @IsGranted("IS_AUTHENTICATED_REMEMBERED")
**/
public function downloadUserGuide(): BinaryFileResponse
{
$response = new BinaryFileResponse('assets/media/files/smarthub-user-guide.pdf');
$response->setContentDisposition(ResponseHeaderBag::DISPOSITION_ATTACHMENT,'smarthub-user-guide.pdf');
return $response;
}
/**
* @return array
*/
private function getNotices(): array
{
$notices = [];
if(!$this->isGranted('ROLE_ADMIN')) return $notices;
$env = $this->getParameter('kernel.environment');
$notices[] = "kernel.environment: $env";
$notices[] = extension_loaded('imagick') ? 'imagick extension is installed' : 'imagick extension is not installed';
$notices[] = shell_exec('which ffmpeg');
$upload_max_filesize = ini_get('upload_max_filesize');
$notices[] = "upload_max_filesize: $upload_max_filesize";
$max_post = ini_get('post_max_size');
$notices[] = "post_max_size: $max_post";
$max_size_mb = preg_replace('/[^0-9]/', '', $upload_max_filesize);
$max_post_mb = preg_replace('/[^0-9]/', '', $max_post);
$min = min($max_size_mb, $max_post_mb);
$notices[] = "file upload limit: $min";
$memory_limit = ini_get('memory_limit');
$notices[] = "memory_limit: $memory_limit";
$img = new imagick();
$imagick_limit_undefined = $img->getResourceLimit(imagick::RESOURCETYPE_UNDEFINED);
$notices[] = "imagick_limit RESOURCETYPE_UNDEFINED: $imagick_limit_undefined";
$imagick_limit_disk = $img->getResourceLimit(imagick::RESOURCETYPE_DISK);
$notices[] = "imagick_limit RESOURCETYPE_DISK: $imagick_limit_disk";
$imagick_limit_file = $img->getResourceLimit(imagick::RESOURCETYPE_FILE);
$notices[] = "imagick_limit RESOURCETYPE_FILE: $imagick_limit_file";
$imagick_limit_map = $img->getResourceLimit(imagick::RESOURCETYPE_MAP);
$notices[] = "imagick_limit RESOURCETYPE_MAP: $imagick_limit_map";
$imagick_limit_memory = $img->getResourceLimit(imagick::RESOURCETYPE_MEMORY);
$notices[] = "imagick_limit RESOURCETYPE_MEMORY: $imagick_limit_memory";
return $notices;
}
}