Vyšla nová verze PrestaShop 8, významná aktualizace oblíbeného systému pro tvorbu internetových obchodů. Mezi hlavní novinky pro běžné uživatele patří:
- Nová stránka pro zabezpečení, která umožňuje správcům obchodu přizpůsobit politiku hesel a spravovat sezení zákazníků a zaměstnanců.
- Indikátor síly hesla, který uživatelům v reálném čase ukazuje, jak silné je jejich vybrané heslo.
Podpora pro formáty obrázků WebP a SVG, což znamená lepší kompresi a rychlejší načítání stránek. - Vylepšená stránka produktu v administraci.
- Vylepšená funkce pro optimalizaci pro vyhledávače (SEO), která nyní zahrnuje další popis pro kategorie, zlepšení indexace vyřazených produktů a návrhy na délku obsahu.
- Zlepšená podpora pro multistore, která umožňuje obchodníkům vybrat, která pole aktualizovat v kontextu obchodu nebo skupiny.
- Podpora pro DKIM podpisy pro e-maily, které snižují pravděpodobnost, že e-maily z vašeho obchodu budou označeny jako spam.
Více informací o novinkách najdete na oficiálních stránkách PrestaShopu. Vyzkoušet si ji můžete také na naší demo instalaci.
Pokud vás trápí spam z kontaktního formuláře a nechcete používat Google reCAPTCHA tak zde je návod na úpravu, díky které do kontaktního formuláře vložíte ověření pomocí jednoduchého součtu čísel. Čísla se automaticky mění při každém načtení formuláře a výsledek vypadá takto (součet je zde pro názornost označen červeným obdélníkem):
UPOZORNĚNÍ: je třeba rozumět všem prováděným krokům. Chybná úprava může způsobit nefunkčnost stránek.
UPOZORNĚNÍ: u všech upravovaných souborů si nejprve vytvořte zálohu
Úprava kontroleru
Nejprve je třeba rozšírit kontroler formuláře a přidat do něj kód pro ověření součtu. Není vhodné přepisovat celý kontroler a proto přepíšeme pouze nezbytné funkce pomocí override.
Vytvoření kontroleru
Vytvoříme soubor ContactController.php v adresáři /override/controllers/front s následujícím kódem:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 |
<?php class ContactController extends ContactControllerCore { /** * Start forms process * @see FrontController::postProcess() */ public function postProcess() { if (Tools::isSubmit('submitMessage')) { $saveContactKey = $this->context->cookie->contactFormKey; $extension = array('.txt', '.rtf', '.doc', '.docx', '.pdf', '.zip', '.png', '.jpeg', '.gif', '.jpg'); $file_attachment = Tools::fileAttachment('fileUpload'); $message = Tools::getValue('message'); $mathAnswer = Tools::getValue('mathAnswer'); $mathNumber1 = Tools::getValue('mathNumber1'); $mathNumber2 = Tools::getValue('mathNumber2'); $mathSum = $mathNumber1 + $mathNumber2; $url = Tools::getValue('url'); if (!($from = trim(Tools::getValue('from'))) || !Validate::isEmail($from)) { $this->errors[] = Tools::displayError('Invalid email address.'); } elseif (!$message) { $this->errors[] = Tools::displayError('The message cannot be blank.'); } elseif (!Validate::isCleanHtml($message)) { $this->errors[] = Tools::displayError('Invalid message'); } elseif (!($id_contact = (int)Tools::getValue('id_contact')) || !(Validate::isLoadedObject($contact = new Contact($id_contact, $this->context->language->id)))) { $this->errors[] = Tools::displayError('Please select a subject from the list provided. '); } elseif (!empty($file_attachment['name']) && $file_attachment['error'] != 0) { $this->errors[] = Tools::displayError('An error occurred during the file-upload process.'); } elseif (!empty($file_attachment['name']) && !in_array(Tools::strtolower(substr($file_attachment['name'], -4)), $extension) && !in_array(Tools::strtolower(substr($file_attachment['name'], -5)), $extension)) { $this->errors[] = Tools::displayError('Bad file extension'); } elseif (!$mathAnswer) { $this->errors[] = Tools::displayError('Sum verification cannot be empty.'); } elseif ($mathSum!=$mathAnswer) { $this->errors[] = Tools::displayError('The sum of the numbers is incorrect. Please try again.'); } elseif ($url === false || !empty($url) || $saveContactKey != (Tools::getValue('contactKey'))) { $this->errors[] = Tools::displayError('An error occurred while sending the message.'); } else { $customer = $this->context->customer; if (!$customer->id) { $customer->getByEmail($from); } $id_order = (int)$this->getOrder(); /** * Check if customer select his order. */ if (!empty($id_order)) { $order = new Order($id_order); $id_order = (int) $order->id_customer === (int) $customer->id ? $id_order : 0; } if (!(( ($id_customer_thread = (int)Tools::getValue('id_customer_thread')) && (int)Db::getInstance()->getValue(' SELECT cm.id_customer_thread FROM '._DB_PREFIX_.'customer_thread cm WHERE cm.id_customer_thread = '.(int)$id_customer_thread.' AND cm.id_shop = '.(int)$this->context->shop->id.' AND token = \''.pSQL(Tools::getValue('token')).'\'') ) || ( $id_customer_thread = CustomerThread::getIdCustomerThreadByEmailAndIdOrder($from, $id_order) ))) { $fields = Db::getInstance()->executeS(' SELECT cm.id_customer_thread, cm.id_contact, cm.id_customer, cm.id_order, cm.id_product, cm.email FROM '._DB_PREFIX_.'customer_thread cm WHERE email = \''.pSQL($from).'\' AND cm.id_shop = '.(int)$this->context->shop->id.' AND ('. ($customer->id ? 'id_customer = '.(int)$customer->id.' OR ' : '').' id_order = '.(int)$id_order.')'); $score = 0; foreach ($fields as $key => $row) { $tmp = 0; if ((int)$row['id_customer'] && $row['id_customer'] != $customer->id && $row['email'] != $from) { continue; } if ($row['id_order'] != 0 && $id_order != $row['id_order']) { continue; } if ($row['email'] == $from) { $tmp += 4; } if ($row['id_contact'] == $id_contact) { $tmp++; } if (Tools::getValue('id_product') != 0 && $row['id_product'] == Tools::getValue('id_product')) { $tmp += 2; } if ($tmp >= 5 && $tmp >= $score) { $score = $tmp; $id_customer_thread = $row['id_customer_thread']; } } } $old_message = Db::getInstance()->getValue(' SELECT cm.message FROM '._DB_PREFIX_.'customer_message cm LEFT JOIN '._DB_PREFIX_.'customer_thread cc on (cm.id_customer_thread = cc.id_customer_thread) WHERE cc.id_customer_thread = '.(int)$id_customer_thread.' AND cc.id_shop = '.(int)$this->context->shop->id.' ORDER BY cm.date_add DESC'); if ($old_message == $message) { $this->context->smarty->assign('alreadySent', 1); $contact->email = ''; $contact->customer_service = 0; } if ($contact->customer_service) { if ((int)$id_customer_thread) { $ct = new CustomerThread($id_customer_thread); $ct->status = 'open'; $ct->id_lang = (int)$this->context->language->id; $ct->id_contact = (int)$id_contact; $ct->id_order = (int)$id_order; if ($id_product = (int)Tools::getValue('id_product')) { $ct->id_product = $id_product; } $ct->update(); } else { $ct = new CustomerThread(); if (isset($customer->id)) { $ct->id_customer = (int)$customer->id; } $ct->id_shop = (int)$this->context->shop->id; $ct->id_order = (int)$id_order; if ($id_product = (int)Tools::getValue('id_product')) { $ct->id_product = $id_product; } $ct->id_contact = (int)$id_contact; $ct->id_lang = (int)$this->context->language->id; $ct->email = $from; $ct->status = 'open'; $ct->token = Tools::passwdGen(12); $ct->add(); } if ($ct->id) { $cm = new CustomerMessage(); $cm->id_customer_thread = $ct->id; $cm->message = $message; if (isset($file_attachment['rename']) && !empty($file_attachment['rename']) && rename($file_attachment['tmp_name'], _PS_UPLOAD_DIR_.basename($file_attachment['rename']))) { $cm->file_name = $file_attachment['rename']; @chmod(_PS_UPLOAD_DIR_.basename($file_attachment['rename']), 0664); } $cm->ip_address = (int)ip2long(Tools::getRemoteAddr()); $cm->user_agent = $_SERVER['HTTP_USER_AGENT']; if (!$cm->add()) { $this->errors[] = Tools::displayError('An error occurred while sending the message.'); } } else { $this->errors[] = Tools::displayError('An error occurred while sending the message.'); } } if (!count($this->errors)) { $var_list = array( '{order_name}' => '-', '{attached_file}' => '-', '{message}' => Tools::nl2br(stripslashes($message)), '{email}' => $from, '{product_name}' => '', ); if (isset($file_attachment['name'])) { $var_list['{attached_file}'] = $file_attachment['name']; } $id_product = (int)Tools::getValue('id_product'); if (isset($ct) && Validate::isLoadedObject($ct) && $ct->id_order) { $order = new Order((int)$ct->id_order); $var_list['{order_name}'] = $order->getUniqReference(); $var_list['{id_order}'] = (int)$order->id; } if ($id_product) { $product = new Product((int)$id_product); if (Validate::isLoadedObject($product) && isset($product->name[Context::getContext()->language->id])) { $var_list['{product_name}'] = $product->name[Context::getContext()->language->id]; } } if (!empty($contact->email)) { if (!Mail::Send($this->context->language->id, 'contact', Mail::l('Message from contact form').' [no_sync]', $var_list, $contact->email, $contact->name, null, null, $file_attachment, null, _PS_MAIL_DIR_, false, null, null, $from)) { $this->errors[] = Tools::displayError('An error occurred while sending the message.'); } } } if (count($this->errors) > 1) { array_unique($this->errors); } elseif (!count($this->errors)) { $this->context->smarty->assign('confirmation', 1); } } } } /** * Assign template vars related to page content * @see FrontController::initContent() */ 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'), 'max_upload_size' => (int)Tools::getMaxUploadSize() )); if (($id_customer_thread = (int)Tools::getValue('id_customer_thread')) && $token = Tools::getValue('token')) { $customer_thread = Db::getInstance()->getRow(' SELECT cm.* FROM '._DB_PREFIX_.'customer_thread cm WHERE cm.id_customer_thread = '.(int)$id_customer_thread.' AND cm.id_shop = '.(int)$this->context->shop->id.' AND token = \''.pSQL($token).'\' '); $order = new Order((int)$customer_thread['id_order']); if (Validate::isLoadedObject($order)) { $customer_thread['reference'] = $order->getUniqReference(); } $this->context->smarty->assign('customerThread', $customer_thread); } $contactKey = md5(uniqid(microtime(), true)); $this->context->cookie->__set('contactFormKey', $contactKey); $this->context->smarty->assign(array( 'contacts' => Contact::getContacts($this->context->language->id), 'message' => html_entity_decode(Tools::getValue('message')), 'contactKey' => $contactKey, )); $this->context->smarty->assign('mathNumber1', rand(1,10)); $this->context->smarty->assign('mathNumber2', rand(1,10)); $this->setTemplate(_PS_THEME_DIR_.'contact-form.tpl'); } } |
Pokud už soubor ContactController.php existuje tak je třeba jen doplnit relevantní část kódu.
Soubor s výše uvedeným kódem si můžete také stáhnout. Odkaz ke stažení je v pravém sloupci této stránky.
Po uložení souboru je třeba vymazat soubor class_index.php v adresáři /cache aby se úprava kontroleru projevila. Tento soubor se automaticky obnoví po načtení stránek.
Překlad chybových hlášek
Po této úpravě jsou texty v angličtině, takže je třeba upravit ještě překlady popisu polí v sekci Lokalizace > Překlady > UPRAVIT PŘEKLADY, kde je třeba zvolit jako typ překladu „Překlady chybových hlášek“ a jazyk :
Nová funkce formuláře jsou připravená a nyní je třeba upravit šablonu a doplnit do formuláře příslušná pole.
Úprava šablony:
Vložení formuláře
Pro účely návodu budeme předpokládat, že je aktivní výchozí šablona default-bootstrap.
V adresáři themes/default-bootstrap upravíme soubor contact-form.tpl. Najdeme sekci pro nahrávání souboru (řádek 133):
1 2 3 4 5 6 7 |
{if $fileupload == 1} <p class="form-group"> <label for="fileUpload">{l s='Attach File'}</label> <input type="hidden" name="MAX_FILE_SIZE" value="{if isset($max_upload_size) && $max_upload_size}{$max_upload_size|intval}{else}2000000{/if}" /> <input type="file" name="fileUpload" id="fileUpload" class="form-control" /> </p> {/if} |
a za ni vložíme kód:
1 2 3 4 5 6 |
<p class="form-group mathcaptcha"> <label for="mathCaptcha">{l s='The sum of numbers'}</label> <input type="text" id="mathNumber1" name="mathNumber1" value="{$mathNumber1}" hidden="true" /> <input type="text" id="mathNumber2" name="mathNumber2" value="{$mathNumber2}" hidden="true" /> <strong>{$mathNumber1}</strong> {l s='and'} <strong>{$mathNumber2}</strong> {l s='is'} <input type="text" id="mathAnswer" name="mathAnswer" autocomplete="off" class="form-control grey" /> </p> |
Výsledek by měl vypadat takto:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
{if $fileupload == 1} <p class="form-group"> <label for="fileUpload">{l s='Attach File'}</label> <input type="hidden" name="MAX_FILE_SIZE" value="{if isset($max_upload_size) && $max_upload_size}{$max_upload_size|intval}{else}2000000{/if}" /> <input type="file" name="fileUpload" id="fileUpload" class="form-control" /> </p> {/if} <p class="form-group mathcaptcha"> <label for="mathCaptcha">{l s='The sum of numbers'}</label> <input type="text" id="mathNumber1" name="mathNumber1" value="{$mathNumber1}" hidden="true" /> <input type="text" id="mathNumber2" name="mathNumber2" value="{$mathNumber2}" hidden="true" /> <strong>{$mathNumber1}</strong> {l s='and'} <strong>{$mathNumber2}</strong> {l s='is'} <input type="text" id="mathAnswer" name="mathAnswer" autocomplete="off" class="form-control grey" /> </p> </div> <div class="col-xs-12 col-md-9"> <div class="form-group"> <label for="message">{l s='Message'}</label> <textarea class="form-control" id="message" name="message">{if isset($message)}{$message|escape:'html':'UTF-8'|stripslashes}{/if}</textarea> </div> </div> |
V souboru contact-form.tpl přibyly žlutě zvýrazněné řádky.
Překlad
Po této úpravě jsou texty v angličtině, takže je třeba upravit ještě překlady popisu polí v sekci Lokalizace > Překlady > UPRAVIT PŘEKLADY, kde je třeba zvolit jako typ překladu „Překlady Obchodu„, šablonu default-bootstrap a jazyk. Příslušné texty jsou v sekci CONTACT-FORM:
Úprava vzhledu
Tato část popisuje jak zmenšit pole pro vložení výsledku a zarovnání na jeden řádek. Velikost pole se automaticky přizpůsobuje šířce stránky. Pokud vzhled vyhovuje tak je možné tuto část vynechat.
V adresáři /themes/default-bootstrap/css vložíme na konec souboru contact-form.css tento kód:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
.mathcaptcha input.form-control { margin: 10px 0; display: inline; max-width: 22px; } @media (max-width: 991px) { .mathcaptcha input.form-control { max-width: 143px; } } @media (min-width: 1200px) { .mathcaptcha input.form-control { max-width: 66px; } } |
Vymazání mezipaměti a kontrola
Po provedených úpravách vymažeme vyrovnávací paměť pomocí tlačítka Vyčistit mezipaměť v sekci Nástroje > Výkon a zkontrolujeme funkčnost formuláře.
Pokud jste se rozhodli používat HTTPS na PrestaShopu tak je k tomu kromě SSL certifikátu potřeba provést potřebné úpravy v konfiguračních souborech. Zde je stručný návod jak provést základní nastavení pro změnu HTTP na HTTPS.
UPOZORNĚNÍ: je třeba rozumět všem prováděným krokům. Doporučujeme problematiku přechodu na HTTPS důkladně prostudovat. Chybné nebo neúplné nastavení může způsobit nefunkčnost stránek nebo problémy s indexací v internetových vyhledávačích.
UPOZORNĚNÍ: u všech upravovaných souborů si nejprve vytvořte zálohu
Zprovoznění SSL certifikátu
Návod na instalaci certifikátu najdete v naší nápovědě ve článku Nastavení HTTPS šifrování.
Ověření funkčnosti SSL certifikátu
Funkčnost certifikátu si můžete ověřit tak, že v adresním řádku přidáte „s“ za http. Test proveďte na administraci PrestaShopu. Pokud ho provedete v uživatelské části tak dojde k automatickému přesměrování na HTTP. Například u domény http://www.zserver.cz/administrace změníte adresu na https://www.zserver.cz/administrace. Prohlížeč by neměl zobrazit žádné chybové hlášení. Dále existují různé online nástroje na otestování správného nastaveni SSL certifikátu. Jeden z kvalitních nástrojů je SSL Server Test od Qualsys.
Změna nastavení v administraci PrestaShopu
Nastavení je podobné ve všech verzích PrestaShopu. PrestaShop 1.4 ale podporuje HTTPS pouze pro přihlášení zákazníka a nákupní proces.
PrestaShop 1.4
Klikněte na záložku Nastavení (1). V případě, že přistupujete přes protokol HTTP tak u volby Povolit SSL (2) uvidíte odkaz Před povolením SSL klikněte prosím sem pro použití HTTPS protokolu dle obrázku A. Kliknutím na tento odkaz automaticky přejdete na HTTPS a zobrazí se volba pro Povolit SSL – Ano (3) jak je vidět na obrázku B. Po uložení bude přihlašovací a nákupní proces na HTTPS.
PrestaShop 1.5
Klikněte na záložku Konfigurace => Základní nastavení (1). V případě, že přistupujete přes protokol HTTP tak u volby Povolit SSL (2) uvidíte odkaz Před povolením SSL klikněte prosím sem pro použití HTTPS protokolu dle obrázku A. Kliknutím na tento odkaz automaticky přejdete na HTTPS a zobrazí se volba pro Povolit SSL – Ano (3) jak je vidět na obrázku B. Po uložení bude přihlašovací a nákupní proces na HTTPS.
PrestaShop 1.5.6.2 a vyšší – pokud chcete používat HTTPS na všech stránkách pak zaškrtněte i volbu Vynutit SSL pro všechny stránky (4). Pokud tuto volbu nevidíte tak opusťte stránku Základní nastavení. Při další návštěvě této stránky už by měla být tato volba vidět.
PrestaShop 1.6
Klikněte na záložku Konfigurace => Hlavní (1). V případě, že přistupujete přes protokol HTTP tak u volby Povolit SSL (2) uvidíte odkaz Před povolením SSL klikněte prosím sem pro použití HTTPS protokolu dle obrázku A. Kliknutím na tento odkaz automaticky přejdete na HTTPS a zobrazí se volba pro Povolit SSL – Ano (3) jak je vidět na obrázku B. Po uložení bude přihlašovací a nákupní proces na HTTPS. Pokud chcete používat HTTPS na všech stránkách pak zaškrtněte i volbu Vynutit SSL pro všechny stránky (4). Tato volba je dostupná až poté co je volba Povolit SSL nastavena na Ano a uložena.
Změna .htaccess souboru – pouze PrestaShop 1.5 a 1.6
Pokud máte nastavenou volbu Vynutit SSL pro všechny stránky pak můžete nastavit i automatické přesměrování. Pro automatické přesměrování z HTTP na HTTPS verzi stránek pomocí mod_rewrite je třeba v souboru .htaccess v kořenovém adresáři před klíčové slovo # ~~start~~ přidat následující kód:
1 2 3 4 5 6 7 8 |
RewriteEngine On RewriteCond %{HTTPS} off RewriteRule (.*) https://%{HTTP_HOST}%{REQUEST_URI} [R=301,L] # ~~start~~ Do not remove this comment, Prestashop will keep automatically the code outside this comment when .htaccess will be generated again # .htaccess automaticaly generated by PrestaShop e-commerce open-source solution # http://www.prestashop.com - http://www.prestashop.com/forums |
Trvalé přesměrování můžete nastavit i bez editace .htaccess souboru přímo v administraci webhostingu dle návodu na přesměrování HTTP na HTTPS.
Změna interních odkazů
Pokud se někde na stránkách odkazujete na své stránky (například v textu úvodní stránky odkazujete na kategorii nebo produkt) absolutním odkazem tedy takovým, který obsahuje i http (například http://www.vasedomena.cz/8-kategorie) tak je třeba tento odkaz přepsat na https. Pokud používáte relativní odkazy (například /8-kategorie) tak tato změna není třeba.
Přegenerování a kontrola xml feedů pro vyhledávače zboží
Pokud používáte náš XML generátor tak stačí pouze přegenerovat xml feed. Pokud používáte jiný modul tak konzultujte tuto část s dodavatelem modulu.
Kontrola vložených scriptů
Typicky se jedná o vložené scripty Facebooku či Google. Pokud budou obsahovat HTTP tak může prohlížeč zobrazit informaci že je část stránky nezabezpečená.
Změna odkazů směrujících na vaše stránky
Změňte veškeré odkazy na vaše stránky, ke kterým máte přístup.
Průběžná kontrola statistik přístupů
Po úspěšném převodu pečlivě sledujte statistiky přístupů kvůli případným problémům. Může nastat dočasný mírný pokles návštěvnosti, ale vše by se mělo brzy vrátit na původní hodnoty.
Vyšla nová verze PrestaShop 1.7 oblíbeného sytému pro tvorbu internetových obchodů. Mezi nejviditelnější novinky v administraci patří vylepšené navigační menu, přepracovaná administrace produktů a modulů. Nová verze přináší také nový výchozí vzhled zákaznického rozhraní. Více informací o novinkách najdete na oficiálních stránkách PrestaShopu. Vyzkoušet si jí můžete také na naší demo instalaci.
Připravili jsme pro vás novou verzi XML Generátoru pro vyhledávače zboží pro PrestaShop. Nová verze XML Generátoru 1.5.2 zahrnuje i nový formát XML feedu pro zboží.cz. Pokud máte u nás webhosting můžete si modul stáhnout zdarma na stránce XML Generátor (multi). XML Generátor (multi) je určen pro PrestaShop verze 1.5.x až 1.6.x.