<?php
namespace WebBundle\Controller;
use DateTime;
use Doctrine\ORM\OptimisticLockException;
use Doctrine\ORM\ORMException;
use Exception;
use FlexApp\Service\RedisCachePool;
use Monolog\Logger;
use Symfony\Component\HttpFoundation\JsonResponse;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use WebBundle\Entity\Collection;
use WebBundle\Entity\Idea;
use WebBundle\Entity\Interior;
use WebBundle\Entity\InteriorHistory;
use WebBundle\Helper\App;
use WebBundle\Helper\CookieHelper;
use WebBundle\Helper\ResponseApiHelper;
use WebBundle\Helper\TwigTe;
use WebBundle\Helper\UserHelper;
use WebBundle\Repository\CollectionRepository;
use WebBundle\Repository\FilterRepository;
use WebBundle\Repository\IdeaRepository;
use WebBundle\Repository\IdeasShareRepository;
use WebBundle\Repository\InteriorHistoryRepository;
use WebBundle\Repository\InteriorRepository;
use WebBundle\Service\IdeaService;
/**
* Class IdeaController
* @package WebBundle\Controller
*/
class IdeaController extends ExtendedController
{
const COUNT_IDEAS_ON_POPUP = 6;
const HEIGHT_STRING = 60;
private array $message = [
'getTokenByKey' => 'Ключ авторизации не правильный, либо вышел срок его действия',
'deleteIdea' => 'Не найдены соответствующий проект идей для удаления',
'editIdea' => 'Не найдены соответствующий проект идей для редактирования',
'copyIdea' => 'Попытка скопировать не существующий проект',
'copySelfIdea' => 'Попытка скопировать свой проект',
'noArrayInteriorsId' => 'Отсутствует массив идентификаторов интерьеров',
'noArrayInteriorsObj' => 'Не найдено интерьеров для слияния',
'noInterior' => 'Не найдено интерьера с данным идентификатором',
'noIdea' => 'Не найдено проекта идей с данным идентификатором',
];
protected Logger $logger;
/** @required */
public CollectionRepository $collectionRepository;
/** @required */
public InteriorRepository $interiorRepository;
/** @required */
public InteriorHistoryRepository $interiorHistoryRepository;
private IdeaRepository $ideaRepository;
protected string $token;
/**
* IdeaController constructor.
* @param Logger $logger
* @param IdeaRepository $repo
* @throws Exception
*/
public function __construct(
Logger $logger,
IdeaRepository $repo
) {
parent::__construct();
$this->logger = $logger;
$this->ideaRepository = $repo;
$this->token = UserHelper::getInstance()->getToken();
}
/**
* Страница проектов идей
* @param Request $request
* @return Response
* @throws OptimisticLockException
* @throws Exception
*/
public function indexAction(Request $request): Response
{
/** @var Idea $idea */
$ideas = $this->ideaRepository->getIdeasByToken($this->token);
// App::dumpExit($ideas);
$noR = (null !== $request->query->get('noR')) ? $request->query->get('noR') : null;
if (count($ideas) == 1 && empty($noR)) {
/** @var Idea $idea */
$idea = $ideas[0];
return $this->redirect(TwigTe::ideaUrl($idea));
}
$lastUpdate = null;
$list = [];
/** @var Idea $idea */
foreach ($ideas as $idea) {
if (!$lastUpdate) {
$lastUpdate = $idea->getUpdateDate() ?: $idea->getCreateDate();
}
$interiorSrc = empty($idea->getInteriors()[0]) ? ' no-img' : $idea->getInteriors()[0]->getWebPathPreview();
$interiorAlt = empty($idea->getInteriors()[0]) ? '' : $idea->getInteriors()[0]->getName();
$list[] = [
'id' => $idea->getId(),
'url' => TwigTe::ideaUrl($idea),
'interiors' => $idea->getInteriors()->count(),
'src' => $interiorSrc,
'name' => $idea->getName(),
'alt' => $interiorAlt
];
}
return $this->renderReact(
'@Web/Idea/index.html.twig',
[
'title' => App::trans('idea_header_list'),
'description' => App::trans('ideas_description'),
'initialState' => [
'ideas' => [
'list' => $list,
'userLocale' => App::getCurLocale(),
'lastUpdate' => $lastUpdate,
'paths' => $this->paths(),
'trans' => $this->trans()
]
]
]
);
}
/**
* Всплывающее окно проектов идей
* @param Request $request
* @return Response
* @throws Exception
*/
public function lastIdeasAction(Request $request): Response
{
$targetHeight = $request->query->get('targetHeight');
$countString = ($targetHeight) ? floor($targetHeight / 2 / self::HEIGHT_STRING) : self::COUNT_IDEAS_ON_POPUP;
$token = UserHelper::getInstance()->getToken();
/** @var Idea $idea */
$ideas = $this->ideaRepository->getIdeasByToken($token);
return $this->render(
'@Web/Idea/last-ideas.html.twig',
[
'ideas' => $ideas,
'countString' => $countString,
]
);
}
/**
* Страница идеи
* @param string $url
* @param ?string $name
* @return Response
* @throws Exception
*/
public function showAction(string $url, ?string $name = null): Response
{
$idea = $this->ideaRepository->getIdeaByUrl(str_replace([' ', '%20'], '_', urldecode($url)), urldecode($name));
if (!$idea) {
$this->logger->error('не найдена идея: (' . json_encode($idea) . ') по параметрам url:(' .
str_replace([' ', '%20'], '_', urldecode($url)) . ') name:(' . urldecode($name) . ')');
throw $this->createNotFoundException($this->message['noIdea']);
} else {
if ($idea->getUser() == null) {
$user = App::getCurUser();
if ($user) {
$idea->setUser($user);
}
}
$sort = CookieHelper::get('ideaSort', 3);
/** @var InteriorRepository $interiorRepo */
$interiorRepo = App::getRepository('WebBundle:Interior');
$interiors = $interiorRepo->getInteriorsByIdeaSort($idea->getId(), $sort);
/** @var IdeasShareRepository $ideasShareRepo */
$ideasShareRepo = App::getRepository('WebBundle:IdeasShare');
$clickIdeaShareToSocials = $ideasShareRepo->getClickIdeaShareToSocials($idea->getId());
/** @var FilterRepository $filterRepo */
$filterRepo = App::getRepository('WebBundle:FilterEntity');
$listSort = $filterRepo->getSortListCataloge();
$sortVariants = [];
if (!empty($listSort[1])) {
$sortVariants[1] = $listSort[1];
}
if (!empty($listSort[3])) {
$sortVariants[3] = $listSort[3];
}
if (!empty($listSort[4])) {
$sortVariants[4] = $listSort[4];
}
$output = [
'idea' => $idea,
'sort' => $sort,
'sortList' => $sortVariants,
'interiors' => $interiors,
'clickIdeaShareToSocialsItem' => $clickIdeaShareToSocials,
'master' => UserHelper::getInstance()->getToken() == $idea->getToken(),
];
return $this->render(
'@Web/Idea/show.html.twig',
$output
);
// для ReactJs
// return $this->render(
// '@Web/Idea/show.html.twig',
// [
// 'title' => $idea->getName(),
// 'initialState' => $output
// ]
// );
}
}
/**
* Страница сортировки идеи
* @param int $id
* @param ?int $sort
* @return Response
* @throws Exception
*/
public function showSortAction(int $id, ?int $sort = 3): Response
{
/** @var InteriorRepository $interiorRepo */
$interiorRepo = App::getRepository('WebBundle:Interior');
$interiors = $interiorRepo->getInteriorsByIdeaSort($id, $sort);
// сохраняем выбранный вариант сортировки идей
CookieHelper::set('ideaSort', $sort);
$owner = false;
if ($this->ideaRepository->checkMasterIdea($id)) {
$owner = true;
}
return $this->render(
'@Web/Idea/idea_elements.html.twig',
[
'ideaId' => $id,
'interiors' => $interiors,
'owner' => $owner
]
);
}
/**
* Страница списка идей
*
* @param int $id
* @param ?int $oldIdeaId Старый id идеи, (null - по умолчанию)
* @param ?string $type Тип добавление (add - по умолчанию) или передвижение (add | move)
* @return Response
* @throws OptimisticLockException
* @throws Exception
*/
public function listAction(int $id, ?int $oldIdeaId = null, ?string $type = 'add')
{
$token = UserHelper::getInstance()->getToken();
/** @var Idea $idea */
$ideas = $this->ideaRepository->getIdeasByToken($token);
$em = App::em();
// если ещё нет проекта, то создаем
if (count($ideas) == 0) {
$idea = new Idea();
$idea->setCreateDate(new DateTime());
$idea->setUpdateDate(new DateTime());
$idea->setName(App::trans('idea_new_project'));
$idea->setToken($token);
$em->persist($idea);
$em->flush();
$ideas[] = $idea;
}
if (count($ideas) == 1) {
if ($type == 'move') {
return new JsonResponse(
[
'html' => $this->render(
'@Web/Idea/message.html.twig',
[
'showMessage' => !$this->getUser(),
'handler' => $type,
]
)->getContent(),
]
);
} else {
/** @var Idea $idea */
$idea = $ideas[0];
return $this->redirect(
$this->generateUrl(
'app_idea_interior_change',
[
'interiorId' => $id,
'ideaId' => $idea->getId(),
'type' => $type
]
)
);
}
} else {
$interior = App::getRepository('WebBundle:Interior')->findOneBy(['id' => $id]);
$active = [];
/** @var Idea $idea */
foreach ($ideas as $idea) {
if ($idea->getInteriors()->contains($interior)) {
$active[$idea->getId()] = true;
}
}
return new JsonResponse(
[
'html' => $this->render(
'@Web/Idea/list.html.twig',
[
'interiorId' => $id,
'ideas' => $ideas,
'showMessage' => !$this->getUser(),
'active' => $active,
'handler' => $type,
'oldIdeaId' => $oldIdeaId,
]
)->getContent(),
]
);
}
}
/**
* Создание проекта идей
* @param string $name Название проекта
* @return Response
* @throws OptimisticLockException
* @throws Exception
*/
public function createAction(?string $name)
{
$res = new ResponseApiHelper();
$token = UserHelper::getInstance()->getToken();
if ($res->isValid()) {
$name = IdeaService::getNameIdea($token, $name ?? 'null');
$idea = new Idea();
$user = App::getCurUser();
if ($user) {
$idea->setUser($user);
}
$idea->setToken($token);
$idea->setName($name);
$idea->setProcess(1);
$idea->setCreateDate(new DateTime());
$idea->setUpdateDate(new DateTime());
$em = App::em();
$em->persist($idea);
$em->flush();
$interiorSrc = empty($idea->getInteriors()[0]) ? ' no-img' : $idea->getInteriors()[0]->getWebPathPreview();
$interiorAlt = empty($idea->getInteriors()[0]) ? '' : $idea->getInteriors()[0]->getName();
$res->setResponse('res', [
'state' => 'created',
'idea' => [
'id' => $idea->getId(),
'url' => TwigTe::ideaUrl($idea),
'interiors' => $idea->getInteriors()->count(),
'src' => $interiorSrc,
'name' => $idea->getName(),
'alt' => $interiorAlt,
'notification' => App::trans(
'idea.create.msg',
App::getCurLocale(),
['%name%' => '<b>' . $idea->getName() . '</b>']
)
]
]);
}
return new JsonResponse($res->result());
}
/**
* Редактирование проекта идей
* @param int $id - код проекта идеи
* @param string $name - название проекта
* @return Response
* @throws OptimisticLockException
* @throws Exception
*/
public function editAction(int $id, string $name)
{
/** @var ResponseApiHelper $response */
$res = new ResponseApiHelper();
$token = UserHelper::getInstance()->getToken();
if ($res->isValid()) {
$idea = App::getContainer()->get('app.repo.idea')->findOneBy(
['token' => $token, 'id' => $id]
);
if (!$idea) {
$res->validate('editIdea', null, 'empty', $this->message['editIdea']);
} else {
$name = str_replace('/', '', $name);
$name = IdeaService::getNameIdea($token, $name, $idea->getId());
$idea->setToken($token);
$idea->setName($name);
$idea->setCreateDate(new DateTime());
$idea->setUpdateDate(new DateTime());
$em = App::em();
$em->persist($idea);
$em->flush();
$result = [
'state' => 'updated',
'idea' => [
'id' => $idea->getId(),
'name' => $idea->getName(),
'url' => TwigTe::ideaUrl($idea)
],
];
$res->setResponse('res', $result);
}
}
return new JsonResponse($res->result());
}
/**
* Удаление проектов идей
* @param string $id - идентификаторы проектов идей разделённые |
* @return mixed
* @throws OptimisticLockException
* @throws Exception
*/
public function deleteAction(string $id): JsonResponse
{
/** @var ResponseApiHelper $response */
$res = new ResponseApiHelper();
$token = UserHelper::getInstance()->getToken();
if ($res->isValid()) {
$ideas = App::getContainer()->get('app.repo.idea')->findBy(
['token' => $token, 'id' => explode('|', $id)]
);
if (!$ideas) {
$res->validate('deleteIdea', null, 'empty', $this->message['deleteIdea']);
} else {
$em = App::em();
$result = ['action' => 'ok'];
/** @var Idea $idea */
foreach ($ideas as $idea) {
/** @var Interior $interior */
foreach ($idea->getInteriors() as $interior) {
$result['c_rating'][$interior->getCollection()->getId()] = (int)($interior->getCollection()->getRating() - 1);
$result['i_rating'][$interior->getId()] = (int)($interior->getIdeas()->count() - 1);
}
$em->remove($idea);
$em->flush();
}
/** @var IdeaRepository $repoIdea */
$repoIdea = App::getContainer()->get('app.repo.idea');
$result['all'] = $repoIdea->countByToken($token);
$res->setResponse('result', $result);
}
}
return new JsonResponse($res->result());
}
/**
* Добавление удаление интерьера из идей
* @param int $interiorId - идентификаторы интерьера
* @param int $ideaId - идентификатор проекта идеи
* @param ?string $type
* @return mixed
* @throws Exception
*/
public function changeIdeaInteriorAction(int $interiorId, int $ideaId, ?string $type = null): JsonResponse
{
/** @var ResponseApiHelper $response */
$res = new ResponseApiHelper();
$token = UserHelper::getInstance()->getToken();
$interior = $this->interiorRepository->find($interiorId);
if (!$interior) {
$res->validate('noInterior', null, 'empty', $this->message['noInterior']);
}
$idea = $this->ideaRepository->find($ideaId);
if (!$idea) {
$res->validate('noIdea', null, 'empty', $this->message['noIdea']);
}
if (!$res->isValid()) {
return new JsonResponse($res->result());
}
$collection = $this->collectionRepository->find($interior->getCollection()->getId());
$rating = $collection->getRating();
$memcache = App::getMemcache();
$memcache->set('updateCollections', time(), false, 600);
$redisCachePool = App::getContainer()->get(RedisCachePool::class)->getPool();
$cacheItem = $redisCachePool->getItem('updateCollections');
$cacheItem->expiresAfter(600);
$cacheItem->set(time());
$redisCachePool->save($cacheItem);
if ($idea->getInteriors()->contains($interior) === false) {
$active = true;
$idea->getInteriors()->add($interior);
$interior->getIdeas()->add($idea);
$collection->setRating($rating + 1);
$this->setIdeaInterior($idea, $interior, InteriorHistory::ADD);
$this->updateFactoryIdeas($collection->getFactory()->getId());
} elseif ($type != 'add') {
$active = false;
$idea->getInteriors()->removeElement($interior);
$interior->getIdeas()->removeElement($idea);
$collection->setRating(($rating > 1) ? $rating - 1 : $rating);
$this->setIdeaInterior($idea, $interior, InteriorHistory::DEL);
$this->updateFactoryIdeas($collection->getFactory()->getId(), false);
} else {
$active = true;
}
$this->interiorRepository->save($interior, true);
$this->ideaRepository->save($idea, true);
$result = [
'iRating' => (int) $interior->getIdeas()->count(),
'cRating' => (int) $interior->getCollection()->getRating(),
'all' => (int) $this->ideaRepository->countByToken($token),
'active' => $active,
'projects' => [
[
'name' => $idea->getName(),
'url' => TwigTe::ideaUrl($idea),
],
],
];
$res->setResponse('res', $result);
return new JsonResponse($res->result());
}
/**
* Добавление удаление интерьера из идей
* @param int $interiorId идентификаторы интерьера
* @return mixed
* @throws OptimisticLockException
* @throws ORMException
* @throws Exception
* @internal param int $ideaId идентификатор проекта идеи
*/
public function changeIdeasInteriorAction(int $interiorId): JsonResponse
{
/** @var ResponseApiHelper $response */
$res = new ResponseApiHelper();
$token = UserHelper::getInstance()->getToken();
$ideasAction = [];
if (!empty($_POST['ideas'])) {
$ideasAction = $_POST['ideas'];
}
/** @var InteriorRepository $interiorRepo */
$interiorRepo = App::getRepository('WebBundle:Interior');
/** @var Interior $interiorChange */
$interiorChange = $interiorRepo->getInteriorForIdea($interiorId);
if (!$interiorChange) {
$res->validate('noInterior', null, 'empty', $this->message['noInterior']);
}
/** @var Idea $idea */
$ideas = $this->ideaRepository->getIdeas(array_keys($ideasAction), false);
$rating = $interiorChange ? $interiorChange->getCollection()->getRating() : null;
if ($res->isValid()) {
$active = false;
$em = App::em();
$projects = [];
/** @var Idea $idea */
foreach ($ideas as $idea) {
if (isset($ideasAction[$idea->getId()])) {
if ($ideasAction[$idea->getId()] == 1) { // добавление интерьера в проект инеи
if (!$idea->getInteriors()->contains($interiorChange)) {
$idea->getInteriors()->add($interiorChange);
$interiorChange->getIdeas()->add($idea);
$this->setIdeaInterior($idea, $interiorChange, 'add');
$rating = $rating + 1;
}
$active = true;
} else { // удаление интерьера из проекта идеи
if ($idea->getInteriors()->contains($interiorChange)) {
$idea->getInteriors()->removeElement($interiorChange);
$interiorChange->getIdeas()->removeElement($idea);
$this->setIdeaInterior($idea, $interiorChange, 'del');
$rating = ($rating > 1) ? $rating - 1 : $rating;
}
}
}
$interiorChange->getCollection()->setRating($rating);
$this->updateFactoryIdeas($interiorChange->getCollection()->getFactory()->getId(), $active);
$em->persist($interiorChange);
$em->persist($interiorChange->getCollection());
$em->persist($idea);
$em->flush();
$projects[] = [
'name' => $idea->getName(),
'url' => TwigTe::ideaUrl($idea)
];
}
/** @var IdeaRepository $repoIdea */
$repoIdea = App::getContainer()->get('app.repo.idea');
$result = [
'iRating' => $interiorChange->getIdeas()->count(),
'cRating' => $interiorChange->getCollection()->getRating(),
'all' => (int)$repoIdea->countByToken($token),
'active' => $active,
'projects' => $projects
];
$res->setResponse('res', $result);
}
return new JsonResponse($res->result());
}
/**
* @param Idea $idea
* @param Interior $interior
* @param bool $action
* @throws Exception
*/
private function setIdeaInterior(Idea $idea, Interior $interior, bool $action)
{
$interiorHistory = $this->interiorHistoryRepository->getInteriorHistory($interior->getId(), $idea->getId());
if (!$interiorHistory) {
$interiorHistory = new InteriorHistory();
$interiorHistory->setInterior($interior);
$interiorHistory->setIdea($idea);
}
$interiorHistory->setAction($action);
$interiorHistory->setDate(new DateTime());
$this->interiorHistoryRepository->save($interiorHistory, true);
}
/**
* @param int $ideaId
* @param int $interiorId
* @return JsonResponse
* @throws OptimisticLockException
* @throws ORMException
* @throws Exception
*/
public function delInteriorAction(int $ideaId, int $interiorId): JsonResponse
{
$res = new ResponseApiHelper();
$token = UserHelper::getInstance()->getToken();
/** @var Idea $idea */
$idea = $this->ideaRepository->getIdeaById($ideaId);
if (!$idea) {
throw $this->createNotFoundException('Not found idea');
} elseif ($idea->getToken() != $token) {
throw $this->createAccessDeniedException();
}
/** @var Interior $interiorChange */
$interiorChange = App::getRepository('WebBundle:Interior')->findOneBy(
['id' => $interiorId]
);
$collection = $interiorChange->getCollection();
$rating = $collection->getRating();
$idea->getInteriors()->removeElement($interiorChange);
$interiorChange->getIdeas()->removeElement($idea);
$this->setIdeaInterior($idea, $interiorChange, InteriorHistory::DEL);
$collection->setRating(($rating > 1) ? $rating - 1 : $rating);
$this->updateFactoryIdeas($interiorChange->getCollection()->getFactory()->getId(), false);
App::em()->persist($collection);
App::em()->persist($interiorChange);
App::em()->persist($idea);
App::em()->flush();
/** @var IdeaRepository $repoIdea */
$repoIdea = App::getContainer()->get('app.repo.idea');
$result = [
'iRating' => (int)$interiorChange->getIdeas()->count(),
'cRating' => (int)$interiorChange->getCollection()->getRating(),
'all' => (int)$repoIdea->countByToken($token),
'active' => false,
'projects' => [
[
'name' => $idea->getName(),
'url' => TwigTe::ideaUrl($idea)
]
]
];
$res->setResponse('res', $result);
return new JsonResponse($res->result());
}
/**
* Перемещение интерьера в другой проект
*
* @param Request $request
* @param int $oldIdeaId
* @param int $interiorId
* @return JsonResponse
* @throws ORMException
* @throws OptimisticLockException
*/
public function moveInteriorAction(Request $request, int $oldIdeaId, int $interiorId): JsonResponse
{
$res = new ResponseApiHelper();
$this->changeIdeasInteriorAction($interiorId);
$this->delInteriorAction($oldIdeaId, $interiorId);
$result = [
'oldIdeaId' => $oldIdeaId,
'targetIdeaId' => $request->get('ideas'),
'interiorId' => $interiorId,
];
$res->setResponse('res', $result);
return new JsonResponse($res->result());
}
/**
* updateFactoryIdeas - Функция по увеличению/уменьшению кол-ва идей для фабрики.
*
* @see Collection entity for duplicate #of shared ideas.
* sum of all "rating" where (Collection->getFactory = $factoryId) === Factory->ideas
*
* @param int $factoryId - Factory id where increase or decrease interiors stat
* @param ?bool $isAdded - if True - increase counter, else decrease
* @return void - Or mb need return boolean : True - all ok, False - not good
* @throws ORMException
* @throws Exception
*/
private function updateFactoryIdeas(int $factoryId, ?bool $isAdded = true)
{
$oFactory = App::getRepository('WebBundle:Factory')->findOneBy(['id' => $factoryId]);
if (!$oFactory) {
return;
}
$em = App::em();
$i = $oFactory->getTotalIdeas() ?? 0;//get current ideas
if ($isAdded) {
//new idea added. +1 to stat in the factory
$oFactory->setTotalIdeas($i + 1);
} else {
// idea is deleted. -1 to stat in the factory
if ($i > 0) {
$oFactory->setTotalIdeas($i - 1);
}
}
if ($i != $oFactory->getTotalIdeas()) {
//write changes
$em->persist($oFactory);
$em->flush();//// ? mb move out from this function for one persist+flush functions
}
}
/**
* @return array
* @throws Exception
*/
private function trans(): array
{
return [
'ideaHeaderList' => App::trans('idea_header_list'),
'ideaUpdateDate' => App::trans('idea_update_date'),
'ideaAddProject' => App::trans('idea_add_project'),
'ideaBookEmpty' => App::trans('user.ideabook_empty'),
'interiorIdeaDelete' => App::trans('interior_idea_dellete'),
'confirmHeader' => App::trans('buyOrder.confirm.header'),
'ideaEmpty' => App::trans('idea_empty'),
'cancel' => App::trans('cancel'),
'save' => App::trans('save'),
'yes' => App::trans('yes'),
'no' => App::trans('no'),
'rename' => App::trans('rename'),
'share' => App::trans('share'),
'delete' => App::trans('idea.button_delete'),
'delInteriorAllIdeas' => App::trans('idea_del_interior_msg'),
'copy' => App::trans('copy'),
'ideaDeleteTitle' => App::trans('idea.del_project'),
'interiorDeleteTitle' => App::trans('idea_msg_active'),
'ideaRenameTitle' => App::trans('idea.rename_coll'),
'ideaShareTitle' => App::trans('idea_share_header'),
'ideaShareDescr' => App::trans('idea_share_link_can'),
'shareOnSocial' => App::trans('share_social_network'),
'ideaNewProject' => App::trans('idea_new_project'),
];
}
/**
* @return array
* @throws Exception
*/
private function paths(): array
{
return [
'appIdeaDel' => App::generateUrl('app_idea_del', ['id' => 0]),
'appIdeaEdit' => App::generateUrl('app_idea_edit', ['id' => 0, 'name' => '-name-']),
'appIdeaCreate' => App::generateUrl('app_idea_create')
];
}
}