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.

710 lines
25KB

  1. <?php
  2. /**
  3. * Copyright Guillaume Bourgeois (2018)
  4. *
  5. * contact@souke.fr
  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', 'signup-producer'],
  70. 'rules' => [
  71. [
  72. 'actions' => ['signup'],
  73. 'allow' => true,
  74. 'roles' => ['?'],
  75. ],
  76. [
  77. 'actions' => ['signup-producer'],
  78. 'allow' => true,
  79. ],
  80. [
  81. 'actions' => ['logout'],
  82. 'allow' => true,
  83. 'roles' => ['@'],
  84. ],
  85. ],
  86. 'denyCallback' => function($rule, $action) {
  87. return $this->redirect('index');
  88. }
  89. ],
  90. 'verbs' => [
  91. 'class' => VerbFilter::class,
  92. 'actions' => [
  93. 'logout' => ['get'],
  94. ],
  95. ],
  96. ];
  97. }
  98. /**
  99. * @inheritdoc
  100. */
  101. public function actions()
  102. {
  103. return [
  104. 'captcha' => [
  105. 'class' => 'yii\captcha\CaptchaAction',
  106. 'fixedVerifyCode' => YII_ENV_TEST ? 'testme' : null,
  107. ],
  108. ];
  109. }
  110. /**
  111. * Affiche la page d'erreur.
  112. *
  113. * @return mixed
  114. */
  115. public function actionError()
  116. {
  117. $exception = \Yii::$app->errorHandler->exception;
  118. if ($exception->getMessage() == 'Producteur introuvable'
  119. || \Yii::$app->getRequest()->getQueryParam('producer_not_found')) {
  120. return $this->render('error-404-producer', ['exception' => $exception]);
  121. }
  122. if ($exception !== null) {
  123. return $this->render('error', ['exception' => $exception]);
  124. }
  125. }
  126. public function actionIndex()
  127. {
  128. $dataProviderProducers = new ActiveDataProvider([
  129. 'query' => $this->getProducerModule()->queryProducersActive('producer.date_creation', 'DESC')->query(),
  130. 'pagination' => [
  131. 'pageSize' => 100,
  132. ],
  133. ]);
  134. return $this->render('index', [
  135. 'dataProviderProducers' => $dataProviderProducers,
  136. 'producersArray' => $this->getProducerModule()->findProducersActive('producer.date_creation', 'DESC')
  137. ]);
  138. }
  139. public function actionIamproducer()
  140. {
  141. return $this->render('iamproducer', []);
  142. }
  143. public function actionService()
  144. {
  145. $paidFeaturesArray = $this->getFeatureModule()->getRepository()->findPaidFeatures();
  146. return $this->render('service', [
  147. 'producerDemoAccount' => $this->getProducerModule()->findOneProducerDemoAccount(),
  148. 'dataProviderPrices' => $this->getDataProviderPrices(),
  149. 'paidFeaturesArray' => $paidFeaturesArray
  150. ]);
  151. }
  152. public function getDataProviderPrices()
  153. {
  154. return new ActiveDataProvider([
  155. 'query' => $this->getProducerPriceRangeModule()->queryProducerPriceRanges()->query(),
  156. 'pagination' => [
  157. 'pageSize' => 100,
  158. ],
  159. ]);
  160. }
  161. public function actionProducers()
  162. {
  163. return $this->render('producer', [
  164. 'maximumNumberProducers' => $this->getSettingModule()->getAdminSettingBag()->get('maximumNumberProducers'),
  165. 'countProducersActive' => $this->getProducerModule()->getRepository()->countCacheProducersActiveWithTurnover()
  166. ]);
  167. }
  168. public function actionAbout()
  169. {
  170. $aboutFewNumbers = Yii::$app->cache->getOrSet('about_few_numbers4', function () {
  171. $producerModule = $this->getProducerModule();
  172. $pointSaleModule = $this->getPointSaleModule();
  173. $userModule = $this->getUserModule();
  174. $orderModule = $this->getOrderModule();
  175. $countProducersActive = $producerModule->getRepository()->countProducersActiveWithTurnover();
  176. $timeSavedByProducersAverage = $producerModule->getTimeSavedByProducersAverage();
  177. $countProducersWithOptionTimeSaved = $producerModule->countProducersWithTimeSaved();
  178. $countPointSalesActive = $pointSaleModule->countPointSalesActiveLastThreeMonths();
  179. $countUsersActive = $userModule->countUsersActiveLastThreeMonths();
  180. $averageOrdersPerDay = $orderModule->countGlobalUserOrdersAverageLastSevenDays();
  181. $turnoverLastThirtyDays = $orderModule->getRepository()->getTurnoverLastThirtyDays();
  182. $resultMatomoApiVisitSummary = json_decode(file_get_contents(Yii::$app->parameterBag->get('matomoApiVisitSummaryUrl')));
  183. $numberVisitsByDay = $resultMatomoApiVisitSummary->nb_uniq_visitors / 30;
  184. return $this->renderPartial('_about_few_numbers', [
  185. 'countProducersActive' => $countProducersActive,
  186. 'countPointSalesActive' => $countPointSalesActive,
  187. 'countUsersActive' => $countUsersActive,
  188. 'averageOrdersPerDay' => $averageOrdersPerDay,
  189. 'turnoverLastThirtyDays' => $turnoverLastThirtyDays,
  190. 'numberVisitsByDay' => $numberVisitsByDay,
  191. 'timeSavedByProducersAverage' => $timeSavedByProducersAverage,
  192. 'countProducersWithOptionTimeSaved' => $countProducersWithOptionTimeSaved
  193. ]);
  194. }, 60 * 60 * 24);
  195. $producerModule = $this->getProducerModule();
  196. return $this->render('about', [
  197. 'countProducers' => $producerModule->countProducersActiveWithTurnover(),
  198. 'producersWithTestimonials' => $producerModule->findProducersWithTestimonials(),
  199. 'aboutFewNumbers' => $aboutFewNumbers
  200. ]);
  201. }
  202. public function actionSourceCode()
  203. {
  204. return $this->render('source_code');
  205. }
  206. /**
  207. * Liste les producteurs utilisant la plateforme.
  208. */
  209. public function actionAjaxProducers()
  210. {
  211. \Yii::$app->response->format = \yii\web\Response::FORMAT_JSON;
  212. $producersArray = $this->getProducerModule()->findProducersActive();
  213. $producersArrayReturn = [];
  214. foreach($producersArray as $producer) {
  215. $producersArrayReturn[] = [
  216. 'id' => $producer->id,
  217. 'name' => Html::encode($producer->name),
  218. 'type' => Html::encode($producer->type),
  219. 'address' => Html::encode($producer->postcode.' '.$producer->city),
  220. 'latitude' => $producer->latitude,
  221. 'longitude' => $producer->longitude,
  222. 'link' => $this->getUrlManagerProducer()->createAbsoluteUrl(['site/index', 'slug_producer' => $producer->slug])
  223. ];
  224. }
  225. return $producersArrayReturn;
  226. }
  227. /**
  228. * Affiche la page de connexion et traite le formulaire de connexion.
  229. */
  230. public function actionLogin()
  231. {
  232. if (!\Yii::$app->user->isGuest) {
  233. return \Yii::$app->getResponse()->redirect(['site/index']);
  234. }
  235. $model = new LoginForm();
  236. if ($model->load(Yii::$app->request->post()) && $model->login()) {
  237. $returnUrl = \Yii::$app->request->get('return_url');
  238. if ($returnUrl) {
  239. return $this->redirect($returnUrl);
  240. }
  241. else {
  242. $userProducerArray = $this->getUserProducerModule()->findUserProducersByUser(GlobalParam::getCurrentUser());
  243. if ($userProducerArray
  244. && is_array($userProducerArray)
  245. && count($userProducerArray) == 1) {
  246. $urlRedirect = $this->getUrlManagerProducer()
  247. ->createAbsoluteUrl([
  248. 'site/index',
  249. 'slug_producer' => $userProducerArray[0]->producer->slug
  250. ]);
  251. return $this->redirect($urlRedirect);
  252. }
  253. else {
  254. return $this->goBack();
  255. }
  256. }
  257. } else {
  258. return $this->render('@frontend/views/site/login', [
  259. 'model' => $model,
  260. ]);
  261. }
  262. }
  263. /**
  264. * Déconnecte l'utilisateur.
  265. */
  266. public function actionLogout()
  267. {
  268. \Yii::$app->user->logout();
  269. $referer = Yii::$app->request->referrer ?: Yii::$app->homeUrl;
  270. // @TODO : comprendre pourquoi le referer n'est pas complet en ligne (slug producteur + controller/action absents)
  271. if($referer == 'https://'.Yii::getAlias('@producerSubdomain').'.'.Yii::getAlias('@domainName').'/') {
  272. return $this->redirect(Yii::$app->homeUrl);
  273. }
  274. $authenticatedActions = [
  275. // frontend
  276. 'user/update',
  277. // producer
  278. 'order/order',
  279. 'order/history',
  280. 'subscription/index',
  281. 'subscription/form',
  282. 'credit/history',
  283. 'credit/add',
  284. 'newsletter/index'
  285. ];
  286. foreach($authenticatedActions as $authenticatedAction) {
  287. $pos = strpos($referer, $authenticatedAction);
  288. if($pos !== false) {
  289. $referer = substr($referer, 0, $pos);
  290. }
  291. }
  292. return $this->redirect($referer);
  293. }
  294. /**
  295. * Affiche la page de contact et traite le formulaire s'il est soumis.
  296. */
  297. public function actionContact()
  298. {
  299. $model = new ContactForm();
  300. $messageSent = false;
  301. if ($model->load(Yii::$app->request->post()) && $model->validate()) {
  302. $model->sendEmailAdmin();
  303. $messageSent = true;
  304. $model = new ContactForm();
  305. }
  306. return $this->render('contact', [
  307. 'model' => $model,
  308. 'messageSent' => $messageSent,
  309. ]);
  310. }
  311. /**
  312. * Affiche la page d'inscription et traite son formulaire.
  313. */
  314. public function actionSignup(string $type = 'user')
  315. {
  316. $sponsorshipFromCode = Yii::$app->request->get('from');
  317. $sponsorshipProducerFrom = $this->findProducerSponsorshipByCode($sponsorshipFromCode);
  318. $model = new SignupForm();
  319. $model->option_user_producer = $type;
  320. $model->sponsored_by = $sponsorshipProducerFrom ? $sponsorshipProducerFrom->id : false;
  321. $producerModule = $this->getProducerModule();
  322. if ($model->load(Yii::$app->request->post())) {
  323. $user = $model->signup();
  324. if ($user && Yii::$app->getUser()->login($user)) {
  325. if ($model->isProducer()) {
  326. $this->redirect(['site/signup-confirm']);
  327. }
  328. else {
  329. $producer = $producerModule->findOneProducerById($model->id_producer);
  330. if ($producer) {
  331. $this->redirect(['site/signup-confirm', 'idProducerRedirect' => $producer->id]);
  332. }
  333. else {
  334. $this->redirect(['site/index']);
  335. }
  336. }
  337. }
  338. }
  339. // Liste des producteurs disponibles
  340. $producersArray = $producerModule->populateProducerDropdown();
  341. $dataProducers = $producersArray['data'];
  342. $optionsProducers = $producersArray['options'];
  343. $paidFeaturesArray = $this->getFeatureModule()->getRepository()->findPaidFeatures();
  344. return $this->render('signup', [
  345. 'model' => $model,
  346. 'sponsorshipProducerFrom' => $sponsorshipProducerFrom,
  347. 'dataProducers' => $dataProducers,
  348. 'dataProviderPrices' => $this->getDataProviderPrices(),
  349. 'paidFeaturesArray' => $paidFeaturesArray,
  350. 'optionsProducers' => $optionsProducers,
  351. ]);
  352. }
  353. public function actionSignupProducer()
  354. {
  355. $userCurrent = $this->getUserCurrent();
  356. $sponsorshipFromCode = Yii::$app->request->get('from');
  357. $sponsorshipProducerFrom = $this->findProducerSponsorshipByCode($sponsorshipFromCode);
  358. if(!$userCurrent) {
  359. // Lien parrainage
  360. if($sponsorshipFromCode && strlen($sponsorshipFromCode)) {
  361. $this->redirect(['site/signup', 'from' => $sponsorshipFromCode]);
  362. }
  363. else {
  364. $this->redirect(['site/signup']);
  365. }
  366. }
  367. $model = new SignupForm();
  368. $model->signup_producer_only = 'producer';
  369. $model->option_user_producer = 'producer';
  370. $model->sponsored_by = $sponsorshipProducerFrom ? $sponsorshipProducerFrom->id : false;
  371. if ($model->load(Yii::$app->request->post())) {
  372. $user = $model->signup($userCurrent);
  373. if($user) {
  374. $this->redirect(['site/signup-confirm']);
  375. }
  376. }
  377. return $this->render('signup_producer', [
  378. 'model' => $model,
  379. 'sponsorshipProducerFrom' => $sponsorshipProducerFrom,
  380. 'dataProviderPrices' => $this->getDataProviderPrices(),
  381. 'paidFeaturesArray' => $this->getFeatureModule()->getRepository()->findPaidFeatures()
  382. ]);
  383. }
  384. public function findProducerSponsorshipByCode($sponsorshipFromCode)
  385. {
  386. $sponsorshipProducerFrom = null;
  387. if($sponsorshipFromCode && strlen($sponsorshipFromCode)) {
  388. $sponsorshipProducerFrom = $this->getProducerModule()->getRepository()->findOneProducerBySponsorshipCode($sponsorshipFromCode);
  389. }
  390. return $sponsorshipProducerFrom;
  391. }
  392. public function actionSignupConfirm($idProducerRedirect = null)
  393. {
  394. $producerModule = $this->getProducerModule();
  395. $user = $this->getUserCurrent();
  396. $producerRedirect = $idProducerRedirect ? $producerModule->findOneProducerById($idProducerRedirect) : null ;
  397. if(!$user) {
  398. throw new NotFoundHttpException('Page introuvable');
  399. }
  400. return $this->render('signup_confirm', [
  401. 'user' => $user,
  402. 'producerRedirect' => $producerRedirect
  403. ]);
  404. }
  405. /**
  406. * Affiche la page de demande de nouveau mot de passe.
  407. * Traitement du formulaire.
  408. */
  409. public function actionRequestPasswordReset()
  410. {
  411. $model = new PasswordResetRequestForm();
  412. if ($model->load(Yii::$app->request->post()) && $model->validate()) {
  413. if ($model->sendEmail()) {
  414. $this->setFlash('success', 'Un lien vous permettant de réinitialiser votre mot de passe
  415. vient d\'être envoyé sur votre boîte mail.');
  416. return $this->goHome();
  417. }
  418. else {
  419. $this->setFlash('error', "Désolé, aucun compte associé à cette adresse email n'a été trouvé.");
  420. }
  421. }
  422. return $this->render('requestPasswordResetToken', [
  423. 'model' => $model,
  424. ]);
  425. }
  426. /**
  427. * Met à jour le mot de passe de l'utilisateur.
  428. */
  429. public function actionResetPassword($token)
  430. {
  431. try {
  432. $model = new ResetPasswordForm($token);
  433. } catch (InvalidParamException $e) {
  434. throw new BadRequestHttpException($e->getMessage());
  435. }
  436. if ($model->load($this->getRequest()->post())
  437. && $model->validate()
  438. && $model->resetPassword()) {
  439. $this->setFlash('success', 'Votre nouveau mot de passe vient d\'être sauvegardé.');
  440. return $this->goHome();
  441. }
  442. return $this->render('resetPassword', [
  443. 'model' => $model,
  444. ]);
  445. }
  446. /**
  447. * Affiche le formulaire de demande de code pour accéder à certains producteurs.
  448. */
  449. public function actionProducerCode(int $id)
  450. {
  451. $producerModule = $this->getProducerModule();
  452. $producer = $producerModule->findOneProducerById($id);
  453. if (!$producer) {
  454. throw new \yii\web\HttpException(404, 'Producteur introuvable');
  455. }
  456. $producerCodeForm = new ProducerCodeForm();
  457. $producerCodeForm->id_producer = $id;
  458. if ($producerCodeForm->load($this->getRequest()->post())
  459. && $producerCodeForm->validate()) {
  460. $this->getLogic()->setProducerContext($producer);
  461. $producerModule->addUser(GlobalParam::getCurrentUser(), $producer);
  462. $this->redirect($this->getUrlManagerProducer()->createAbsoluteUrl(['site/index', 'slug_producer' => $producer->slug]));
  463. }
  464. return $this->render('producer_code', [
  465. 'producer' => $producer,
  466. 'producerCodeForm' => $producerCodeForm,
  467. ]);
  468. }
  469. /**
  470. * Affiche la page de connexion / inscription pour accéder notamment au
  471. * formulaire de commande des producteurs.
  472. */
  473. public function actionProducer(int $id)
  474. {
  475. $loginForm = new LoginForm();
  476. $signupForm = new SignupForm();
  477. $producerModule = $this->getProducerModule();
  478. $producer = $producerModule->findOneProducerById($id);
  479. $this->getLogic()->setProducerContext($producer);
  480. $loginForm->id_producer = $id;
  481. $signupForm->id_producer = $id;
  482. $signupForm->option_user_producer = 'user';
  483. $returnUrl = $this->getRequest()->get('return_url', $this->getUrlManagerProducer()->createAbsoluteUrl(['site/index', 'slug_producer' => $producer->slug]));
  484. if (Yii::$app->user->isGuest) {
  485. if ($loginForm->load($this->getRequest()->post()) && $loginForm->login()) {
  486. if (!strlen($producer->code)) {
  487. $producerModule->addUser(GlobalParam::getCurrentUser(), $producer);
  488. }
  489. $this->redirect($returnUrl);
  490. }
  491. if ($signupForm->load($this->getRequest()->post())
  492. && ($user = $signupForm->signup())
  493. && Yii::$app->user->login($user)) {
  494. $this->redirect($returnUrl);
  495. }
  496. }
  497. else {
  498. $this->redirect($returnUrl);
  499. }
  500. return $this->render('producer', [
  501. 'loginForm' => $loginForm,
  502. 'signupForm' => $signupForm,
  503. 'producer' => $producer,
  504. ]);
  505. }
  506. /**
  507. * Indique à l'utilisateur que l'espace d'un producteur est hors ligne.
  508. */
  509. public function actionProducerOffline(int $id)
  510. {
  511. return $this->render('producer_offline', [
  512. 'producer' => $this->getProducerModule()->findOneProducerById($id),
  513. ]);
  514. }
  515. public function actionOpinion()
  516. {
  517. $opinionFormModel = new OpinionForm();
  518. $opinionSent = false;
  519. if ($opinionFormModel->load(Yii::$app->request->post()) && $opinionFormModel->validate()) {
  520. $this->getOpinionModule()->getManager()
  521. ->sendOpinionEmailAdmin($opinionFormModel, $this->getUserCurrent());
  522. $opinionSent = true;
  523. $opinionFormModel = new OpinionForm();
  524. }
  525. return $this->render('opinion', [
  526. 'model' => $opinionFormModel,
  527. 'opinionSent' => $opinionSent
  528. ]);
  529. }
  530. /**
  531. * Affiche les mentions légales.
  532. */
  533. public function actionMentions()
  534. {
  535. return $this->render('mentions');
  536. }
  537. /**
  538. * Affiche les conditions générale de service.
  539. */
  540. public function actionCgv()
  541. {
  542. return $this->render('cgv');
  543. }
  544. /**
  545. * Affiche les précisions concernant l'utilisation de la cagnotte
  546. */
  547. public function actionCredit()
  548. {
  549. return $this->render('credit');
  550. }
  551. public function actionImageProducersLogos()
  552. {
  553. $image = @imagecreatetruecolor(1600, 1200);
  554. // fond en blanc
  555. $whiteBackground = imagecolorallocate($image, 255, 255, 255);
  556. imagefill($image,0,0,$whiteBackground);
  557. // logos des producteurs
  558. $producerModule = $this->getProducerModule();
  559. $producersArray = $producerModule->getRepository()->findProducersActive();
  560. shuffle($producersArray);
  561. $x = 50;
  562. $y = 0;
  563. foreach($producersArray as $producer) {
  564. if($producer->logo) {
  565. $logo = null;
  566. $srcLogo = dirname(__FILE__).'/../../producer/web/uploads/'.$producer->logo;
  567. $imageType = exif_imagetype($srcLogo);
  568. if($imageType == IMAGETYPE_PNG) {
  569. $logo = imagecreatefrompng($srcLogo);
  570. $backgroundBlack = imagecolorallocate($logo , 0, 0, 0);
  571. imagecolortransparent($logo, $backgroundBlack);
  572. }
  573. elseif($imageType == IMAGETYPE_JPEG) {
  574. $logo = imagecreatefromjpeg($srcLogo);
  575. }
  576. if($logo) {
  577. imagealphablending($logo, false);
  578. imagesavealpha($logo, true);
  579. list(
  580. $sourceImageWidth,
  581. $sourceImageHeight
  582. ) = getimagesize( $srcLogo);
  583. if($sourceImageWidth && $sourceImageHeight) {
  584. $targetImageWidth = 120;
  585. $targetImageHeight = 120;
  586. $sourceAspectRatio = $sourceImageWidth / $sourceImageHeight;
  587. $targetAspectRatio = $targetImageWidth / $targetImageHeight;
  588. if ($targetAspectRatio > $sourceAspectRatio) {
  589. $targetImageHeight = (int) ($targetImageWidth / $sourceAspectRatio);
  590. }
  591. else {
  592. $targetImageWidth = (int) ($targetImageHeight * $sourceAspectRatio);
  593. }
  594. $transparency = 0.7;
  595. imagefilter($logo, IMG_FILTER_COLORIZE, 0,0,0,127 * $transparency);
  596. imagecopyresampled($image, $logo, $x, $y + 60, 0, 0, $targetImageWidth, $targetImageHeight, $sourceImageWidth, $sourceImageHeight);
  597. $x += $targetImageWidth + 75;
  598. if($x > 1600) {
  599. $x = rand(-50, 50);
  600. $y += 200;
  601. }
  602. }
  603. }
  604. }
  605. }
  606. // noir et blanc
  607. imagefilter($image, IMG_FILTER_GRAYSCALE);
  608. // rendu de l'image
  609. header ('Content-Type: image/png');
  610. imagepng($image);
  611. imagedestroy($image);
  612. die();
  613. }
  614. }