You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

541 lines
18KB

  1. <?php
  2. /**
  3. * Copyright distrib (2018)
  4. *
  5. * contact@opendistrib.net
  6. *
  7. * Ce logiciel est un programme informatique servant à aider les producteurs
  8. * à distribuer leur production en circuits courts.
  9. *
  10. * Ce logiciel est régi par la licence CeCILL soumise au droit français et
  11. * respectant les principes de diffusion des logiciels libres. Vous pouvez
  12. * utiliser, modifier et/ou redistribuer ce programme sous les conditions
  13. * de la licence CeCILL telle que diffusée par le CEA, le CNRS et l'INRIA
  14. * sur le site "http://www.cecill.info".
  15. *
  16. * En contrepartie de l'accessibilité au code source et des droits de copie,
  17. * de modification et de redistribution accordés par cette licence, il n'est
  18. * offert aux utilisateurs qu'une garantie limitée. Pour les mêmes raisons,
  19. * seule une responsabilité restreinte pèse sur l'auteur du programme, le
  20. * titulaire des droits patrimoniaux et les concédants successifs.
  21. *
  22. * A cet égard l'attention de l'utilisateur est attirée sur les risques
  23. * associés au chargement, à l'utilisation, à la modification et/ou au
  24. * développement et à la reproduction du logiciel par l'utilisateur étant
  25. * donné sa spécificité de logiciel libre, qui peut le rendre complexe à
  26. * manipuler et qui le réserve donc à des développeurs et des professionnels
  27. * avertis possédant des connaissances informatiques approfondies. Les
  28. * utilisateurs sont donc invités à charger et tester l'adéquation du
  29. * logiciel à leurs besoins dans des conditions permettant d'assurer la
  30. * sécurité de leurs systèmes et ou de leurs données et, plus généralement,
  31. * à l'utiliser et l'exploiter dans les mêmes conditions de sécurité.
  32. *
  33. * Le fait que vous puissiez accéder à cet en-tête signifie que vous avez
  34. * pris connaissance de la licence CeCILL, et que vous en avez accepté les
  35. * termes.
  36. */
  37. namespace frontend\controllers;
  38. use common\helpers\GlobalParam;
  39. use frontend\forms\OpinionForm;
  40. use frontend\forms\ProducerCodeForm;
  41. use GuzzleHttp\Client;
  42. use Yii;
  43. use frontend\forms\PasswordResetRequestForm;
  44. use frontend\forms\ResetPasswordForm;
  45. use frontend\forms\SignupForm;
  46. use common\forms\ContactForm;
  47. use yii\base\InvalidParamException;
  48. use yii\base\UserException;
  49. use yii\data\ActiveDataProvider;
  50. use yii\helpers\Html;
  51. use yii\web\BadRequestHttpException;
  52. use yii\filters\VerbFilter;
  53. use yii\filters\AccessControl;
  54. use common\forms\LoginForm;
  55. use yii\web\NotFoundHttpException;
  56. /**
  57. * Site controller
  58. */
  59. class SiteController extends FrontendController
  60. {
  61. /**
  62. * @inheritdoc
  63. */
  64. public function behaviors()
  65. {
  66. return [
  67. 'access' => [
  68. 'class' => AccessControl::class,
  69. 'only' => ['logout', 'signup'],
  70. 'rules' => [
  71. [
  72. 'actions' => ['signup'],
  73. 'allow' => true,
  74. 'roles' => ['?'],
  75. ],
  76. [
  77. 'actions' => ['logout'],
  78. 'allow' => true,
  79. 'roles' => ['@'],
  80. ],
  81. ],
  82. 'denyCallback' => function($rule, $action) {
  83. return $this->redirect('index');
  84. }
  85. ],
  86. 'verbs' => [
  87. 'class' => VerbFilter::class,
  88. 'actions' => [
  89. 'logout' => ['get'],
  90. ],
  91. ],
  92. ];
  93. }
  94. /**
  95. * @inheritdoc
  96. */
  97. public function actions()
  98. {
  99. return [
  100. 'captcha' => [
  101. 'class' => 'yii\captcha\CaptchaAction',
  102. 'fixedVerifyCode' => YII_ENV_TEST ? 'testme' : null,
  103. ],
  104. ];
  105. }
  106. /**
  107. * Affiche la page d'erreur.
  108. *
  109. * @return mixed
  110. */
  111. public function actionError()
  112. {
  113. $exception = \Yii::$app->errorHandler->exception;
  114. if ($exception->getMessage() == 'Producteur introuvable'
  115. || \Yii::$app->getRequest()->getQueryParam('producer_not_found')) {
  116. return $this->render('error-404-producer', ['exception' => $exception]);
  117. }
  118. if ($exception !== null) {
  119. return $this->render('error', ['exception' => $exception]);
  120. }
  121. }
  122. /**
  123. * Affiche la page d'accueil.
  124. */
  125. public function actionIndex()
  126. {
  127. return $this->render('index');
  128. }
  129. public function actionService()
  130. {
  131. return $this->render('service', [
  132. 'producerDemoAccount' => $this->getProducerManager()->findOneProducerDemoAccount(),
  133. 'dataProviderPrices' => $this->getDataProviderPrices()
  134. ]);
  135. }
  136. public function getDataProviderPrices()
  137. {
  138. return new ActiveDataProvider([
  139. 'query' => $this->getProducerPriceRangeManager()->queryProducerPriceRanges()->query(),
  140. 'pagination' => [
  141. 'pageSize' => 100,
  142. ],
  143. ]);
  144. }
  145. /**
  146. * Liste les producteurs utilisant la plateforme.
  147. */
  148. public function actionProducers()
  149. {
  150. $dataProviderProducers = new ActiveDataProvider([
  151. 'query' => $this->getProducerManager()->queryProducersActive()->query(),
  152. 'pagination' => [
  153. 'pageSize' => 100,
  154. ],
  155. ]);
  156. return $this->render('producers', [
  157. 'dataProviderProducers' => $dataProviderProducers,
  158. 'producersArray' => $this->getProducerManager()->findProducersActive()
  159. ]);
  160. }
  161. public function actionAbout()
  162. {
  163. $aboutFewNumbers = Yii::$app->cache->getOrSet('about_few_numbers7', function () {
  164. $producerManager = $this->getProducerManager();
  165. $pointSaleManager = $this->getPointSaleManager();
  166. $userModule = $this->getUserModule();
  167. $orderManager = $this->getOrderManager();
  168. $countProducersActive = $producerManager->countProducersActiveWithTurnover();
  169. $timeSavedByProducersAverage = $producerManager->getTimeSavedByProducersAverage();
  170. $countProducersWithOptionTimeSaved = $producerManager->countProducersWithTimeSaved();
  171. $countPointSalesActive = $pointSaleManager->countPointSalesActiveLastThreeMonths();
  172. $countUsersActive = $userModule->countUsersActiveLastThreeMonths();
  173. $averageOrdersPerDay = $orderManager->countGlobalUserOrdersAverageLastSevenDays();
  174. $averageTurnover = $orderManager->getAverageTurnoverLastThreeMonths();
  175. $resultMatomoApiVisitSummary = json_decode(file_get_contents(Yii::$app->parameterBag->get('matomoApiVisitSummaryUrl')));
  176. $numberVisitsMonth = $resultMatomoApiVisitSummary->nb_uniq_visitors;
  177. return $this->renderPartial('_about_few_numbers', [
  178. 'countProducersActive' => $countProducersActive,
  179. 'countPointSalesActive' => $countPointSalesActive,
  180. 'countUsersActive' => $countUsersActive,
  181. 'averageOrdersPerDay' => $averageOrdersPerDay,
  182. 'averageTurnover' => $averageTurnover,
  183. 'numberVisitsMonth' => $numberVisitsMonth,
  184. 'timeSavedByProducersAverage' => $timeSavedByProducersAverage,
  185. 'countProducersWithOptionTimeSaved' => $countProducersWithOptionTimeSaved
  186. ]);
  187. }, 60 * 60 * 24);
  188. $producerManager = $this->getProducerManager();
  189. return $this->render('about', [
  190. 'countProducers' => $producerManager->countProducersActiveWithTurnover(),
  191. 'producersWithTestimonials' => $producerManager->findProducersWithTestimonials(),
  192. 'aboutFewNumbers' => $aboutFewNumbers
  193. ]);
  194. }
  195. public function actionSourceCode()
  196. {
  197. return $this->render('source_code');
  198. }
  199. /**
  200. * Liste les producteurs utilisant la plateforme.
  201. */
  202. public function actionAjaxProducers()
  203. {
  204. \Yii::$app->response->format = \yii\web\Response::FORMAT_JSON;
  205. $producersArray = $this->getProducerManager()->findProducersActive();
  206. $producersArrayReturn = [];
  207. foreach($producersArray as $producer) {
  208. $producersArrayReturn[] = [
  209. 'id' => $producer->id,
  210. 'name' => Html::encode($producer->name),
  211. 'type' => Html::encode($producer->type),
  212. 'address' => Html::encode($producer->postcode.' '.$producer->city),
  213. 'latitude' => $producer->latitude,
  214. 'longitude' => $producer->longitude,
  215. 'link' => $this->getUrlManagerProducer()->createAbsoluteUrl(['site/index', 'slug_producer' => $producer->slug])
  216. ];
  217. }
  218. return $producersArrayReturn;
  219. }
  220. /**
  221. * Affiche la page de connexion et traite le formulaire de connexion.
  222. */
  223. public function actionLogin()
  224. {
  225. if (!\Yii::$app->user->isGuest) {
  226. return \Yii::$app->getResponse()->redirect(['site/index']);
  227. }
  228. $model = new LoginForm();
  229. if ($model->load(Yii::$app->request->post()) && $model->login()) {
  230. $returnUrl = \Yii::$app->request->get('return_url');
  231. if ($returnUrl) {
  232. return $this->redirect($returnUrl);
  233. }
  234. else {
  235. $userProducerArray = $this->getUserProducerManager()->findUserProducersByUser(GlobalParam::getCurrentUser());
  236. if ($userProducerArray
  237. && is_array($userProducerArray)
  238. && count($userProducerArray) == 1) {
  239. $urlRedirect = $this->getUrlManagerProducer()
  240. ->createAbsoluteUrl([
  241. 'site/index',
  242. 'slug_producer' => $userProducerArray[0]->producer->slug
  243. ]);
  244. return $this->redirect($urlRedirect);
  245. }
  246. else {
  247. return $this->goBack();
  248. }
  249. }
  250. } else {
  251. return $this->render('@frontend/views/site/login', [
  252. 'model' => $model,
  253. ]);
  254. }
  255. }
  256. /**
  257. * Déconnecte l'utilisateur.
  258. */
  259. public function actionLogout()
  260. {
  261. \Yii::$app->user->logout();
  262. return $this->goHome();
  263. }
  264. /**
  265. * Affiche la page de contact et traite le formulaire s'il est soumis.
  266. */
  267. public function actionContact()
  268. {
  269. $model = new ContactForm();
  270. $messageSent = false;
  271. if ($model->load(Yii::$app->request->post()) && $model->validate()) {
  272. $model->sendEmail(Yii::$app->parameterBag->get('adminEmail'));
  273. $messageSent = true;
  274. }
  275. return $this->render('contact', [
  276. 'model' => $model,
  277. 'messageSent' => $messageSent,
  278. ]);
  279. }
  280. /**
  281. * Affiche la page d'inscription et traite son formulaire.
  282. */
  283. public function actionSignup()
  284. {
  285. $model = new SignupForm();
  286. $producerManager = $this->getProducerManager();
  287. if ($model->load(Yii::$app->request->post())) {
  288. $user = $model->signup();
  289. if ($user && Yii::$app->getUser()->login($user)) {
  290. if ($model->isProducer()) {
  291. $this->redirect(['site/signup-confirm']);
  292. }
  293. else {
  294. $producer = $producerManager->findOneProducerById($model->id_producer);
  295. if ($producer) {
  296. $this->redirect(['site/signup-confirm', 'idProducerRedirect' => $producer->id]);
  297. }
  298. else {
  299. $this->redirect(['site/index']);
  300. }
  301. }
  302. }
  303. }
  304. // Liste des producteurs disponibles
  305. $producersArray = $producerManager->populateProducerDropdown();
  306. $dataProducers = $producersArray['data'];
  307. $optionsProducers = $producersArray['options'];
  308. return $this->render('signup', [
  309. 'model' => $model,
  310. 'dataProducers' => $dataProducers,
  311. 'dataProviderPrices' => $this->getDataProviderPrices(),
  312. 'optionsProducers' => $optionsProducers,
  313. ]);
  314. }
  315. public function actionSignupConfirm($idProducerRedirect = null)
  316. {
  317. $producerManager = $this->getProducerManager();
  318. $user = $this->getUserCurrent();
  319. $producerRedirect = $idProducerRedirect ? $producerManager->findOneProducerById($idProducerRedirect) : null ;
  320. if(!$user) {
  321. throw new NotFoundHttpException('Page introuvable');
  322. }
  323. return $this->render('signup_confirm', [
  324. 'user' => $user,
  325. 'producerRedirect' => $producerRedirect
  326. ]);
  327. }
  328. /**
  329. * Affiche la page de demande de nouveau mot de passe.
  330. * Traitement du formulaire.
  331. */
  332. public function actionRequestPasswordReset()
  333. {
  334. $model = new PasswordResetRequestForm();
  335. if ($model->load(Yii::$app->request->post()) && $model->validate()) {
  336. if ($model->sendEmail()) {
  337. $this->setFlash('success', 'Un lien vous permettant de réinitialiser votre mot de passe
  338. vient d\'être envoyé sur votre boîte mail.');
  339. return $this->goHome();
  340. }
  341. else {
  342. $this->setFlash('error', 'Sorry, we are unable to reset password for email provided.');
  343. }
  344. }
  345. return $this->render('requestPasswordResetToken', [
  346. 'model' => $model,
  347. ]);
  348. }
  349. /**
  350. * Met à jour le mot de passe de l'utilisateur.
  351. */
  352. public function actionResetPassword($token)
  353. {
  354. try {
  355. $model = new ResetPasswordForm($token);
  356. } catch (InvalidParamException $e) {
  357. throw new BadRequestHttpException($e->getMessage());
  358. }
  359. if ($model->load($this->getRequest()->post())
  360. && $model->validate()
  361. && $model->resetPassword()) {
  362. $this->setFlash('success', 'Votre nouveau mot de passe vient d\'être sauvegardé.');
  363. return $this->goHome();
  364. }
  365. return $this->render('resetPassword', [
  366. 'model' => $model,
  367. ]);
  368. }
  369. /**
  370. * Affiche le formulaire de demande de code pour accéder à certains producteurs.
  371. */
  372. public function actionProducerCode(int $id)
  373. {
  374. $producerManager = $this->getProducerManager();
  375. $producer = $producerManager->findOneProducerById($id);
  376. if (!$producer) {
  377. throw new \yii\web\HttpException(404, 'Producteur introuvable');
  378. }
  379. $producerCodeForm = new ProducerCodeForm();
  380. $producerCodeForm->id_producer = $id;
  381. if ($producerCodeForm->load($this->getRequest()->post())
  382. && $producerCodeForm->validate()) {
  383. $this->getLogic()->setProducerContext($producer);
  384. $producerManager->addUser(GlobalParam::getCurrentUser(), $producer);
  385. $this->redirect($this->getUrlManagerProducer()->createAbsoluteUrl(['site/index', 'slug_producer' => $producer->slug]));
  386. }
  387. return $this->render('producer_code', [
  388. 'producer' => $producer,
  389. 'producerCodeForm' => $producerCodeForm,
  390. ]);
  391. }
  392. /**
  393. * Affiche la page de connexion / inscription pour accéder notamment au
  394. * formulaire de commande des producteurs.
  395. */
  396. public function actionProducer(int $id)
  397. {
  398. $loginForm = new LoginForm();
  399. $signupForm = new SignupForm();
  400. $producerManager = $this->getProducerManager();
  401. $producer = $producerManager->findOneProducerById($id);
  402. $this->getLogic()->setProducerContext($producer);
  403. $loginForm->id_producer = $id;
  404. $signupForm->id_producer = $id;
  405. $signupForm->option_user_producer = 'user';
  406. $returnUrl = $this->getRequest()->get('return_url', $this->getUrlManagerProducer()->createAbsoluteUrl(['site/index', 'slug_producer' => $producer->slug]));
  407. if (Yii::$app->user->isGuest) {
  408. if ($loginForm->load($this->getRequest()->post()) && $loginForm->login()) {
  409. if (!strlen($producer->code)) {
  410. $producerManager->addUser(GlobalParam::getCurrentUser(), $producer);
  411. }
  412. $this->redirect($returnUrl);
  413. }
  414. if ($signupForm->load($this->getRequest()->post())
  415. && ($user = $signupForm->signup())
  416. && Yii::$app->user->login($user)) {
  417. $this->redirect($returnUrl);
  418. }
  419. }
  420. else {
  421. $this->redirect($returnUrl);
  422. }
  423. return $this->render('producer', [
  424. 'loginForm' => $loginForm,
  425. 'signupForm' => $signupForm,
  426. 'producer' => $producer,
  427. ]);
  428. }
  429. /**
  430. * Indique à l'utilisateur que l'espace d'un producteur est hors ligne.
  431. */
  432. public function actionProducerOffline(int $id)
  433. {
  434. return $this->render('producer_offline', [
  435. 'producer' => $this->getProducerManager()->findOneProducerById($id),
  436. ]);
  437. }
  438. public function actionOpinion()
  439. {
  440. $opinionFormModel = new OpinionForm();
  441. $opinionSent = false;
  442. if ($opinionFormModel->load(Yii::$app->request->post()) && $opinionFormModel->validate()) {
  443. $this->getOpinionManager()->sendOpinionEmailAdmin($opinionFormModel, $this->getUserCurrent());
  444. $opinionSent = true;
  445. }
  446. return $this->render('opinion', [
  447. 'model' => $opinionFormModel,
  448. 'opinionSent' => $opinionSent
  449. ]);
  450. }
  451. /**
  452. * Affiche les mentions légales.
  453. */
  454. public function actionMentions()
  455. {
  456. return $this->render('mentions');
  457. }
  458. /**
  459. * Affiche les conditions générale de service.
  460. */
  461. public function actionCgv()
  462. {
  463. return $this->render('cgv');
  464. }
  465. /**
  466. * Affiche les précisions concernant l'utilisation du crédit.
  467. */
  468. public function actionCredit()
  469. {
  470. return $this->render('credit');
  471. }
  472. }