<?php
namespace App\Controller\Api\V1\Song;
use App\DTO\MMPZ\Song\DownloadSongParametersDTO;
use App\Entity\Profile\Profile;
use App\Entity\Song\Song;
use App\Enums\Constants;
use App\Helpers\PaginationHelper;
use App\Repository\Song\SongRepository;
use App\Responders\CollectionResponder;
use App\Service\ElasticSearch\SongElasticSearchService;
use App\Service\RequestDataExtractorService;
use App\Service\SongService;
use Doctrine\Common\Collections\ArrayCollection;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\IsGranted;
use Swagger\Annotations as SWG;
use Symfony\Component\HttpFoundation\JsonResponse;
use Symfony\Component\HttpKernel\Exception\BadRequestHttpException;
use Symfony\Component\Routing\Annotation\Route;
class GetAllUnderProfile
{
/**
* @var SongService
*/
private $songService;
/**
* @var PaginationHelper
*/
private $paginationHelper;
/**
* @var RequestDataExtractorService
*/
private $requestDataExtractorService;
/**
* @var SongRepository
*/
private $songRepository;
public function __construct(
SongService $songService,
PaginationHelper $paginationHelper,
RequestDataExtractorService $requestDataExtractorService,
SongRepository $songRepository
)
{
$this->songService = $songService;
$this->paginationHelper = $paginationHelper;
$this->requestDataExtractorService = $requestDataExtractorService;
$this->songRepository = $songRepository;
}
/**
* @Route(path="/v1/profile/{id}/song", methods={"GET"})
*
* @SWG\Get(
* tags={"Song"},
* description="Get all songs under some profile"
* )
*
* @SWG\Parameter(
* name="limit",
* in="query",
* type="integer",
* default="5",
* description="Enter the number of result items to show on a page",
* required=true
* ),
*
* * @SWG\Parameter(
* name="search_term",
* in="query",
* type="string",
* default="",
* description="Enter the search terms",
* ),
*
* @SWG\Parameter(
* name="page",
* in="query",
* type="integer",
* default="1",
* description="Enter the number of result page to show",
* required=true
* )
*
* @SWG\Parameter(
* name="sort",
* in="query",
* type="string",
* default="",
* description="Enter the number of result page to show",
* )
*
* @SWG\Parameter(
* name="sort_order",
* in="query",
* type="string",
* default="",
* description="Enter the number of result page to show",
* )
*
* @SWG\Response(
* response=200,
* description="Profiles list"
* )
*
* @IsGranted("PROFILE_ACCESS", subject="profile")
*
* @param Profile $profile
* @param CollectionResponder $collectionResponder
* @param SongElasticSearchService $songElasticSearchService
* @return JsonResponse
* @throws \Exception
*/
public function __invoke(Profile $profile, CollectionResponder $collectionResponder, SongElasticSearchService $songElasticSearchService)
{
$searchTerm = $this->requestDataExtractorService->extractQueryParameter('search_term');
$searchTerm = $this->escapeElasticSearchQuery($searchTerm);
$status = $this->requestDataExtractorService->extractQueryParameter('status');
$sort = $this->requestDataExtractorService->extractQueryParameter('sort');
$sortOrder = $this->requestDataExtractorService->extractQueryParameter('sort_order');
/** @var DownloadSongParametersDTO $downloadSongParameters */
$downloadSongParameters = (new DownloadSongParametersDTO())
->setAll(true);
$allSongsUnderProfile = new ArrayCollection($this->songService->findAllUnderProfile($profile, $downloadSongParameters));
if ($profile->getProfileType()->getName() === Constants::PROFILE_TYPE_SERVICE) {
$allSongsUnderProfile = new ArrayCollection($this->songRepository->findAll());
}
if(!is_null($searchTerm)) {
$params = [];
$params['search_term'] = $searchTerm;
$elasticCollection = $songElasticSearchService->search($params);
}
if (! $searchTerm) {
$elasticCollection = $allSongsUnderProfile;
}
/** @var ArrayCollection $elasticCollection */
$elasticCollection = $elasticCollection->filter(function (Song $song) use ($status, $allSongsUnderProfile) {
if (! $allSongsUnderProfile->contains($song)) {
return null;
}
if (! $status) {
return $song;
}
if ($song->getComposition()->getStatus() === $status) {
return $song;
}
return null;
});
/** @var \Iterator $iterator */
$iterator = $elasticCollection->getIterator();
$iterator->uasort(function (Song $first, Song $second) use ($sort, $sortOrder) {
if(!is_null($sort) && !is_null($sortOrder)){
if($sortOrder === "asc"){
if($sort === "published_at"){
return $first->getComposition()->getPublishedAt() <=> $second->getComposition()->getPublishedAt();
}else if($sort === "submitted_at"){
return $first->getComposition()->getSubmittedAt() <=> $second->getComposition()->getSubmittedAt();
}
}else if($sortOrder === "desc"){
if($sort === "published_at"){
return $second->getComposition()->getPublishedAt() <=> $first->getComposition()->getPublishedAt();
}else if($sort === "submitted_at"){
return $second->getComposition()->getSubmittedAt() <=> $first->getComposition()->getSubmittedAt();
}
}
}
return strnatcasecmp($first->getComposition()->getTitle(), $second->getComposition()->getTitle());
});
$sortedCollection = iterator_to_array($iterator);
$paginatedCollection = $this->paginationHelper->buildPaginatedResult($sortedCollection);
return $collectionResponder($paginatedCollection, ['song:index']);
}
private function escapeElasticSearchQuery(string $query): string
{
return addcslashes($query, '+-=&|><!(){}[]^"~*?:\\/');
}
}