Controller.php 17KB

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