Nicks Posted July 23, 2013 Share Posted July 23, 2013 (edited) Bonjour, J'ai rajouté un petit formulaire à la page de détail produit. Je ne rencontre pas de problèmes particuliers avec les champs textes, les listes déroulantes etc... En revanche, je n'arrive pas à faire fonctionner l'envoi de pièces jointes (elles ne sont pas envoyées sur le serveur, si j'en crois la rapidité avec laquelle le formulaire est traité; et c'est confirmé : puisqu'elles ne sont pas dans le dossier Uploads...). Je me suis inspiré du formulaire de contact d'origine et voici ce que j'ai fait (je ne mets pas les codes complets, histoire de gagner du temps) : themes/mon_theme/product.tpl <form action="{$request_uri|escape:'htmlall':'UTF-8'}" method="post"> (...) <label for="fileUpload">{l s='Attach File'}</label> <input type="hidden" name="MAX_FILE_SIZE" value="2000000" /> <input type="file" name="fileUpload" id="fileUpload" /> (...) <input type="submit" name="submitMessage" id="submitMessage" value="Envoyer" class="exclusive"/> </form> controllers/front/ProductController.php public function postProcess() { if (Tools::isSubmit('submitMessage')) { $fileAttachment = null; if (isset($_FILES['fileUpload']['name']) && !empty($_FILES['fileUpload']['name']) && !empty($_FILES['fileUpload']['tmp_name'])) { $extension = array('.txt', '.rtf', '.doc', '.docx', '.pdf', '.zip', '.png', '.jpeg', '.gif', '.jpg'); $filename = uniqid().substr($_FILES['fileUpload']['name'], -5); $fileAttachment['content'] = file_get_contents($_FILES['fileUpload']['tmp_name']); $fileAttachment['name'] = $_FILES['fileUpload']['name']; $fileAttachment['mime'] = $_FILES['fileUpload']['type']; } (...) if (!empty($_FILES['fileUpload']['name']) && $_FILES['fileUpload']['error'] != 0) $this->errors[] = Tools::displayError('An error occurred during the file-upload process.'); elseif (!empty($_FILES['fileUpload']['name']) && !in_array(substr(Tools::strtolower($_FILES['fileUpload']['name']), -4), $extension) && !in_array(substr(Tools::strtolower($_FILES['fileUpload']['name']), -5), $extension)) $this->errors[] = Tools::displayError('Bad file extension'); (...) if (!empty($contact->email)) { if (Mail::Send((int)self::$cookie->id_lang, 'contact2', Mail::l('Demande information produit', (int)self::$cookie->id_lang), array( (...) '{attached_file}' => isset($_FILES['fileUpload'], $_FILES['fileUpload']['name']) ? $_FILES['fileUpload']['name'] : '', '{message}' => stripslashes($message) ), $contact->email, $contact->name, $from, $fileAttachment) AND Mail::Send((int)self::$cookie->id_lang, 'contact_form', Mail::l('Your message has been correctly sent', (int)self::$cookie->id_lang), array('{message}' => stripslashes($message)), $from)) self::$smarty->assign('confirmation', 1); else $this->errors[] = Tools::displayError('An error occurred while sending message.'); } } Si je compare mon fichier du controller à celui de contact (ContactController.php), je constate qu'il me manque quelque-chose comme ca elseif (isset($filename) && rename($_FILES['fileUpload']['tmp_name'], _PS_MODULE_DIR_.'../upload/'.$filename)) $cm->file_name = $filename; Ca semble être le code qui définit où sont "uploadées" les pièces-jointes, mais dans ce code "$cm" pose un problème dans mon script puisque je ne sais pas trop à quoi il se réfère? Et surtout je ne sais pas comment l'utiliser dans mon cas? Merci d'avance! Edited July 25, 2013 by Nicks (see edit history) Link to comment Share on other sites More sharing options...
Matt75 Posted July 23, 2013 Share Posted July 23, 2013 Salut, Pour l'envoi de fichier, il faut ajouter un attribut à la balise form enctype="multipart/form-data" A+ 1 Link to comment Share on other sites More sharing options...
Nicks Posted July 23, 2013 Author Share Posted July 23, 2013 Merci Matt75, Effectivement maintenant je vois que les PJ sont bien envoyées dans le dossier Uploads, en revanche elles ne sont toujours pas attachées au mail... J'ai testé d'afficher la valeur de la pj dans le corps du mail : '{attached_file}' => isset($_FILES['fileUpload'], $_FILES['fileUpload']['name']) ? $_FILES['fileUpload']['name'] : '', Et j'obtiens dans le mail : nom_du_ficher.extension (ex: toto.doc) Encore une petite idée? Merci! Link to comment Share on other sites More sharing options...
Matt75 Posted July 23, 2013 Share Posted July 23, 2013 Cette ligne est inutile : '{attached_file}' => isset($_FILES['fileUpload'], $_FILES['fileUpload']['name']) ? $_FILES['fileUpload']['name'] : '', Tu dois transmettre le fichier à la classMail pour qu'il soit mis en pièce jointe, la méthode send de cette class que tu utilises pour envoyer l'email possède un paramètre pour ça et d'ailleurs tu as une variable fileAttachment qui devrait normalement transmettre le fichier. Essaye de faire un die(var_dump($fileAttachment)) avant d'appeler ta class Mail pour vérifier ce que contient cette variable, normalement elle devrait contenir les informations sur ton fichier. Ton code est pas super propre, faudrait nettoyer un peu pour y voir plus clair. Link to comment Share on other sites More sharing options...
Nicks Posted July 23, 2013 Author Share Posted July 23, 2013 Encore une fois merci de ton intérêt et pour tes commentaires constructifs (désolé d'avance si tu fais des bonds en lisant ce qui va suivre, je crois toutefois que tu as cerné que je ne suis pas un spécialiste de PHP ) J'essaie de transmettre un pdf (test.pdf - 3.42 Ko) J'ai donc fait if(isset($fileAttachment)){ die(var_dump($fileAttachment)); } avant d'appeller la Classe Mail et j'obtiens : array(3) { ["content"]=> string(3505) "%PDF-1.5 %���� 4 0 obj <> endobj xref 4 5 0000000016 00000 n 0000000524 00000 n 0000000620 00000 n 0000000852 00000 n 0000000396 00000 n trailer <<38A0C59E34438E43996439AA5391D422>]/Prev 3296>> startxref 0 %%EOF 8 0 obj <>stream h�b```b``|��f�������~��f� �@� �n�� endstream endobj 5 0 obj <>>> endobj 6 0 obj <>/Rotate 0/TrimBox[0.0 0.0 1280.0 800.0]/Type/Page>> endobj 7 0 obj <>stream H�0 endstream endobj 1 0 obj <> endobj 2 0 obj <>stream Adobe InDesign CS5 (7.0.4) 2013-05-21T15:54:26+02:00 2013-05-21T15:54:26+02:00 2013-05-21T15:54:26+02:00 uuid:ef71e42b-5a1c-47fe-99d2-fec4ee0b88ce xmp.did:152BB9E01DC2E2118F8291B9931F84D6 xmp.did:152BB9E01DC2E2118F8291B9931F84D6 proof:pdf created xmp.iid:152BB9E01DC2E2118F8291B9931F84D6 2013-05-21T15:53:55+02:00 Adobe InDesign 7.0 application/pdf Adobe PDF Library 9.9 False endstream endobj 3 0 obj <> endobj xref 0 4 0000000000 65535 f 0000000930 00000 n 0000000981 00000 n 0000003121 00000 n trailer <<38A0C59E34438E43996439AA5391D422>]>> startxref 116 %%EOF " ["name"]=> string(8) "test.pdf" ["mime"]=> string(15) "application/pdf" } Après j'admets volontiers que mon code est en bordel, mais à priori tout est là, quand je compare avec ce qui est fait sur le formulaire de contact de base + les autres sujets que j'ai lu traitant de ma problématique. Revoici mon code (un peu mieux organisé) 01. themes/montheme/product.tpl <form action="{$request_uri|escape:'htmlall':'UTF-8'}" method="post" enctype="multipart/form-data"> <!-- Ici les autres champs --> <label for="fileUpload">{l s='Attach File'}</label> <input type="hidden" name="MAX_FILE_SIZE" value="2000000" /> <input type="file" name="fileUpload" id="fileUpload" /> <input type="submit" name="submitMessage" id="submitMessage" value="Envoyer" class="exclusive"/> </form> 02. controllers/front/ProductController.php public function postProcess() { if (Tools::isSubmit('submitMessage')) { $fileAttachment = null; if (isset($_FILES['fileUpload']['name']) && !empty($_FILES['fileUpload']['name']) && !empty($_FILES['fileUpload']['tmp_name'])) { $extension = array('.txt', '.rtf', '.doc', '.docx', '.pdf', '.zip', '.png', '.jpeg', '.gif', '.jpg'); $filename = uniqid().substr($_FILES['fileUpload']['name'], -5); $fileAttachment['content'] = file_get_contents($_FILES['fileUpload']['tmp_name']); $fileAttachment['name'] = $_FILES['fileUpload']['name']; $fileAttachment['mime'] = $_FILES['fileUpload']['type']; } // ... Ici mes restrictions sur les autres champs... //Vérif sur l'envoi de la PJ elseif (!empty($_FILES['fileUpload']['name']) && $_FILES['fileUpload']['error'] != 0) $this->errors[] = Tools::displayError('An error occurred during the file-upload process.'); elseif (!empty($_FILES['fileUpload']['name']) && !in_array(substr(Tools::strtolower($_FILES['fileUpload']['name']), -4), $extension) && !in_array(substr(Tools::strtolower($_FILES['fileUpload']['name']), -5), $extension)) $this->errors[] = Tools::displayError('Bad file extension'); } if (!empty($contact->email)) { //Tableau 'var_list' avec mes champs à faire figurer dans le mail $var_list = array( '{email}' => $from, '{client}' => $client, '{id_produit}' => $id_produit, '{societe}' => $societe, '{nom}' => $nom, '{prenom}' => $prenom, '{fonction}' => $fonction, '{secteuractivite}' => $secteuractivite, '{adresse}' => $adresse, '{codepostal}' => $codepostal, '{ville}' => $ville, '{pays}' => $pays, '{tel}' => $tel, '{fax}' => $fax, '{sujet}' => $sujet, //Ci-dessous attached_file ne sert à rien, si ce n'est indiquer le nom de la PJ (nom et extension qui apparaissent bien dans le mail + bien chargé dans /upload) '{attached_file}' => isset($_FILES['fileUpload'], $_FILES['fileUpload']['name']) ? $_FILES['fileUpload']['name'] : '', '{message}' => stripslashes($message) ); if( // Le mail est envoyé avec les différents champs, j'oublie pas d'ajouter $fileAttachment - je pensais naïvement que ca suffirait Mail::Send((int)self::$cookie->id_lang, 'contact2', Mail::l('Demande information produit', (int)self::$cookie->id_lang), $var_list, $contact->email, $contact->name, $from, $fileAttachment) AND Mail::Send((int)self::$cookie->id_lang, 'contact_form', Mail::l('Your message has been correctly sent', (int)self::$cookie->id_lang), array('{message}' => stripslashes($message)), $from, $fileAttachment)) self::$smarty->assign('confirmation', 1); else $this->errors[] = Tools::displayError('An error occurred while sending message.'); } } Voilà, et donc le résultat c'est que la PJ est bien envoyée sur le ftp (/upload) mais pas dans le mail... Link to comment Share on other sites More sharing options...
Matt75 Posted July 23, 2013 Share Posted July 23, 2013 (edited) Bon ta variable contient bien le fichier joint et elle semble bien transmise à la fonction. Normalement tu devrais l'avoir en pièce jointe. Par contre tu utilises un objet $contact à plusieurs reprise alors que je ne vois instancié nul part... En gros tu veux faire un formulaire de contact comme celui de Prestashop mais avec des champs en plus c'est ça ? Edited July 23, 2013 by Matt75 (see edit history) 1 Link to comment Share on other sites More sharing options...
Nicks Posted July 24, 2013 Author Share Posted July 24, 2013 $contact est bien instancié c'est juste que je n'ai pas mis tout le code histoire de faciliter la lecture de mon problème. C'est à peut près ca oui, le formulaire de contact avec plus de champs dans la fiche produit pour que je puisse récupérer la variable "product name" (ou product id). L'idée c'est qu'en naviguant sur un produit, si le client aimerait plus de renseignement sur celui-ci il puisse envoyer un mail très simplement depuis la page produit sans avoir à passer par la page contact et devoir noter lui-même la référence du produit (et risquer de se tromper). En tout cas, ca ne marche pas comme ca. Si je continues ma comparaison avec le formulaire de contact d'origine, dans le controller on trouve une autre fonction initContent : controllers/front/ContactController.php public function initContent() { parent::initContent(); $this->assignOrderList(); $email = Tools::safeOutput(Tools::getValue('from', ((isset($this->context->cookie) && isset($this->context->cookie->email) && Validate::isEmail($this->context->cookie->email)) ? $this->context->cookie->email : ''))); $this->context->smarty->assign(array( 'errors' => $this->errors, 'email' => $email, 'fileupload' => Configuration::get('PS_CUSTOMER_SERVICE_FILE_UPLOAD') )); (...) Je me demande si ca peut jouer? Je pensais jusque-là que c'était ce qui permettait d'afficher les messages dans le BO, non? Link to comment Share on other sites More sharing options...
Matt75 Posted July 24, 2013 Share Posted July 24, 2013 Salut, Bon déjà c'est pas très propre de faire comme tu le fais, c'est-à-dire de mettre du code directement dans le controller Product, il vaudrait mieux faire un module pour ne pas perdre tes modifications après une mise à jour de Prestashop, ensuite récupérer le code du controller Contact n'est pas idéal car il est conçu pour fonctionner avec un ObjectModel Contact dont le but est d'enregistrer les messages dans le BO. Le mieux aurait été de faire un module avec un code totalement indépendant et sans utilisé d'ObjectModel puisque tu veux juste envoyer un Mail et pas stocker en base de données. Le problème quand on est un truc brouillon c'est que quand ça marche pas, c'est difficile d'identifier ce qui ne va pas car c'est le bazar. Concrètement ton formulaire, il est affiché dans la fiche produit ou il faut cliquer sur un lien pour le faire apparaître ? Parce que bon autant essayer de faire un truc propre, qui fonctionne et qui ne gênera pas les futurs mises à jour. Tu pourrais me dire quels sont les champs que tu veux dans ton formulaire ? Link to comment Share on other sites More sharing options...
Nicks Posted July 24, 2013 Author Share Posted July 24, 2013 (edited) Voici ci-dessous mes champs, mais franchement t'embêtes pas avec tous, un champs texte et un champs file pour tester et c'est bon... 01. Vous êtes* (liste déroulante <select> => options : deja client / particulier / entreprise / revendeur. 02. Société* : champs texte 03. Nom* : champs texte 04. Prénom* :champs texte 05. secteur d'activités : champs texte 06. adresse : champs texte 07. Code postal* : champs texte 08. Ville* : champs texte 09. Pays* : champs texte 10. Tel: champs texte 11. email* : champs texte (validation email, champs "from" pour le mail) 12. fax: champs texte 13. Message* : textarea 14. Ajouter une PJ : champs file 15. Envoyer : bouton submit Je n'ai pas encore défini si le formulaire s'affiche dans la page ou si un bouton renvoit vers une page externe. Mais les deux me vont, donc j'aurai tendance à dire : allons au plus simple! Merci encore pour ton aide précieuse. Je me forme à PHP mais je commence par du procédurale et les quelques connaissances que celà m'apporte ne me servent quasiment à rien quand je suis confronté à des applis en MVC comme PS... Edited July 24, 2013 by Nicks (see edit history) Link to comment Share on other sites More sharing options...
Matt75 Posted July 24, 2013 Share Posted July 24, 2013 Quels sont les champs obligatoires ? Au lieu de redirigé vers une page externe, on peut ouvrir une fenêtre modal comme le module Envoyer à un ami Cela fait beaucoup de champs à remplir, tu devrais peut être envisager de cacher certains champs si la personne est connecté et que ces champs sont déjà renseignés dans son compte ou alors les pré-remplir avec les infos déjà présente dans le compte. Les gens n'aiment pas remplir les formulaires, donc si ils ont trop de champs à remplir une majorité d'entre eux ne le fera pas. Link to comment Share on other sites More sharing options...
Nicks Posted July 24, 2013 Author Share Posted July 24, 2013 J'ai rajouté des * pour les champs obligatoires. Je suis sensible à tes remarques pour améliorer l’expérience utilisateur, tout comme il faudra également que je conditionne certains champs en valeurs numériques (code postal, numéro de tel...). J'ai pensé à la popup aussi, ou une div en display:none qui passe en display:block après un clic sur un bouton etc... Si je n'ai pas précisé tout cela c'est simplement pour ne pas faire fuir les gens comme toi prêt à me filer un coup de pouce, donc je me cantonne à l'essentiel Link to comment Share on other sites More sharing options...
Matt75 Posted July 25, 2013 Share Posted July 25, 2013 (edited) Salut, Bon j'ai fais un mix de plusieurs de mes modules pour faire un truc qui colle a ton besoin. Mon module ajoute un lien sur la fiche de produit nommé "Nous contacter à propos de ce produit", que tu pourras modifier dans les traductions si besoin. Lors d'un clic sur ce lien, un popup s'ouvre avec le formulaire de contact. Une fois le formulaire valide, un email est envoyé à l'adresse indiqué dans la configuration du module avec la pièce jointe. Compatible uniquement Prestashop 1.5 (Module MVC et helpers) Pour télécharger le module, me contacter. A+ Edited July 26, 2013 by Matt75 (see edit history) 1 Link to comment Share on other sites More sharing options...
Nicks Posted July 25, 2013 Author Share Posted July 25, 2013 Salut, Déjà, les mots me manquent pour te remercier comme il se doit, mais vraiment c'est extrêmement généreux de ta part Ensuite, j'ai donc téléchargé ton module que j'ai installé et testé. Et malheureusement je suis confronté à un petit problème, je n'arrive pas à envoyer le mail. J'ai essayé une première fois en remplissant tous les champs (PJ comprise) puis une seconde en ne remplissant que les champs obligatoires et j'ai invariablement la même erreur : 1. Failed to send email J'ai essayé en réactivant le thème par défaut de Prestashop et en modifiant les droits sur le module, mais sans succès. J'ai trouvé les lignes où tu conditionne l'affichage de cette erreur : modules/productcontact/controllers/front/defaults.php (l.138) if (file_exists(_PS_MODULE_DIR_.$this->module->name.'/mails/'.$iso.'/productcontact.txt') && file_exists(_PS_MODULE_DIR_.$this->module->name.'/mails/'.$iso.'/productcontact.html')) if (!Mail::Send((int)Configuration::get('PS_LANG_DEFAULT'), 'productcontact', Mail::l('Product contact form', $id_lang), $templateVars, strval(Configuration::get('BETTERPRICE_EMAIL')), strval(Configuration::get('PS_SHOP_NAME')), strval($productcontact_email), strval($productcontact_firstname).strval($productcontact_lastname), $attachment, NULL, _PS_MODULE_DIR_.$this->module->name.'/mails/')) $return['errors'][] = $this->module->l('Failed to send email'); J'utilise Prestashop 1.5.4.1 Link to comment Share on other sites More sharing options...
Matt75 Posted July 25, 2013 Share Posted July 25, 2013 Oui j'ai oublié de modifier le nom d'une variable, du coup la fonction mail ne recevait pas l'adresse à laquelle envoyer le mail. Je mets à jour le ZIP dans mon message précédent. Link to comment Share on other sites More sharing options...
Nicks Posted July 25, 2013 Author Share Posted July 25, 2013 Re! Cette fois c'est tout bon J'ai testé avec et sans PJ, ca marche parfaitement bien Encore une fois merci infiniment pour ton temps et ton travail, je suis certain que ton module va servir à beaucoup de monde! Link to comment Share on other sites More sharing options...
Matt75 Posted July 25, 2013 Share Posted July 25, 2013 Cela peut surtout servir de modèle pour ceux qui veulent créer un module. J'ai essayé de faire un code le plus propre possible. Link to comment Share on other sites More sharing options...
Nicks Posted July 25, 2013 Author Share Posted July 25, 2013 Je n'ai clairement pas le niveau pour saisir toutes les subtilités de ton code, mais je te confirme que rien qu'au niveau de l'indentation et de l'organisation du code c'est très organisé donc bien lisible. Tu aurais des ressources à conseiller (tuto, livres, videos?) pour qui veut apprendre le modèle MVC? (j'ai lu le cours sur la POO sur le siteduzero (http://www.siteduzero.com/informatique/tutoriels/programmez-en-oriente-objet-en-php) mais j'ai pas réussi à faire fonctionner l'application... ) Link to comment Share on other sites More sharing options...
Matt75 Posted July 25, 2013 Share Posted July 25, 2013 Concernant Prestashop, les ressources pour apprendre sont quasi nulles. (la documentation est très pauvre) Néanmoins certains dev partagent leurs connaissances comme J.Danse qui a publié un canvas de module qui a servit à beaucoup de monde, d'autres ont créé leur propre documentation, certains publient parfois des trucs & astuces. Moi généralement je mets à disposition de le code de certains de mes modules (Ceux qui n'ont qu'un faible potentiel de vente et qui présentent un intérêt concernant l'implémentation de telle ou telle possibilité) Pour le PHP en général, y a le site du zéro qui vulgarise assez bien, pour les tutoriels vidéos il y a grafikart et concernant les bouquins, il y en a pas mal mais je trouve pas ça très utile. Link to comment Share on other sites More sharing options...
Nicks Posted July 25, 2013 Author Share Posted July 25, 2013 Ok je prends note des ressources (je connaissais déjà lesiteduzero et grafikart aussi qui est très bien certes, mais si t'es super débutant il manque "un fil rouge" je dirai, je suis assez vite perdu rien que dans la classification des vidéos en tout cas). Allez je vais de ce pas me former... @+ Link to comment Share on other sites More sharing options...
Recommended Posts
Create an account or sign in to comment
You need to be a member in order to leave a comment
Create an account
Sign up for a new account in our community. It's easy!
Register a new accountSign in
Already have an account? Sign in here.
Sign In Now