Controller.php 20KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751
  1. <?php
  2. namespace Muzich\CoreBundle\lib;
  3. use Symfony\Bundle\FrameworkBundle\Controller\Controller as BaseController;
  4. use Muzich\CoreBundle\Searcher\ElementSearcher;
  5. use Symfony\Component\Security\Core\Authentication\Token\UsernamePasswordToken;
  6. use Muzich\CoreBundle\Form\Search\ElementSearchForm;
  7. use Muzich\CoreBundle\Form\Element\ElementAddForm;
  8. use Symfony\Component\HttpFoundation\Response;
  9. use Muzich\CoreBundle\Searcher\GlobalSearcher;
  10. use Muzich\CoreBundle\Entity\Element;
  11. use Muzich\CoreBundle\Entity\Presubscription;
  12. use Muzich\CoreBundle\Entity\User;
  13. use Muzich\CoreBundle\Entity\Playlist;
  14. use Muzich\CoreBundle\Security\Context as SecurityContext;
  15. use Muzich\CoreBundle\Managers\PlaylistManager;
  16. use Muzich\CoreBundle\Form\Playlist\PlaylistForm;
  17. class Controller extends BaseController
  18. {
  19. const RESPONSE_STATUS_ID = 'status';
  20. const RESPONSE_ERROR_ID = 'error';
  21. const RESPONSE_MESSAGE_ID = 'message';
  22. const RESPONSE_STATUS_ERROR = 'error';
  23. const ERROR_TYPE_NOTFOUND = 'notfound';
  24. const ERROR_TYPE_MUSTBECONNECTED = 'mustbeconnected';
  25. protected static $user = null;
  26. protected static $user_personal_query = null;
  27. protected static $tags = array();
  28. /** @var SecurityContext */
  29. protected $security_context;
  30. /**
  31. * Authenticate a user with Symfony Security
  32. *
  33. */
  34. protected function authenticateUser($user)
  35. {
  36. $providerKey = $this->container->getParameter('fos_user.firewall_name');
  37. $token = new UsernamePasswordToken($user, null, $providerKey, $user->getRoles());
  38. $this->container->get('security.context')->setToken($token);
  39. }
  40. /**
  41. * Met a jour les parametres de ElementSearcher pour la "mémoire" de la
  42. * recherche
  43. *
  44. * @param array $params
  45. */
  46. protected function setElementSearcherParams($params, $session_id = '')
  47. {
  48. if ($session_id != '')
  49. {
  50. $session_id = '.'.$session_id;
  51. }
  52. if (!count($params['tags']))
  53. {
  54. if (count($this->getElementSearcher()->getTags()))
  55. {
  56. $this->get("session")->set('user.element_search.last_tags', $this->getElementSearcher()->getTags());
  57. }
  58. }
  59. $this->get("session")->set('user.element_search.params'.$session_id, $params);
  60. }
  61. protected function isVisitor()
  62. {
  63. $user = $this->getUser();
  64. if ($user === 'anon.')
  65. {
  66. return true;
  67. }
  68. elseif ($user instanceof User)
  69. {
  70. return false;
  71. }
  72. throw new \Exception('Unable to determine user type');
  73. }
  74. /**
  75. * Retourn l'objet ElementSearcher en cours.
  76. *
  77. * @param int $count Si renseigné impact le nombre d'éléments qui seront
  78. * récupérés
  79. * @param boolean $force_new Si a vrai la méthode procéède comme si on
  80. * demandé un nouveau objet de recherche (basé sur les tags favoris donc).
  81. *
  82. * @return ElementSearcher
  83. */
  84. protected function getElementSearcher($count = null, $force_new = false, $session_id = '')
  85. {
  86. $session = $this->get("session");
  87. if ($session_id != '')
  88. {
  89. $session_id = '.'.$session_id;
  90. }
  91. // Si l'objet n'existe pas encore, a t-on déjà des paramètres de recherche
  92. if (!$session->has('user.element_search.params'.$session_id) || $force_new)
  93. {
  94. // Il nous faut instancier notre premier objet recherche
  95. // Premièrement on récupère les tags favoris de l'utilisateur
  96. $this->ElementSearcher = new ElementSearcher();
  97. $this->ElementSearcher->init(array(
  98. 'tags' => $this->getUserFavoriteTags(),
  99. 'count' => ($count)?$count:$this->container->getParameter('search_default_count')
  100. ));
  101. // Et on met en session les paramètres
  102. $session->set('user.element_search.params', $this->ElementSearcher->getParams());
  103. }
  104. else
  105. {
  106. // Des paramètres existes, on fabrique l'objet recherche
  107. $this->ElementSearcher = new ElementSearcher();
  108. // et on l'initatialise avec ces paramétres connus
  109. $this->ElementSearcher->init($session->get('user.element_search.params'.$session_id));
  110. if ($count)
  111. {
  112. $this->ElementSearcher->update(array('count' => $count));
  113. }
  114. }
  115. // on le retourne
  116. return $this->ElementSearcher;
  117. }
  118. protected function getUserFavoriteTags()
  119. {
  120. if (!$this->isVisitor())
  121. {
  122. return $this->getDoctrine()->getRepository('MuzichCoreBundle:User')
  123. ->getTagsFavorites(
  124. $this->getUserId(),
  125. $this->container->getParameter('search_default_favorites_tags_count')
  126. )
  127. ;
  128. }
  129. return array();
  130. }
  131. protected function getNewElementSearcher()
  132. {
  133. return $this->getElementSearcher(null, true);
  134. }
  135. /**
  136. * Retourne l'objet User. Il est possible de préciser de quel manière récupérer
  137. * l'utilisateur:
  138. *
  139. * $user = $this->getUser(true, array('join' => array(
  140. * 'groups_owned'
  141. * )));
  142. *
  143. * ou de forcer sa (re)récupération en base (sinon c'est l'objet static qui est renvoyé)
  144. *
  145. * @param boolean $personal_query
  146. * @param array $params
  147. * @param boolean $force_refresh
  148. * @return \Muzich\CoreBundle\Entity\User
  149. */
  150. public function getUser($personal_query = false, $params = array(), $force_refresh = false)
  151. {
  152. if ($this->container->getParameter('env') == 'test')
  153. {
  154. return $this->container->get('security.context')->getToken()->getUser();
  155. }
  156. if (!$personal_query)
  157. {
  158. // Si on demande l'utilisateur sans forcer la réactualisation et que l'utilisateur
  159. // a déjà été demandé mais avec un requête personelle, on retourne cet utilisateur
  160. if (!$force_refresh && self::$user_personal_query)
  161. {
  162. return self::$user_personal_query;
  163. }
  164. // Si on demande une actualisation ou que l'utilisateur n'a pas encore été demandé
  165. // on va le récupérer
  166. else if ($force_refresh || !self::$user)
  167. {
  168. self::$user = $this->container->get('security.context')->getToken()->getUser();
  169. return self::$user;
  170. }
  171. return self::$user;
  172. }
  173. else
  174. {
  175. // Si l'on demande une réactualisation ou si l'user n'a pas encore été demandé
  176. // on va le récupérer en base.
  177. if ($force_refresh || !self::$user_personal_query)
  178. {
  179. $user = $this->container->get('security.context')->getToken()->getUser();
  180. if ($user !== 'anon.')
  181. {
  182. self::$user_personal_query = $this->getDoctrine()->getRepository('MuzichCoreBundle:User')->findOneById(
  183. $this->container->get('security.context')->getToken()->getUser()->getId(),
  184. array_key_exists('join', $params) ? $params['join'] : array()
  185. )->getSingleResult();
  186. return self::$user_personal_query;
  187. }
  188. else
  189. {
  190. return 'anon.';
  191. }
  192. }
  193. return self::$user_personal_query;
  194. }
  195. }
  196. protected function getUserOrNullIfVisitor()
  197. {
  198. if (($user = $this->getUser()) === 'anon.')
  199. {
  200. return null;
  201. }
  202. return $user;
  203. }
  204. /**
  205. * Retourne l'id de l'utilisateur en cours
  206. */
  207. protected function getUserId($return_null_if_visitor = false)
  208. {
  209. $user = $this->getUser();
  210. if ($user !== 'anon.')
  211. {
  212. return $user->getId();
  213. }
  214. if ($return_null_if_visitor)
  215. {
  216. return null;
  217. }
  218. throw new \Exception('User not connected');
  219. }
  220. protected function getUserRefreshed()
  221. {
  222. return $this->getUser(false, array(), true);
  223. }
  224. /**
  225. * Retourne un tabeau avec les tags connus.
  226. * TODO: Voir pour que cette info soit stocké (par exemple) dans un champs
  227. * texte en base. (json array)
  228. * TODO2: Voir si la question d'opt. "Formulaire d'ajout d'un élément" ne résoue pas
  229. * le problème du TODO ci-dessus.
  230. *
  231. * @return array
  232. */
  233. protected function getTagsArray($force_refresh = false)
  234. {
  235. throw new \Exception("Cette méthode ne doit plus être utilisé.");
  236. if (!count(self::$tags) || $force_refresh)
  237. {
  238. return self::$tags = $this->getDoctrine()->getRepository('MuzichCoreBundle:Tag')->getTagsArray();
  239. }
  240. return self::$tags;
  241. }
  242. /**
  243. * Retourne un tabeau avec les groupes accessible pour un ajout d'element.
  244. *
  245. * @return array
  246. */
  247. protected function getGroupsArray()
  248. {
  249. return $this->getDoctrine()->getRepository('MuzichCoreBundle:Group')
  250. ->getPublicAndOwnedArray($this->getUserId());
  251. }
  252. /**
  253. * Met en place un message de type flash.
  254. *
  255. * @param string $type
  256. * @param string $value
  257. */
  258. protected function setFlash($type, $value)
  259. {
  260. $this->container->get('session')->setFlash($type, $value);
  261. }
  262. /**
  263. * Instancie et retourne un objet ElementSearch
  264. *
  265. * @param array $params
  266. * @return ElementSearcher
  267. */
  268. protected function createSearchObject($params)
  269. {
  270. $search_object = new ElementSearcher();
  271. $search_object->init($params);
  272. return $search_object;
  273. }
  274. /**
  275. * Retourne un User en fonction du slug passé
  276. *
  277. * @param string $slug
  278. * @return User
  279. */
  280. protected function findUserWithSlug($slug)
  281. {
  282. try {
  283. return $this->getDoctrine()
  284. ->getRepository('MuzichCoreBundle:User')
  285. ->findOneBySlug($slug)
  286. ->getSingleResult()
  287. ;
  288. } catch (\Doctrine\ORM\NoResultException $e) {
  289. throw $this->createNotFoundException('Utilisateur introuvable.');
  290. }
  291. }
  292. /**
  293. * Retourne un Group en fonction du slug passé
  294. *
  295. * @param string $slug
  296. * @return Group
  297. */
  298. protected function findGroupWithSlug($slug)
  299. {
  300. try {
  301. return $this->getDoctrine()
  302. ->getRepository('MuzichCoreBundle:Group')
  303. ->findOneBySlug($slug)
  304. ->getSingleResult()
  305. ;
  306. } catch (\Doctrine\ORM\NoResultException $e) {
  307. throw $this->createNotFoundException('Groupe introuvable.');
  308. }
  309. }
  310. /**
  311. * Retourne un Group en fonction du id passé
  312. *
  313. * @param string $slug
  314. * @return Group
  315. */
  316. protected function findGroupWithId($id)
  317. {
  318. try {
  319. return $this->getDoctrine()
  320. ->getRepository('MuzichCoreBundle:Group')
  321. ->findOneById($id)
  322. ;
  323. } catch (\Doctrine\ORM\NoResultException $e) {
  324. throw $this->createNotFoundException('Groupe introuvable.');
  325. }
  326. }
  327. /**
  328. * Retourne le formulaire de recherche
  329. *
  330. * @param \Muzich\CoreBundle\Searcher\Searcher $search_object
  331. * @return \Symfony\Component\Form\Form
  332. */
  333. protected function getSearchForm($search_object)
  334. {
  335. return $this->createForm(
  336. new ElementSearchForm(),
  337. $search_object->getParams(true),
  338. array()
  339. );
  340. }
  341. /**
  342. * Retourne l'objet Form du formulaire de recherche global.
  343. *
  344. * @return \Symfony\Component\Form\Form
  345. */
  346. protected function getGlobalSearchForm($searcher = null)
  347. {
  348. if ($searcher === null)
  349. {
  350. $searcher = new GlobalSearcher();
  351. }
  352. return $this->createFormBuilder($searcher)
  353. ->add('string', 'text')
  354. ->getForm();
  355. }
  356. /**
  357. * Retourne le formulaire d'ajout d'élément
  358. *
  359. * @param \Muzich\CoreBundle\Searcher\Searcher $search_object
  360. * @return \Symfony\Component\Form\Form
  361. */
  362. protected function getAddForm($element = array(), $name = null)
  363. {
  364. //$form = new ElementAddForm();
  365. //$form->setName($name);
  366. //return $this->createForm(
  367. // $form,
  368. // $element,
  369. // array()
  370. //);
  371. $form = new ElementAddForm();
  372. $form->setName($name);
  373. return $this->createForm($form, $element);
  374. }
  375. /**
  376. * Retourne une réponse contenant et de type json
  377. *
  378. * @param array $content
  379. * @return Response
  380. */
  381. protected function jsonResponse($content)
  382. {
  383. $response = new Response(json_encode($content));
  384. $response->headers->set('Content-Type', 'application/json; charset=utf-8');
  385. return $response;
  386. }
  387. protected function jsonResponseError($error_type, $error_content = array())
  388. {
  389. return $this->jsonResponse(array(
  390. 'status' => 'error',
  391. 'error' => $error_type,
  392. 'data' => $error_content
  393. ));
  394. }
  395. protected function jsonNotFoundResponse()
  396. {
  397. $response = new Response(json_encode(array(
  398. 'status' => 'error',
  399. 'errors' => array('NotFound')
  400. )));
  401. $response->headers->set('Content-Type', 'application/json; charset=utf-8');
  402. return $response;
  403. }
  404. /**
  405. * @param array $data
  406. * @return \Symfony\Component\HttpFoundation\Response
  407. */
  408. protected function jsonSuccessResponse($data = array())
  409. {
  410. $response = new Response(json_encode(array(
  411. 'status' => 'success',
  412. 'data' => $data
  413. )));
  414. $response->headers->set('Content-Type', 'application/json; charset=utf-8');
  415. return $response;
  416. }
  417. /**
  418. * Permet d'utiliser la méthode Assert que l'on utilise dans les templates
  419. * afin d'avoir une url correcte vers une ressource web (img, js, ...)
  420. *
  421. * @param string $path
  422. * @param string $packageName
  423. * @return string
  424. */
  425. protected function getAssetUrl($path, $packageName = null)
  426. {
  427. return $this->container->get('templating.helper.assets')->getUrl($path, $packageName);
  428. }
  429. /**
  430. * Retourne une traduction effectué par le translator
  431. *
  432. * @param string $string
  433. * @param array $params
  434. * @param string $package
  435. * @return string
  436. */
  437. protected function trans($string, $params = array(), $package = null)
  438. {
  439. return $this->get('translator')->trans($string, $params, $package);
  440. }
  441. /**
  442. * Permet de récupérer un objet réponse si l'utilisateur doit être connecté
  443. * pour accéder a cette ressource. On peux préciser $and_ajax pour que
  444. * la requete de type ajax soit une nécéssité.
  445. *
  446. * @return Response
  447. */
  448. protected function mustBeConnected($and_ajax = false)
  449. {
  450. if ($and_ajax && !$this->getRequest()->isXmlHttpRequest())
  451. {
  452. throw $this->createNotFoundException('Ressource ajax uniquement.');
  453. }
  454. if ($this->getUser() == 'anon.')
  455. {
  456. if ($this->getRequest()->isXmlHttpRequest())
  457. {
  458. return $this->mustBeConnectedResponse();
  459. }
  460. else
  461. {
  462. $this->setFlash('error', 'user.session_expired');
  463. return $this->redirect($this->generateUrl('home'));
  464. }
  465. }
  466. }
  467. protected function mustBeConnectedAjaxResponse()
  468. {
  469. return $this->jsonResponse(array(
  470. 'status' => 'mustbeconnected'
  471. ));
  472. }
  473. /**
  474. *
  475. * @return \Doctrine\ORM\EntityManager
  476. */
  477. public function getEntityManager()
  478. {
  479. return $this->getDoctrine()->getManager();
  480. }
  481. /** @return Doctrine\ODM\MongoDB\DocumentManager */
  482. public function getMongoManager()
  483. {
  484. return $this->get('doctrine_mongodb')->getManager();
  485. }
  486. /** @return Doctrine\ODM\MongoDB\DocumentRepository */
  487. public function getMongoRepository($repository)
  488. {
  489. return $this->get('doctrine_mongodb')->getRepository($repository);
  490. }
  491. /**
  492. *
  493. * @param object $entity
  494. */
  495. public function persist($entity)
  496. {
  497. $this->getEntityManager()->persist($entity);
  498. }
  499. /**
  500. *
  501. * @param object $entity
  502. */
  503. public function remove($entity)
  504. {
  505. $this->getEntityManager()->remove($entity);
  506. }
  507. /**
  508. *
  509. */
  510. public function flush()
  511. {
  512. $this->getEntityManager()->flush();
  513. }
  514. /**
  515. * Cette méthode vérifie si l'élément qui vient d'être envoyé pourrais être
  516. * associé a un groupe de l'utilisateur.
  517. *
  518. * @param Element $element
  519. * @return array
  520. */
  521. protected function isAddedElementCanBeInGroup(Element $element)
  522. {
  523. $element_tags = $element->getTags();
  524. $groups = array();
  525. if ($element_tags)
  526. {
  527. foreach ($this->getUser()->getGroupsOwned() as $group)
  528. {
  529. foreach ($element_tags as $element_tag)
  530. {
  531. if ($group->hasThisTag($element_tag->getId()))
  532. {
  533. $groups[] = array(
  534. 'name' => $group->getName(),
  535. 'id' => $group->getId(),
  536. 'url' => $this->generateUrl('ajax_set_element_group', array(
  537. 'token' => $this->getUser()->getPersonalHash($element->getId()),
  538. 'element_id' => $element->getId(),
  539. 'group_id' => $group->getId()
  540. ))
  541. );
  542. }
  543. }
  544. }
  545. }
  546. return $groups;
  547. }
  548. protected function getPreSubscriptionForm()
  549. {
  550. return $this->createFormBuilder(new Presubscription())
  551. ->add('email', 'email')
  552. ->getForm()
  553. ;
  554. }
  555. protected function getDisplayAutoplayBooleanForContext($context)
  556. {
  557. if (in_array($context,
  558. $this->container->getParameter('autoplay_contexts')
  559. ))
  560. {
  561. return true;
  562. }
  563. return false;
  564. }
  565. protected function sendEmailconfirmationEmail($set_send_time = true)
  566. {
  567. $user = $this->getUserRefreshed();
  568. $tokenGenerator = $this->container->get('fos_user.util.token_generator');
  569. $user->setConfirmationToken($tokenGenerator->generateToken());
  570. if ($set_send_time)
  571. $user->setEmailConfirmationSentTimestamp(time());
  572. $token = hash('sha256', $user->getConfirmationToken().$user->getEmail());
  573. $url = $this->get('router')->generate('email_confirm', array('token' => $token), true);
  574. $rendered = $this->get('templating')->render('MuzichUserBundle:User:confirm_email_email.txt.twig', array(
  575. 'confirmation_url' => $url
  576. ));
  577. //$this->sendEmailMessage($rendered, $this->parameters['from_email']['resetting'], $user->getEmail());
  578. // Render the email, use the first line as the subject, and the rest as the body
  579. $renderedLines = explode("\n", trim($rendered));
  580. $subject = $renderedLines[0];
  581. $body = implode("\n", array_slice($renderedLines, 1));
  582. $message = \Swift_Message::newInstance()
  583. ->setSubject($subject)
  584. ->setFrom('contact@muzi.ch')
  585. ->setTo($user->getEmail())
  586. ->setBody($body);
  587. $message->getHeaders()->addTextHeader('List-Unsubscribe', 'unsubscribe@muzi.ch');
  588. $mailer = $this->get('mailer');
  589. $mailer->send($message);
  590. $this->persist($user);
  591. $this->flush();
  592. }
  593. protected function getParameter($key)
  594. {
  595. return $this->container->getParameter($key);
  596. }
  597. protected function userHaveNonConditionToMakeAction($action)
  598. {
  599. $secutity_context = $this->getSecurityContext();
  600. if (($condition = $secutity_context->actionIsAffectedBy(SecurityContext::AFFECT_CANT_MAKE, $action)) !== false)
  601. {
  602. return $condition;
  603. }
  604. return false;
  605. }
  606. /** @return SecurityContext */
  607. protected function getSecurityContext()
  608. {
  609. if ($this->security_context == null)
  610. $this->security_context = new SecurityContext($this->getUser());
  611. return $this->security_context;
  612. }
  613. /** @return PlaylistManager */
  614. protected function getPlaylistManager()
  615. {
  616. return new PlaylistManager($this->getEntityManager());
  617. }
  618. protected function getLastDisplayedElementId($elements)
  619. {
  620. if (count($elements))
  621. return $elements[count($elements)-1]->getId();
  622. return null;
  623. }
  624. protected function getElementWithId($element_id)
  625. {
  626. return $this->getEntityManager()->getRepository('MuzichCoreBundle:Element')
  627. ->findOneById($element_id);
  628. }
  629. protected function getPlaylistForm(Playlist $playlist = null)
  630. {
  631. if (!$playlist)
  632. $playlist = $this->getPlaylistManager()->getNewPlaylist($this->getUserOrNullIfVisitor());
  633. return $this->createForm(new PlaylistForm(), $playlist);
  634. }
  635. protected function tokenIsCorrect($intention = 'unknown')
  636. {
  637. if ($this->getRequest()->get('token') != $this->container->get('form.csrf_provider')->generateCsrfToken($intention))
  638. return false;
  639. return true;
  640. }
  641. protected function getToken($intention = 'unknown')
  642. {
  643. return $this->container->get('form.csrf_provider')->generateCsrfToken($intention);
  644. }
  645. protected function getUserManager()
  646. {
  647. return $this->container->get('muzich_user_manager');
  648. }
  649. /** @return \Muzich\CoreBundle\Mining\Tag\TagMiner */
  650. protected function getMineTagMiner()
  651. {
  652. return $this->container->get('muzich.mining.tag.miner');
  653. }
  654. /** @return \Muzich\CoreBundle\Mining\Tag\TagData */
  655. protected function getMineTagData()
  656. {
  657. return $this->container->get('muzich.mining.tag.data');
  658. }
  659. }