Du kannst nicht mehr als 25 Themen auswählen Themen müssen entweder mit einem Buchstaben oder einer Ziffer beginnen. Sie können Bindestriche („-“) enthalten und bis zu 35 Zeichen lang sein.

628 Zeilen
21KB

  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. 'maximumNumberProducers' => $this->getSettingModule()->getAdminSettingBag()->get('maximumNumberProducers'),
  129. 'countProducersActive' => $this->getProducerModule()->getRepository()->countCacheProducersActiveWithTurnover()
  130. ]);
  131. }
  132. public function actionService()
  133. {
  134. $paidFeaturesArray = $this->getFeatureModule()->getRepository()->findPaidFeatures();
  135. return $this->render('service', [
  136. 'producerDemoAccount' => $this->getProducerModule()->findOneProducerDemoAccount(),
  137. 'dataProviderPrices' => $this->getDataProviderPrices(),
  138. 'paidFeaturesArray' => $paidFeaturesArray
  139. ]);
  140. }
  141. public function getDataProviderPrices()
  142. {
  143. return new ActiveDataProvider([
  144. 'query' => $this->getProducerPriceRangeModule()->queryProducerPriceRanges()->query(),
  145. 'pagination' => [
  146. 'pageSize' => 100,
  147. ],
  148. ]);
  149. }
  150. /**
  151. * Liste les producteurs utilisant la plateforme.
  152. */
  153. public function actionProducers()
  154. {
  155. $dataProviderProducers = new ActiveDataProvider([
  156. 'query' => $this->getProducerModule()->queryProducersActive()->query(),
  157. 'pagination' => [
  158. 'pageSize' => 100,
  159. ],
  160. ]);
  161. return $this->render('producers', [
  162. 'dataProviderProducers' => $dataProviderProducers,
  163. 'producersArray' => $this->getProducerModule()->findProducersActive()
  164. ]);
  165. }
  166. public function actionAbout()
  167. {
  168. $aboutFewNumbers = Yii::$app->cache->getOrSet('about_few_numbers7', function () {
  169. $producerModule = $this->getProducerModule();
  170. $pointSaleModule = $this->getPointSaleModule();
  171. $userModule = $this->getUserModule();
  172. $orderModule = $this->getOrderModule();
  173. $countProducersActive = $producerModule->getRepository()->countProducersActiveWithTurnover();
  174. $timeSavedByProducersAverage = $producerModule->getTimeSavedByProducersAverage();
  175. $countProducersWithOptionTimeSaved = $producerModule->countProducersWithTimeSaved();
  176. $countPointSalesActive = $pointSaleModule->countPointSalesActiveLastThreeMonths();
  177. $countUsersActive = $userModule->countUsersActiveLastThreeMonths();
  178. $averageOrdersPerDay = $orderModule->countGlobalUserOrdersAverageLastSevenDays();
  179. $averageTurnover = $orderModule->getAverageTurnoverLastThreeMonths();
  180. $resultMatomoApiVisitSummary = json_decode(file_get_contents(Yii::$app->parameterBag->get('matomoApiVisitSummaryUrl')));
  181. $numberVisitsMonth = $resultMatomoApiVisitSummary->nb_uniq_visitors;
  182. return $this->renderPartial('_about_few_numbers', [
  183. 'countProducersActive' => $countProducersActive,
  184. 'countPointSalesActive' => $countPointSalesActive,
  185. 'countUsersActive' => $countUsersActive,
  186. 'averageOrdersPerDay' => $averageOrdersPerDay,
  187. 'averageTurnover' => $averageTurnover,
  188. 'numberVisitsMonth' => $numberVisitsMonth,
  189. 'timeSavedByProducersAverage' => $timeSavedByProducersAverage,
  190. 'countProducersWithOptionTimeSaved' => $countProducersWithOptionTimeSaved
  191. ]);
  192. }, 60 * 60 * 24);
  193. $producerModule = $this->getProducerModule();
  194. return $this->render('about', [
  195. 'countProducers' => $producerModule->countProducersActiveWithTurnover(),
  196. 'producersWithTestimonials' => $producerModule->findProducersWithTestimonials(),
  197. 'aboutFewNumbers' => $aboutFewNumbers
  198. ]);
  199. }
  200. public function actionSourceCode()
  201. {
  202. return $this->render('source_code');
  203. }
  204. /**
  205. * Liste les producteurs utilisant la plateforme.
  206. */
  207. public function actionAjaxProducers()
  208. {
  209. \Yii::$app->response->format = \yii\web\Response::FORMAT_JSON;
  210. $producersArray = $this->getProducerModule()->findProducersActive();
  211. $producersArrayReturn = [];
  212. foreach($producersArray as $producer) {
  213. $producersArrayReturn[] = [
  214. 'id' => $producer->id,
  215. 'name' => Html::encode($producer->name),
  216. 'type' => Html::encode($producer->type),
  217. 'address' => Html::encode($producer->postcode.' '.$producer->city),
  218. 'latitude' => $producer->latitude,
  219. 'longitude' => $producer->longitude,
  220. 'link' => $this->getUrlManagerProducer()->createAbsoluteUrl(['site/index', 'slug_producer' => $producer->slug])
  221. ];
  222. }
  223. return $producersArrayReturn;
  224. }
  225. /**
  226. * Affiche la page de connexion et traite le formulaire de connexion.
  227. */
  228. public function actionLogin()
  229. {
  230. if (!\Yii::$app->user->isGuest) {
  231. return \Yii::$app->getResponse()->redirect(['site/index']);
  232. }
  233. $model = new LoginForm();
  234. if ($model->load(Yii::$app->request->post()) && $model->login()) {
  235. $returnUrl = \Yii::$app->request->get('return_url');
  236. if ($returnUrl) {
  237. return $this->redirect($returnUrl);
  238. }
  239. else {
  240. $userProducerArray = $this->getUserProducerModule()->findUserProducersByUser(GlobalParam::getCurrentUser());
  241. if ($userProducerArray
  242. && is_array($userProducerArray)
  243. && count($userProducerArray) == 1) {
  244. $urlRedirect = $this->getUrlManagerProducer()
  245. ->createAbsoluteUrl([
  246. 'site/index',
  247. 'slug_producer' => $userProducerArray[0]->producer->slug
  248. ]);
  249. return $this->redirect($urlRedirect);
  250. }
  251. else {
  252. return $this->goBack();
  253. }
  254. }
  255. } else {
  256. return $this->render('@frontend/views/site/login', [
  257. 'model' => $model,
  258. ]);
  259. }
  260. }
  261. /**
  262. * Déconnecte l'utilisateur.
  263. */
  264. public function actionLogout()
  265. {
  266. \Yii::$app->user->logout();
  267. return $this->goHome();
  268. }
  269. /**
  270. * Affiche la page de contact et traite le formulaire s'il est soumis.
  271. */
  272. public function actionContact()
  273. {
  274. $model = new ContactForm();
  275. $messageSent = false;
  276. if ($model->load(Yii::$app->request->post()) && $model->validate()) {
  277. $model->sendEmailAdmin();
  278. $messageSent = true;
  279. }
  280. return $this->render('contact', [
  281. 'model' => $model,
  282. 'messageSent' => $messageSent,
  283. ]);
  284. }
  285. /**
  286. * Affiche la page d'inscription et traite son formulaire.
  287. */
  288. public function actionSignup()
  289. {
  290. $model = new SignupForm();
  291. $producerModule = $this->getProducerModule();
  292. if ($model->load(Yii::$app->request->post())) {
  293. $user = $model->signup();
  294. if ($user && Yii::$app->getUser()->login($user)) {
  295. if ($model->isProducer()) {
  296. $this->redirect(['site/signup-confirm']);
  297. }
  298. else {
  299. $producer = $producerModule->findOneProducerById($model->id_producer);
  300. if ($producer) {
  301. $this->redirect(['site/signup-confirm', 'idProducerRedirect' => $producer->id]);
  302. }
  303. else {
  304. $this->redirect(['site/index']);
  305. }
  306. }
  307. }
  308. }
  309. // Liste des producteurs disponibles
  310. $producersArray = $producerModule->populateProducerDropdown();
  311. $dataProducers = $producersArray['data'];
  312. $optionsProducers = $producersArray['options'];
  313. $paidFeaturesArray = $this->getFeatureModule()->getRepository()->findPaidFeatures();
  314. return $this->render('signup', [
  315. 'model' => $model,
  316. 'dataProducers' => $dataProducers,
  317. 'dataProviderPrices' => $this->getDataProviderPrices(),
  318. 'paidFeaturesArray' => $paidFeaturesArray,
  319. 'optionsProducers' => $optionsProducers,
  320. ]);
  321. }
  322. public function actionSignupConfirm($idProducerRedirect = null)
  323. {
  324. $producerModule = $this->getProducerModule();
  325. $user = $this->getUserCurrent();
  326. $producerRedirect = $idProducerRedirect ? $producerModule->findOneProducerById($idProducerRedirect) : null ;
  327. if(!$user) {
  328. throw new NotFoundHttpException('Page introuvable');
  329. }
  330. return $this->render('signup_confirm', [
  331. 'user' => $user,
  332. 'producerRedirect' => $producerRedirect
  333. ]);
  334. }
  335. /**
  336. * Affiche la page de demande de nouveau mot de passe.
  337. * Traitement du formulaire.
  338. */
  339. public function actionRequestPasswordReset()
  340. {
  341. $model = new PasswordResetRequestForm();
  342. if ($model->load(Yii::$app->request->post()) && $model->validate()) {
  343. if ($model->sendEmail()) {
  344. $this->setFlash('success', 'Un lien vous permettant de réinitialiser votre mot de passe
  345. vient d\'être envoyé sur votre boîte mail.');
  346. return $this->goHome();
  347. }
  348. else {
  349. $this->setFlash('error', 'Sorry, we are unable to reset password for email provided.');
  350. }
  351. }
  352. return $this->render('requestPasswordResetToken', [
  353. 'model' => $model,
  354. ]);
  355. }
  356. /**
  357. * Met à jour le mot de passe de l'utilisateur.
  358. */
  359. public function actionResetPassword($token)
  360. {
  361. try {
  362. $model = new ResetPasswordForm($token);
  363. } catch (InvalidParamException $e) {
  364. throw new BadRequestHttpException($e->getMessage());
  365. }
  366. if ($model->load($this->getRequest()->post())
  367. && $model->validate()
  368. && $model->resetPassword()) {
  369. $this->setFlash('success', 'Votre nouveau mot de passe vient d\'être sauvegardé.');
  370. return $this->goHome();
  371. }
  372. return $this->render('resetPassword', [
  373. 'model' => $model,
  374. ]);
  375. }
  376. /**
  377. * Affiche le formulaire de demande de code pour accéder à certains producteurs.
  378. */
  379. public function actionProducerCode(int $id)
  380. {
  381. $producerModule = $this->getProducerModule();
  382. $producer = $producerModule->findOneProducerById($id);
  383. if (!$producer) {
  384. throw new \yii\web\HttpException(404, 'Producteur introuvable');
  385. }
  386. $producerCodeForm = new ProducerCodeForm();
  387. $producerCodeForm->id_producer = $id;
  388. if ($producerCodeForm->load($this->getRequest()->post())
  389. && $producerCodeForm->validate()) {
  390. $this->getLogic()->setProducerContext($producer);
  391. $producerModule->addUser(GlobalParam::getCurrentUser(), $producer);
  392. $this->redirect($this->getUrlManagerProducer()->createAbsoluteUrl(['site/index', 'slug_producer' => $producer->slug]));
  393. }
  394. return $this->render('producer_code', [
  395. 'producer' => $producer,
  396. 'producerCodeForm' => $producerCodeForm,
  397. ]);
  398. }
  399. /**
  400. * Affiche la page de connexion / inscription pour accéder notamment au
  401. * formulaire de commande des producteurs.
  402. */
  403. public function actionProducer(int $id)
  404. {
  405. $loginForm = new LoginForm();
  406. $signupForm = new SignupForm();
  407. $producerModule = $this->getProducerModule();
  408. $producer = $producerModule->findOneProducerById($id);
  409. $this->getLogic()->setProducerContext($producer);
  410. $loginForm->id_producer = $id;
  411. $signupForm->id_producer = $id;
  412. $signupForm->option_user_producer = 'user';
  413. $returnUrl = $this->getRequest()->get('return_url', $this->getUrlManagerProducer()->createAbsoluteUrl(['site/index', 'slug_producer' => $producer->slug]));
  414. if (Yii::$app->user->isGuest) {
  415. if ($loginForm->load($this->getRequest()->post()) && $loginForm->login()) {
  416. if (!strlen($producer->code)) {
  417. $producerModule->addUser(GlobalParam::getCurrentUser(), $producer);
  418. }
  419. $this->redirect($returnUrl);
  420. }
  421. if ($signupForm->load($this->getRequest()->post())
  422. && ($user = $signupForm->signup())
  423. && Yii::$app->user->login($user)) {
  424. $this->redirect($returnUrl);
  425. }
  426. }
  427. else {
  428. $this->redirect($returnUrl);
  429. }
  430. return $this->render('producer', [
  431. 'loginForm' => $loginForm,
  432. 'signupForm' => $signupForm,
  433. 'producer' => $producer,
  434. ]);
  435. }
  436. /**
  437. * Indique à l'utilisateur que l'espace d'un producteur est hors ligne.
  438. */
  439. public function actionProducerOffline(int $id)
  440. {
  441. return $this->render('producer_offline', [
  442. 'producer' => $this->getProducerModule()->findOneProducerById($id),
  443. ]);
  444. }
  445. public function actionOpinion()
  446. {
  447. $opinionFormModel = new OpinionForm();
  448. $opinionSent = false;
  449. if ($opinionFormModel->load(Yii::$app->request->post()) && $opinionFormModel->validate()) {
  450. $this->getOpinionModule()->getManager()
  451. ->sendOpinionEmailAdmin($opinionFormModel, $this->getUserCurrent());
  452. $opinionSent = true;
  453. }
  454. return $this->render('opinion', [
  455. 'model' => $opinionFormModel,
  456. 'opinionSent' => $opinionSent
  457. ]);
  458. }
  459. /**
  460. * Affiche les mentions légales.
  461. */
  462. public function actionMentions()
  463. {
  464. return $this->render('mentions');
  465. }
  466. /**
  467. * Affiche les conditions générale de service.
  468. */
  469. public function actionCgv()
  470. {
  471. return $this->render('cgv');
  472. }
  473. /**
  474. * Affiche les précisions concernant l'utilisation du crédit.
  475. */
  476. public function actionCredit()
  477. {
  478. return $this->render('credit');
  479. }
  480. public function actionImageProducersLogos()
  481. {
  482. $image = @imagecreatetruecolor(1600, 1200);
  483. // fond en blanc
  484. $whiteBackground = imagecolorallocate($image, 255, 255, 255);
  485. imagefill($image,0,0,$whiteBackground);
  486. // logos des producteurs
  487. $producerModule = $this->getProducerModule();
  488. $producersArray = $producerModule->getRepository()->findProducersActive();
  489. shuffle($producersArray);
  490. $x = 50;
  491. $y = 0;
  492. foreach($producersArray as $producer) {
  493. if($producer->logo) {
  494. $logo = null;
  495. $srcLogo = dirname(__FILE__).'/../../producer/web/uploads/'.$producer->logo;
  496. $imageType = exif_imagetype($srcLogo);
  497. if($imageType == IMAGETYPE_PNG) {
  498. $logo = imagecreatefrompng($srcLogo);
  499. $backgroundBlack = imagecolorallocate($logo , 0, 0, 0);
  500. imagecolortransparent($logo, $backgroundBlack);
  501. }
  502. elseif($imageType == IMAGETYPE_JPEG) {
  503. $logo = imagecreatefromjpeg($srcLogo);
  504. }
  505. if($logo) {
  506. imagealphablending($logo, false);
  507. imagesavealpha($logo, true);
  508. list(
  509. $sourceImageWidth,
  510. $sourceImageHeight
  511. ) = getimagesize( $srcLogo);
  512. if($sourceImageWidth && $sourceImageHeight) {
  513. $targetImageWidth = 120;
  514. $targetImageHeight = 120;
  515. $sourceAspectRatio = $sourceImageWidth / $sourceImageHeight;
  516. $targetAspectRatio = $targetImageWidth / $targetImageHeight;
  517. if ($targetAspectRatio > $sourceAspectRatio) {
  518. $targetImageHeight = (int) ($targetImageWidth / $sourceAspectRatio);
  519. }
  520. else {
  521. $targetImageWidth = (int) ($targetImageHeight * $sourceAspectRatio);
  522. }
  523. $transparency = 0.7;
  524. imagefilter($logo, IMG_FILTER_COLORIZE, 0,0,0,127 * $transparency);
  525. imagecopyresampled($image, $logo, $x, $y + 60, 0, 0, $targetImageWidth, $targetImageHeight, $sourceImageWidth, $sourceImageHeight);
  526. $x += $targetImageWidth + 75;
  527. if($x > 1600) {
  528. $x = rand(-50, 50);
  529. $y += 200;
  530. }
  531. }
  532. }
  533. }
  534. }
  535. // noir et blanc
  536. imagefilter($image, IMG_FILTER_GRAYSCALE);
  537. // rendu de l'image
  538. header ('Content-Type: image/png');
  539. imagepng($image);
  540. imagedestroy($image);
  541. die();
  542. }
  543. }