first commit
This commit is contained in:
243
classes/form/AbstractForm.php
Normal file
243
classes/form/AbstractForm.php
Normal file
@@ -0,0 +1,243 @@
|
||||
<?php
|
||||
/**
|
||||
* Copyright since 2007 PrestaShop SA and Contributors
|
||||
* PrestaShop is an International Registered Trademark & Property of PrestaShop SA
|
||||
*
|
||||
* NOTICE OF LICENSE
|
||||
*
|
||||
* This source file is subject to the Open Software License (OSL 3.0)
|
||||
* that is bundled with this package in the file LICENSE.md.
|
||||
* It is also available through the world-wide-web at this URL:
|
||||
* https://opensource.org/licenses/OSL-3.0
|
||||
* If you did not receive a copy of the license and are unable to
|
||||
* obtain it through the world-wide-web, please send an email
|
||||
* to license@prestashop.com so we can send you a copy immediately.
|
||||
*
|
||||
* DISCLAIMER
|
||||
*
|
||||
* Do not edit or add to this file if you wish to upgrade PrestaShop to newer
|
||||
* versions in the future. If you wish to customize PrestaShop for your
|
||||
* needs please refer to https://devdocs.prestashop.com/ for more information.
|
||||
*
|
||||
* @author PrestaShop SA and Contributors <contact@prestashop.com>
|
||||
* @copyright Since 2007 PrestaShop SA and Contributors
|
||||
* @license https://opensource.org/licenses/OSL-3.0 Open Software License (OSL 3.0)
|
||||
*/
|
||||
use PrestaShop\PrestaShop\Core\Foundation\Templating\RenderableProxy;
|
||||
use Symfony\Component\Translation\TranslatorInterface;
|
||||
|
||||
abstract class AbstractFormCore implements FormInterface
|
||||
{
|
||||
private $smarty;
|
||||
protected $translator;
|
||||
protected $constraintTranslator;
|
||||
|
||||
protected $action;
|
||||
protected $template;
|
||||
|
||||
protected $formatter;
|
||||
|
||||
protected $formFields = [];
|
||||
protected $errors = ['' => []];
|
||||
|
||||
public function __construct(
|
||||
Smarty $smarty,
|
||||
TranslatorInterface $translator,
|
||||
FormFormatterInterface $formatter
|
||||
) {
|
||||
$this->smarty = $smarty;
|
||||
$this->translator = $translator;
|
||||
$this->formatter = $formatter;
|
||||
$this->constraintTranslator = new ValidateConstraintTranslator(
|
||||
$this->translator
|
||||
);
|
||||
}
|
||||
|
||||
public function getFormatter()
|
||||
{
|
||||
return $this->formatter;
|
||||
}
|
||||
|
||||
public function setAction($action)
|
||||
{
|
||||
$this->action = $action;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getAction()
|
||||
{
|
||||
return $this->action;
|
||||
}
|
||||
|
||||
public function getErrors()
|
||||
{
|
||||
foreach ($this->formFields as $field) {
|
||||
$this->errors[$field->getName()] = $field->getErrors();
|
||||
}
|
||||
|
||||
return $this->errors;
|
||||
}
|
||||
|
||||
public function hasErrors()
|
||||
{
|
||||
foreach ($this->getErrors() as $errors) {
|
||||
if (!empty($errors)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
abstract public function getTemplateVariables();
|
||||
|
||||
public function setTemplate($template)
|
||||
{
|
||||
$this->template = $template;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getTemplate()
|
||||
{
|
||||
return $this->template;
|
||||
}
|
||||
|
||||
public function render(array $extraVariables = [])
|
||||
{
|
||||
$scope = $this->smarty->createData(
|
||||
$this->smarty
|
||||
);
|
||||
|
||||
$context = Context::getContext();
|
||||
$theme = $context->shop->theme->getName();
|
||||
|
||||
$scope->assign($extraVariables);
|
||||
$scope->assign($this->getTemplateVariables());
|
||||
|
||||
$tpl = $this->smarty->createTemplate(
|
||||
$this->getTemplate(),
|
||||
$scope,
|
||||
$theme
|
||||
);
|
||||
|
||||
return $tpl->fetch();
|
||||
}
|
||||
|
||||
public function getProxy()
|
||||
{
|
||||
return new RenderableProxy($this);
|
||||
}
|
||||
|
||||
public function validate()
|
||||
{
|
||||
foreach ($this->formFields as $field) {
|
||||
if ($field->isRequired()) {
|
||||
if (!$field->getValue()) {
|
||||
$field->addError(
|
||||
$this->constraintTranslator->translate('required')
|
||||
);
|
||||
|
||||
continue;
|
||||
} elseif (!$this->checkFieldLength($field)) {
|
||||
$field->addError(
|
||||
$this->translator->trans(
|
||||
'The %1$s field is too long (%2$d chars max).',
|
||||
[$field->getLabel(), $field->getMaxLength()],
|
||||
'Shop.Notifications.Error'
|
||||
)
|
||||
);
|
||||
}
|
||||
} elseif (!$field->isRequired()) {
|
||||
if (!$field->getValue()) {
|
||||
continue;
|
||||
} elseif (!$this->checkFieldLength($field)) {
|
||||
$field->addError(
|
||||
$this->translator->trans(
|
||||
'The %1$s field is too long (%2$d chars max).',
|
||||
[$field->getLabel(), $field->getMaxLength()],
|
||||
'Shop.Notifications.Error'
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
foreach ($field->getConstraints() as $constraint) {
|
||||
if (!Validate::$constraint($field->getValue())) {
|
||||
$field->addError(
|
||||
$this->constraintTranslator->translate($constraint)
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return !$this->hasErrors();
|
||||
}
|
||||
|
||||
public function fillWith(array $params = [])
|
||||
{
|
||||
$newFields = $this->formatter->getFormat();
|
||||
|
||||
foreach ($newFields as $field) {
|
||||
if (array_key_exists($field->getName(), $this->formFields)) {
|
||||
// keep current value if set
|
||||
$field->setValue($this->formFields[$field->getName()]->getValue());
|
||||
}
|
||||
|
||||
if (array_key_exists($field->getName(), $params)) {
|
||||
// overwrite it if necessary
|
||||
$field->setValue($params[$field->getName()]);
|
||||
} elseif ($field->getType() === 'checkbox') {
|
||||
// checkboxes that are not submitted
|
||||
// are interpreted as booleans switched off
|
||||
if (empty($field->getValue())) {
|
||||
$field->setValue(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$this->formFields = $newFields;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getField($field_name)
|
||||
{
|
||||
if (array_key_exists($field_name, $this->formFields)) {
|
||||
return $this->formFields[$field_name];
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public function getValue($field_name)
|
||||
{
|
||||
if ($field = $this->getField($field_name)) {
|
||||
return $field->getValue();
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public function setValue($field_name, $value)
|
||||
{
|
||||
$this->getField($field_name)->setValue($value);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Validate field length
|
||||
*
|
||||
* @param $field the field to check
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
protected function checkFieldLength($field)
|
||||
{
|
||||
$error = $field->getMaxLength() != null && strlen($field->getValue()) > (int) $field->getMaxLength();
|
||||
|
||||
return !$error;
|
||||
}
|
||||
}
|
||||
219
classes/form/CustomerAddressForm.php
Normal file
219
classes/form/CustomerAddressForm.php
Normal file
@@ -0,0 +1,219 @@
|
||||
<?php
|
||||
/**
|
||||
* Copyright since 2007 PrestaShop SA and Contributors
|
||||
* PrestaShop is an International Registered Trademark & Property of PrestaShop SA
|
||||
*
|
||||
* NOTICE OF LICENSE
|
||||
*
|
||||
* This source file is subject to the Open Software License (OSL 3.0)
|
||||
* that is bundled with this package in the file LICENSE.md.
|
||||
* It is also available through the world-wide-web at this URL:
|
||||
* https://opensource.org/licenses/OSL-3.0
|
||||
* If you did not receive a copy of the license and are unable to
|
||||
* obtain it through the world-wide-web, please send an email
|
||||
* to license@prestashop.com so we can send you a copy immediately.
|
||||
*
|
||||
* DISCLAIMER
|
||||
*
|
||||
* Do not edit or add to this file if you wish to upgrade PrestaShop to newer
|
||||
* versions in the future. If you wish to customize PrestaShop for your
|
||||
* needs please refer to https://devdocs.prestashop.com/ for more information.
|
||||
*
|
||||
* @author PrestaShop SA and Contributors <contact@prestashop.com>
|
||||
* @copyright Since 2007 PrestaShop SA and Contributors
|
||||
* @license https://opensource.org/licenses/OSL-3.0 Open Software License (OSL 3.0)
|
||||
*/
|
||||
use Symfony\Component\Translation\TranslatorInterface;
|
||||
|
||||
/**
|
||||
* StarterTheme TODO: FIXME:
|
||||
* In the old days, when updating an address, we actually:
|
||||
* - checked if the address was used by an order
|
||||
* - if so, just mark it as deleted and create a new one
|
||||
* - otherwise, update it like a normal entity
|
||||
* I *think* this is not necessary now because the invoicing thing
|
||||
* does its own historization. But this should be checked more thoroughly.
|
||||
*/
|
||||
class CustomerAddressFormCore extends AbstractForm
|
||||
{
|
||||
private $language;
|
||||
|
||||
protected $template = 'customer/_partials/address-form.tpl';
|
||||
|
||||
private $address;
|
||||
|
||||
private $persister;
|
||||
|
||||
public function __construct(
|
||||
Smarty $smarty,
|
||||
Language $language,
|
||||
TranslatorInterface $translator,
|
||||
CustomerAddressPersister $persister,
|
||||
CustomerAddressFormatter $formatter
|
||||
) {
|
||||
parent::__construct(
|
||||
$smarty,
|
||||
$translator,
|
||||
$formatter
|
||||
);
|
||||
|
||||
$this->language = $language;
|
||||
$this->persister = $persister;
|
||||
}
|
||||
|
||||
public function loadAddressById($id_address)
|
||||
{
|
||||
$context = Context::getContext();
|
||||
|
||||
$this->address = new Address($id_address, $this->language->id);
|
||||
|
||||
if ($this->address->id === null) {
|
||||
return Tools::redirect('pagenotfound');
|
||||
}
|
||||
|
||||
if (!$context->customer->isLogged() && !$context->customer->isGuest()) {
|
||||
return Tools::redirect('/index.php?controller=authentication');
|
||||
}
|
||||
|
||||
if ($this->address->id_customer != $context->customer->id) {
|
||||
return Tools::redirect('pagenotfound');
|
||||
}
|
||||
|
||||
$params = get_object_vars($this->address);
|
||||
$params['id_address'] = $this->address->id;
|
||||
|
||||
return $this->fillWith($params);
|
||||
}
|
||||
|
||||
public function fillWith(array $params = [])
|
||||
{
|
||||
// This form is very tricky: fields may change depending on which
|
||||
// country is being submitted!
|
||||
// So we first update the format if a new id_country was set.
|
||||
if (isset($params['id_country'])
|
||||
&& $params['id_country'] != $this->formatter->getCountry()->id
|
||||
) {
|
||||
$this->formatter->setCountry(new Country(
|
||||
$params['id_country'],
|
||||
$this->language->id
|
||||
));
|
||||
}
|
||||
|
||||
return parent::fillWith($params);
|
||||
}
|
||||
|
||||
public function validate()
|
||||
{
|
||||
$is_valid = true;
|
||||
|
||||
$postcode = $this->getField('postcode');
|
||||
if ($postcode && $postcode->isRequired()) {
|
||||
$country = $this->formatter->getCountry();
|
||||
if (!$country->checkZipCode($postcode->getValue())) {
|
||||
$postcode->addError($this->translator->trans(
|
||||
'Invalid postcode - should look like "%zipcode%"',
|
||||
['%zipcode%' => $country->zip_code_format],
|
||||
'Shop.Forms.Errors'
|
||||
));
|
||||
$is_valid = false;
|
||||
}
|
||||
}
|
||||
|
||||
if (($hookReturn = Hook::exec('actionValidateCustomerAddressForm', ['form' => $this])) !== '') {
|
||||
$is_valid &= (bool) $hookReturn;
|
||||
}
|
||||
|
||||
return $is_valid && parent::validate();
|
||||
}
|
||||
|
||||
public function submit()
|
||||
{
|
||||
if (!$this->validate()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$address = new Address(
|
||||
Tools::getValue('id_address'),
|
||||
$this->language->id
|
||||
);
|
||||
|
||||
foreach ($this->formFields as $formField) {
|
||||
$address->{$formField->getName()} = $formField->getValue();
|
||||
}
|
||||
|
||||
if (!isset($this->formFields['id_state'])) {
|
||||
$address->id_state = 0;
|
||||
}
|
||||
|
||||
if (empty($address->alias)) {
|
||||
$address->alias = $this->translator->trans('My Address', [], 'Shop.Theme.Checkout');
|
||||
}
|
||||
|
||||
Hook::exec('actionSubmitCustomerAddressForm', ['address' => &$address]);
|
||||
|
||||
$this->setAddress($address);
|
||||
|
||||
return $this->getPersister()->save(
|
||||
$address,
|
||||
$this->getValue('token')
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Address
|
||||
*/
|
||||
public function getAddress()
|
||||
{
|
||||
return $this->address;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return CustomerAddressPersister
|
||||
*/
|
||||
protected function getPersister()
|
||||
{
|
||||
return $this->persister;
|
||||
}
|
||||
|
||||
protected function setAddress(Address $address)
|
||||
{
|
||||
$this->address = $address;
|
||||
}
|
||||
|
||||
public function getTemplateVariables()
|
||||
{
|
||||
$context = Context::getContext();
|
||||
|
||||
if (!$this->formFields) {
|
||||
// This is usually done by fillWith but the form may be
|
||||
// rendered before fillWith is called.
|
||||
// I don't want to assign formFields in the constructor
|
||||
// because it accesses the DB and a constructor should not
|
||||
// have side effects.
|
||||
$this->formFields = $this->formatter->getFormat();
|
||||
}
|
||||
|
||||
$this->setValue('token', $this->persister->getToken());
|
||||
$formFields = array_map(
|
||||
function (FormField $item) {
|
||||
return $item->toArray();
|
||||
},
|
||||
$this->formFields
|
||||
);
|
||||
|
||||
if (empty($formFields['firstname']['value'])) {
|
||||
$formFields['firstname']['value'] = $context->customer->firstname;
|
||||
}
|
||||
|
||||
if (empty($formFields['lastname']['value'])) {
|
||||
$formFields['lastname']['value'] = $context->customer->lastname;
|
||||
}
|
||||
|
||||
return [
|
||||
'id_address' => (isset($this->address->id)) ? $this->address->id : 0,
|
||||
'action' => $this->action,
|
||||
'errors' => $this->getErrors(),
|
||||
'formFields' => $formFields,
|
||||
];
|
||||
}
|
||||
}
|
||||
238
classes/form/CustomerAddressFormatter.php
Normal file
238
classes/form/CustomerAddressFormatter.php
Normal file
@@ -0,0 +1,238 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Copyright since 2007 PrestaShop SA and Contributors
|
||||
* PrestaShop is an International Registered Trademark & Property of PrestaShop SA
|
||||
*
|
||||
* NOTICE OF LICENSE
|
||||
*
|
||||
* This source file is subject to the Open Software License (OSL 3.0)
|
||||
* that is bundled with this package in the file LICENSE.md.
|
||||
* It is also available through the world-wide-web at this URL:
|
||||
* https://opensource.org/licenses/OSL-3.0
|
||||
* If you did not receive a copy of the license and are unable to
|
||||
* obtain it through the world-wide-web, please send an email
|
||||
* to license@prestashop.com so we can send you a copy immediately.
|
||||
*
|
||||
* DISCLAIMER
|
||||
*
|
||||
* Do not edit or add to this file if you wish to upgrade PrestaShop to newer
|
||||
* versions in the future. If you wish to customize PrestaShop for your
|
||||
* needs please refer to https://devdocs.prestashop.com/ for more information.
|
||||
*
|
||||
* @author PrestaShop SA and Contributors <contact@prestashop.com>
|
||||
* @copyright Since 2007 PrestaShop SA and Contributors
|
||||
* @license https://opensource.org/licenses/OSL-3.0 Open Software License (OSL 3.0)
|
||||
*/
|
||||
use Symfony\Component\Translation\TranslatorInterface;
|
||||
|
||||
class CustomerAddressFormatterCore implements FormFormatterInterface
|
||||
{
|
||||
private $country;
|
||||
private $translator;
|
||||
private $availableCountries;
|
||||
private $definition;
|
||||
|
||||
public function __construct(
|
||||
Country $country,
|
||||
TranslatorInterface $translator,
|
||||
array $availableCountries
|
||||
) {
|
||||
$this->country = $country;
|
||||
$this->translator = $translator;
|
||||
$this->availableCountries = $availableCountries;
|
||||
$this->definition = Address::$definition['fields'];
|
||||
}
|
||||
|
||||
public function setCountry(Country $country)
|
||||
{
|
||||
$this->country = $country;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getCountry()
|
||||
{
|
||||
return $this->country;
|
||||
}
|
||||
|
||||
public function getFormat()
|
||||
{
|
||||
$fields = AddressFormat::getOrderedAddressFields(
|
||||
$this->country->id,
|
||||
true,
|
||||
true
|
||||
);
|
||||
$required = array_flip(AddressFormat::getFieldsRequired());
|
||||
|
||||
$format = [
|
||||
'back' => (new FormField())
|
||||
->setName('back')
|
||||
->setType('hidden'),
|
||||
'token' => (new FormField())
|
||||
->setName('token')
|
||||
->setType('hidden'),
|
||||
'alias' => (new FormField())
|
||||
->setName('alias')
|
||||
->setLabel(
|
||||
$this->getFieldLabel('alias')
|
||||
),
|
||||
];
|
||||
|
||||
foreach ($fields as $field) {
|
||||
$formField = new FormField();
|
||||
$formField->setName($field);
|
||||
|
||||
$fieldParts = explode(':', $field, 2);
|
||||
|
||||
if (count($fieldParts) === 1) {
|
||||
if ($field === 'postcode') {
|
||||
if ($this->country->need_zip_code) {
|
||||
$formField->setRequired(true);
|
||||
}
|
||||
} elseif ($field === 'phone') {
|
||||
$formField->setType('tel');
|
||||
} elseif ($field === 'dni' && null !== $this->country) {
|
||||
if ($this->country->need_identification_number) {
|
||||
$formField->setRequired(true);
|
||||
}
|
||||
}
|
||||
} elseif (count($fieldParts) === 2) {
|
||||
list($entity, $entityField) = $fieldParts;
|
||||
|
||||
// Fields specified using the Entity:field
|
||||
// notation are actually references to other
|
||||
// entities, so they should be displayed as a select
|
||||
$formField->setType('select');
|
||||
|
||||
// Also, what we really want is the id of the linked entity
|
||||
$formField->setName('id_' . strtolower($entity));
|
||||
|
||||
if ($entity === 'Country') {
|
||||
$formField->setType('countrySelect');
|
||||
$formField->setValue($this->country->id);
|
||||
foreach ($this->availableCountries as $country) {
|
||||
$formField->addAvailableValue(
|
||||
$country['id_country'],
|
||||
$country[$entityField]
|
||||
);
|
||||
}
|
||||
} elseif ($entity === 'State') {
|
||||
if ($this->country->contains_states) {
|
||||
$states = State::getStatesByIdCountry($this->country->id, true, 'name', 'asc');
|
||||
foreach ($states as $state) {
|
||||
$formField->addAvailableValue(
|
||||
$state['id_state'],
|
||||
$state[$entityField]
|
||||
);
|
||||
}
|
||||
$formField->setRequired(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$formField->setLabel($this->getFieldLabel($field));
|
||||
if (!$formField->isRequired()) {
|
||||
// Only trust the $required array for fields
|
||||
// that are not marked as required.
|
||||
// $required doesn't have all the info, and fields
|
||||
// may be required for other reasons than what
|
||||
// AddressFormat::getFieldsRequired() says.
|
||||
$formField->setRequired(
|
||||
array_key_exists($field, $required)
|
||||
);
|
||||
}
|
||||
|
||||
$format[$formField->getName()] = $formField;
|
||||
}
|
||||
|
||||
//To add the extra fields in address form
|
||||
$additionalAddressFormFields = Hook::exec('additionalCustomerAddressFields', ['fields' => &$format], null, true);
|
||||
if (is_array($additionalAddressFormFields)) {
|
||||
foreach ($additionalAddressFormFields as $moduleName => $additionnalFormFields) {
|
||||
if (!is_array($additionnalFormFields)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
foreach ($additionnalFormFields as $formField) {
|
||||
$formField->moduleName = $moduleName;
|
||||
$format[$moduleName . '_' . $formField->getName()] = $formField;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $this->addConstraints(
|
||||
$this->addMaxLength(
|
||||
$format
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
private function addConstraints(array $format)
|
||||
{
|
||||
foreach ($format as $field) {
|
||||
if (!empty($this->definition[$field->getName()]['validate'])) {
|
||||
$field->addConstraint(
|
||||
$this->definition[$field->getName()]['validate']
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
return $format;
|
||||
}
|
||||
|
||||
private function addMaxLength(array $format)
|
||||
{
|
||||
foreach ($format as $field) {
|
||||
if (!empty($this->definition[$field->getName()]['size'])) {
|
||||
$field->setMaxLength(
|
||||
$this->definition[$field->getName()]['size']
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
return $format;
|
||||
}
|
||||
|
||||
private function getFieldLabel($field)
|
||||
{
|
||||
// Country:name => Country, Country:iso_code => Country,
|
||||
// same label regardless of which field is used for mapping.
|
||||
$field = explode(':', $field)[0];
|
||||
|
||||
switch ($field) {
|
||||
case 'alias':
|
||||
return $this->translator->trans('Alias', [], 'Shop.Forms.Labels');
|
||||
case 'firstname':
|
||||
return $this->translator->trans('First name', [], 'Shop.Forms.Labels');
|
||||
case 'lastname':
|
||||
return $this->translator->trans('Last name', [], 'Shop.Forms.Labels');
|
||||
case 'address1':
|
||||
return $this->translator->trans('Address', [], 'Shop.Forms.Labels');
|
||||
case 'address2':
|
||||
return $this->translator->trans('Address Complement', [], 'Shop.Forms.Labels');
|
||||
case 'postcode':
|
||||
return $this->translator->trans('Zip/Postal Code', [], 'Shop.Forms.Labels');
|
||||
case 'city':
|
||||
return $this->translator->trans('City', [], 'Shop.Forms.Labels');
|
||||
case 'Country':
|
||||
return $this->translator->trans('Country', [], 'Shop.Forms.Labels');
|
||||
case 'State':
|
||||
return $this->translator->trans('State', [], 'Shop.Forms.Labels');
|
||||
case 'phone':
|
||||
return $this->translator->trans('Phone', [], 'Shop.Forms.Labels');
|
||||
case 'phone_mobile':
|
||||
return $this->translator->trans('Mobile phone', [], 'Shop.Forms.Labels');
|
||||
case 'company':
|
||||
return $this->translator->trans('Company', [], 'Shop.Forms.Labels');
|
||||
case 'vat_number':
|
||||
return $this->translator->trans('VAT number', [], 'Shop.Forms.Labels');
|
||||
case 'dni':
|
||||
return $this->translator->trans('Identification number', [], 'Shop.Forms.Labels');
|
||||
case 'other':
|
||||
return $this->translator->trans('Other', [], 'Shop.Forms.Labels');
|
||||
default:
|
||||
return $field;
|
||||
}
|
||||
}
|
||||
}
|
||||
122
classes/form/CustomerAddressPersister.php
Normal file
122
classes/form/CustomerAddressPersister.php
Normal file
@@ -0,0 +1,122 @@
|
||||
<?php
|
||||
/**
|
||||
* Copyright since 2007 PrestaShop SA and Contributors
|
||||
* PrestaShop is an International Registered Trademark & Property of PrestaShop SA
|
||||
*
|
||||
* NOTICE OF LICENSE
|
||||
*
|
||||
* This source file is subject to the Open Software License (OSL 3.0)
|
||||
* that is bundled with this package in the file LICENSE.md.
|
||||
* It is also available through the world-wide-web at this URL:
|
||||
* https://opensource.org/licenses/OSL-3.0
|
||||
* If you did not receive a copy of the license and are unable to
|
||||
* obtain it through the world-wide-web, please send an email
|
||||
* to license@prestashop.com so we can send you a copy immediately.
|
||||
*
|
||||
* DISCLAIMER
|
||||
*
|
||||
* Do not edit or add to this file if you wish to upgrade PrestaShop to newer
|
||||
* versions in the future. If you wish to customize PrestaShop for your
|
||||
* needs please refer to https://devdocs.prestashop.com/ for more information.
|
||||
*
|
||||
* @author PrestaShop SA and Contributors <contact@prestashop.com>
|
||||
* @copyright Since 2007 PrestaShop SA and Contributors
|
||||
* @license https://opensource.org/licenses/OSL-3.0 Open Software License (OSL 3.0)
|
||||
*/
|
||||
class CustomerAddressPersisterCore
|
||||
{
|
||||
private $customer;
|
||||
private $token;
|
||||
private $cart;
|
||||
|
||||
public function __construct(Customer $customer, Cart $cart, $token)
|
||||
{
|
||||
$this->customer = $customer;
|
||||
$this->cart = $cart;
|
||||
$this->token = $token;
|
||||
}
|
||||
|
||||
public function getToken()
|
||||
{
|
||||
return $this->token;
|
||||
}
|
||||
|
||||
private function authorizeChange(Address $address, $token)
|
||||
{
|
||||
if ($address->id_customer && (int) $address->id_customer !== (int) $this->customer->id) {
|
||||
// Can't touch anybody else's address
|
||||
return false;
|
||||
}
|
||||
|
||||
if ($token !== $this->token) {
|
||||
// XSS?
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public function save(Address $address, $token)
|
||||
{
|
||||
if (!$this->authorizeChange($address, $token)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$address->id_customer = $this->customer->id;
|
||||
|
||||
if ($address->isUsed()) {
|
||||
return $this->updateUsedAddress($address);
|
||||
}
|
||||
|
||||
return $address->save();
|
||||
}
|
||||
|
||||
public function delete(Address $address, $token)
|
||||
{
|
||||
if (!$this->authorizeChange($address, $token)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$id = $address->id;
|
||||
$ok = $address->delete();
|
||||
|
||||
if ($ok) {
|
||||
if ($this->cart->id_address_invoice == $id) {
|
||||
unset($this->cart->id_address_invoice);
|
||||
}
|
||||
if ($this->cart->id_address_delivery == $id) {
|
||||
unset($this->cart->id_address_delivery);
|
||||
$this->cart->updateAddressId(
|
||||
$id,
|
||||
Address::getFirstCustomerAddressId($this->customer->id)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
return $ok;
|
||||
}
|
||||
|
||||
/**
|
||||
* When an address has already been used in a placed order, it is not edited directly,
|
||||
* instead it is set to "deleted" (but kept in database) and a new address
|
||||
* is created.
|
||||
*
|
||||
* @param Address $address
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
private function updateUsedAddress(Address $address)
|
||||
{
|
||||
$old_address = new Address($address->id);
|
||||
$address->id = $address->id_address = null;
|
||||
|
||||
if ($address->save() && $old_address->delete()) {
|
||||
// a new address was created, we must update current cart
|
||||
$this->cart->updateAddressId($old_address->id, $address->id);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
278
classes/form/CustomerForm.php
Normal file
278
classes/form/CustomerForm.php
Normal file
@@ -0,0 +1,278 @@
|
||||
<?php
|
||||
/**
|
||||
* Copyright since 2007 PrestaShop SA and Contributors
|
||||
* PrestaShop is an International Registered Trademark & Property of PrestaShop SA
|
||||
*
|
||||
* NOTICE OF LICENSE
|
||||
*
|
||||
* This source file is subject to the Open Software License (OSL 3.0)
|
||||
* that is bundled with this package in the file LICENSE.md.
|
||||
* It is also available through the world-wide-web at this URL:
|
||||
* https://opensource.org/licenses/OSL-3.0
|
||||
* If you did not receive a copy of the license and are unable to
|
||||
* obtain it through the world-wide-web, please send an email
|
||||
* to license@prestashop.com so we can send you a copy immediately.
|
||||
*
|
||||
* DISCLAIMER
|
||||
*
|
||||
* Do not edit or add to this file if you wish to upgrade PrestaShop to newer
|
||||
* versions in the future. If you wish to customize PrestaShop for your
|
||||
* needs please refer to https://devdocs.prestashop.com/ for more information.
|
||||
*
|
||||
* @author PrestaShop SA and Contributors <contact@prestashop.com>
|
||||
* @copyright Since 2007 PrestaShop SA and Contributors
|
||||
* @license https://opensource.org/licenses/OSL-3.0 Open Software License (OSL 3.0)
|
||||
*/
|
||||
use PrestaShop\PrestaShop\Core\Util\InternationalizedDomainNameConverter;
|
||||
use Symfony\Component\Translation\TranslatorInterface;
|
||||
|
||||
/**
|
||||
* StarterTheme TODO: B2B fields, Genders, CSRF.
|
||||
*/
|
||||
class CustomerFormCore extends AbstractForm
|
||||
{
|
||||
protected $template = 'customer/_partials/customer-form.tpl';
|
||||
|
||||
private $context;
|
||||
private $urls;
|
||||
|
||||
private $customerPersister;
|
||||
private $guest_allowed;
|
||||
private $passwordRequired = true;
|
||||
|
||||
private $IDNConverter;
|
||||
|
||||
public function __construct(
|
||||
Smarty $smarty,
|
||||
Context $context,
|
||||
TranslatorInterface $translator,
|
||||
CustomerFormatter $formatter,
|
||||
CustomerPersister $customerPersister,
|
||||
array $urls
|
||||
) {
|
||||
parent::__construct(
|
||||
$smarty,
|
||||
$translator,
|
||||
$formatter
|
||||
);
|
||||
|
||||
$this->context = $context;
|
||||
$this->urls = $urls;
|
||||
$this->customerPersister = $customerPersister;
|
||||
$this->IDNConverter = new InternationalizedDomainNameConverter();
|
||||
}
|
||||
|
||||
public function setGuestAllowed($guest_allowed = true)
|
||||
{
|
||||
$this->formatter->setPasswordRequired(!$guest_allowed);
|
||||
$this->setPasswordRequired(!$guest_allowed);
|
||||
$this->guest_allowed = $guest_allowed;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function setPasswordRequired($passwordRequired)
|
||||
{
|
||||
$this->passwordRequired = $passwordRequired;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function fillWith(array $params = [])
|
||||
{
|
||||
if (!empty($params['email'])) {
|
||||
// In some cases, browsers convert non ASCII chars (from input type="email") to "punycode",
|
||||
// we need to convert it back
|
||||
$params['email'] = $this->IDNConverter->emailToUtf8($params['email']);
|
||||
}
|
||||
|
||||
return parent::fillWith($params);
|
||||
}
|
||||
|
||||
public function fillFromCustomer(Customer $customer)
|
||||
{
|
||||
$params = get_object_vars($customer);
|
||||
$params['birthday'] = $customer->birthday === '0000-00-00' ? null : Tools::displayDate($customer->birthday);
|
||||
|
||||
return $this->fillWith($params);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return \Customer
|
||||
*/
|
||||
public function getCustomer()
|
||||
{
|
||||
$customer = new Customer($this->context->customer->id);
|
||||
|
||||
foreach ($this->formFields as $field) {
|
||||
$customerField = $field->getName();
|
||||
if (property_exists($customer, $customerField)) {
|
||||
$customer->$customerField = $field->getValue();
|
||||
}
|
||||
}
|
||||
|
||||
return $customer;
|
||||
}
|
||||
|
||||
public function validate()
|
||||
{
|
||||
$emailField = $this->getField('email');
|
||||
$id_customer = Customer::customerExists($emailField->getValue(), true, true);
|
||||
$customer = $this->getCustomer();
|
||||
if ($id_customer && $id_customer != $customer->id) {
|
||||
$emailField->addError($this->translator->trans(
|
||||
'The email is already used, please choose another one or sign in',
|
||||
[],
|
||||
'Shop.Notifications.Error'
|
||||
));
|
||||
}
|
||||
|
||||
// check birthdayField against null case is mandatory.
|
||||
$birthdayField = $this->getField('birthday');
|
||||
if (!empty($birthdayField) &&
|
||||
!empty($birthdayField->getValue()) &&
|
||||
Validate::isBirthDate($birthdayField->getValue(), $this->context->language->date_format_lite)
|
||||
) {
|
||||
$dateBuilt = DateTime::createFromFormat(
|
||||
$this->context->language->date_format_lite,
|
||||
$birthdayField->getValue()
|
||||
);
|
||||
$birthdayField->setValue($dateBuilt->format('Y-m-d'));
|
||||
}
|
||||
|
||||
$passwordField = $this->getField('password');
|
||||
if ((!empty($passwordField->getValue()) || $this->passwordRequired)
|
||||
&& Validate::isPasswd($passwordField->getValue()) === false) {
|
||||
$passwordField->addError($this->translator->trans(
|
||||
'Password must be between 5 and 72 characters long',
|
||||
[],
|
||||
'Shop.Notifications.Error'
|
||||
));
|
||||
}
|
||||
$this->validateFieldsLengths();
|
||||
$this->validateByModules();
|
||||
|
||||
return parent::validate();
|
||||
}
|
||||
|
||||
protected function validateFieldsLengths()
|
||||
{
|
||||
$this->validateFieldLength('email', 255, $this->getEmailMaxLengthViolationMessage());
|
||||
$this->validateFieldLength('firstname', 255, $this->getFirstNameMaxLengthViolationMessage());
|
||||
$this->validateFieldLength('lastname', 255, $this->getLastNameMaxLengthViolationMessage());
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $fieldName
|
||||
* @param $maximumLength
|
||||
* @param $violationMessage
|
||||
*/
|
||||
protected function validateFieldLength($fieldName, $maximumLength, $violationMessage)
|
||||
{
|
||||
$emailField = $this->getField($fieldName);
|
||||
if (strlen($emailField->getValue()) > $maximumLength) {
|
||||
$emailField->addError($violationMessage);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return mixed
|
||||
*/
|
||||
protected function getEmailMaxLengthViolationMessage()
|
||||
{
|
||||
return $this->translator->trans(
|
||||
'The %1$s field is too long (%2$d chars max).',
|
||||
['email', 255],
|
||||
'Shop.Notifications.Error'
|
||||
);
|
||||
}
|
||||
|
||||
protected function getFirstNameMaxLengthViolationMessage()
|
||||
{
|
||||
return $this->translator->trans(
|
||||
'The %1$s field is too long (%2$d chars max).',
|
||||
['first name', 255],
|
||||
'Shop.Notifications.Error'
|
||||
);
|
||||
}
|
||||
|
||||
protected function getLastNameMaxLengthViolationMessage()
|
||||
{
|
||||
return $this->translator->trans(
|
||||
'The %1$s field is too long (%2$d chars max).',
|
||||
['last name', 255],
|
||||
'Shop.Notifications.Error'
|
||||
);
|
||||
}
|
||||
|
||||
public function submit()
|
||||
{
|
||||
if ($this->validate()) {
|
||||
$clearTextPassword = $this->getValue('password');
|
||||
$newPassword = $this->getValue('new_password');
|
||||
|
||||
$ok = $this->customerPersister->save(
|
||||
$this->getCustomer(),
|
||||
$clearTextPassword,
|
||||
$newPassword,
|
||||
$this->passwordRequired
|
||||
);
|
||||
|
||||
if (!$ok) {
|
||||
foreach ($this->customerPersister->getErrors() as $field => $errors) {
|
||||
$this->formFields[$field]->setErrors($errors);
|
||||
}
|
||||
}
|
||||
|
||||
return $ok;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public function getTemplateVariables()
|
||||
{
|
||||
return [
|
||||
'action' => $this->action,
|
||||
'urls' => $this->urls,
|
||||
'errors' => $this->getErrors(),
|
||||
'hook_create_account_form' => Hook::exec('displayCustomerAccountForm'),
|
||||
'formFields' => array_map(
|
||||
function (FormField $field) {
|
||||
return $field->toArray();
|
||||
},
|
||||
$this->formFields
|
||||
),
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* This function call the hook validateCustomerFormFields of every modules
|
||||
* which added one or several fields to the customer registration form.
|
||||
*
|
||||
* Note: they won't get all the fields from the form, but only the one
|
||||
* they added.
|
||||
*/
|
||||
private function validateByModules()
|
||||
{
|
||||
$formFieldsAssociated = [];
|
||||
// Group FormField instances by module name
|
||||
foreach ($this->formFields as $formField) {
|
||||
if (!empty($formField->moduleName)) {
|
||||
$formFieldsAssociated[$formField->moduleName][] = $formField;
|
||||
}
|
||||
}
|
||||
// Because of security reasons (i.e password), we don't send all
|
||||
// the values to the module but only the ones it created
|
||||
foreach ($formFieldsAssociated as $moduleName => $formFields) {
|
||||
if ($moduleId = Module::getModuleIdByName($moduleName)) {
|
||||
// ToDo : replace Hook::exec with HookFinder, because we expect a specific class here
|
||||
$validatedCustomerFormFields = Hook::exec('validateCustomerFormFields', ['fields' => $formFields], $moduleId, true);
|
||||
|
||||
if (is_array($validatedCustomerFormFields)) {
|
||||
array_merge($this->formFields, $validatedCustomerFormFields);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
268
classes/form/CustomerFormatter.php
Normal file
268
classes/form/CustomerFormatter.php
Normal file
@@ -0,0 +1,268 @@
|
||||
<?php
|
||||
/**
|
||||
* Copyright since 2007 PrestaShop SA and Contributors
|
||||
* PrestaShop is an International Registered Trademark & Property of PrestaShop SA
|
||||
*
|
||||
* NOTICE OF LICENSE
|
||||
*
|
||||
* This source file is subject to the Open Software License (OSL 3.0)
|
||||
* that is bundled with this package in the file LICENSE.md.
|
||||
* It is also available through the world-wide-web at this URL:
|
||||
* https://opensource.org/licenses/OSL-3.0
|
||||
* If you did not receive a copy of the license and are unable to
|
||||
* obtain it through the world-wide-web, please send an email
|
||||
* to license@prestashop.com so we can send you a copy immediately.
|
||||
*
|
||||
* DISCLAIMER
|
||||
*
|
||||
* Do not edit or add to this file if you wish to upgrade PrestaShop to newer
|
||||
* versions in the future. If you wish to customize PrestaShop for your
|
||||
* needs please refer to https://devdocs.prestashop.com/ for more information.
|
||||
*
|
||||
* @author PrestaShop SA and Contributors <contact@prestashop.com>
|
||||
* @copyright Since 2007 PrestaShop SA and Contributors
|
||||
* @license https://opensource.org/licenses/OSL-3.0 Open Software License (OSL 3.0)
|
||||
*/
|
||||
use Symfony\Component\Translation\TranslatorInterface;
|
||||
|
||||
class CustomerFormatterCore implements FormFormatterInterface
|
||||
{
|
||||
private $translator;
|
||||
private $language;
|
||||
|
||||
private $ask_for_birthdate = true;
|
||||
private $ask_for_partner_optin = true;
|
||||
private $partner_optin_is_required = true;
|
||||
private $ask_for_password = true;
|
||||
private $password_is_required = true;
|
||||
private $ask_for_new_password = false;
|
||||
|
||||
public function __construct(
|
||||
TranslatorInterface $translator,
|
||||
Language $language
|
||||
) {
|
||||
$this->translator = $translator;
|
||||
$this->language = $language;
|
||||
}
|
||||
|
||||
public function setAskForBirthdate($ask_for_birthdate)
|
||||
{
|
||||
$this->ask_for_birthdate = $ask_for_birthdate;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function setAskForPartnerOptin($ask_for_partner_optin)
|
||||
{
|
||||
$this->ask_for_partner_optin = $ask_for_partner_optin;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function setPartnerOptinRequired($partner_optin_is_required)
|
||||
{
|
||||
$this->partner_optin_is_required = $partner_optin_is_required;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function setAskForPassword($ask_for_password)
|
||||
{
|
||||
$this->ask_for_password = $ask_for_password;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function setAskForNewPassword($ask_for_new_password)
|
||||
{
|
||||
$this->ask_for_new_password = $ask_for_new_password;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function setPasswordRequired($password_is_required)
|
||||
{
|
||||
$this->password_is_required = $password_is_required;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getFormat()
|
||||
{
|
||||
$format = [];
|
||||
|
||||
$genders = Gender::getGenders($this->language->id);
|
||||
if ($genders->count() > 0) {
|
||||
$genderField = (new FormField())
|
||||
->setName('id_gender')
|
||||
->setType('radio-buttons')
|
||||
->setLabel(
|
||||
$this->translator->trans(
|
||||
'Social title',
|
||||
[],
|
||||
'Shop.Forms.Labels'
|
||||
)
|
||||
);
|
||||
foreach ($genders as $gender) {
|
||||
$genderField->addAvailableValue($gender->id, $gender->name);
|
||||
}
|
||||
$format[$genderField->getName()] = $genderField;
|
||||
}
|
||||
|
||||
$format['firstname'] = (new FormField())
|
||||
->setName('firstname')
|
||||
->setLabel(
|
||||
$this->translator->trans(
|
||||
'First name',
|
||||
[],
|
||||
'Shop.Forms.Labels'
|
||||
)
|
||||
)
|
||||
->setRequired(true)
|
||||
->addAvailableValue(
|
||||
'comment',
|
||||
$this->translator->trans('Only letters and the dot (.) character, followed by a space, are allowed.', [], 'Shop.Forms.Help')
|
||||
);
|
||||
|
||||
$format['lastname'] = (new FormField())
|
||||
->setName('lastname')
|
||||
->setLabel(
|
||||
$this->translator->trans(
|
||||
'Last name',
|
||||
[],
|
||||
'Shop.Forms.Labels'
|
||||
)
|
||||
)
|
||||
->setRequired(true)
|
||||
->addAvailableValue(
|
||||
'comment',
|
||||
$this->translator->trans('Only letters and the dot (.) character, followed by a space, are allowed.', [], 'Shop.Forms.Help')
|
||||
);
|
||||
|
||||
if (Configuration::get('PS_B2B_ENABLE')) {
|
||||
$format['company'] = (new FormField())
|
||||
->setName('company')
|
||||
->setType('text')
|
||||
->setLabel($this->translator->trans(
|
||||
'Company',
|
||||
[],
|
||||
'Shop.Forms.Labels'
|
||||
));
|
||||
$format['siret'] = (new FormField())
|
||||
->setName('siret')
|
||||
->setType('text')
|
||||
->setLabel($this->translator->trans(
|
||||
// Please localize this string with the applicable registration number type in your country. For example : "SIRET" in France and "Código fiscal" in Spain.
|
||||
'Identification number',
|
||||
[],
|
||||
'Shop.Forms.Labels'
|
||||
));
|
||||
}
|
||||
|
||||
$format['email'] = (new FormField())
|
||||
->setName('email')
|
||||
->setType('email')
|
||||
->setLabel(
|
||||
$this->translator->trans(
|
||||
'Email',
|
||||
[],
|
||||
'Shop.Forms.Labels'
|
||||
)
|
||||
)
|
||||
->setRequired(true);
|
||||
|
||||
if ($this->ask_for_password) {
|
||||
$format['password'] = (new FormField())
|
||||
->setName('password')
|
||||
->setType('password')
|
||||
->setLabel(
|
||||
$this->translator->trans(
|
||||
'Password',
|
||||
[],
|
||||
'Shop.Forms.Labels'
|
||||
)
|
||||
)
|
||||
->setRequired($this->password_is_required);
|
||||
}
|
||||
|
||||
if ($this->ask_for_new_password) {
|
||||
$format['new_password'] = (new FormField())
|
||||
->setName('new_password')
|
||||
->setType('password')
|
||||
->setLabel(
|
||||
$this->translator->trans(
|
||||
'New password',
|
||||
[],
|
||||
'Shop.Forms.Labels'
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
if ($this->ask_for_birthdate) {
|
||||
$format['birthday'] = (new FormField())
|
||||
->setName('birthday')
|
||||
->setType('text')
|
||||
->setLabel(
|
||||
$this->translator->trans(
|
||||
'Birthdate',
|
||||
[],
|
||||
'Shop.Forms.Labels'
|
||||
)
|
||||
)
|
||||
->addAvailableValue('placeholder', Tools::getDateFormat())
|
||||
->addAvailableValue(
|
||||
'comment',
|
||||
$this->translator->trans('(E.g.: %date_format%)', ['%date_format%' => Tools::formatDateStr('31 May 1970')], 'Shop.Forms.Help')
|
||||
);
|
||||
}
|
||||
|
||||
if ($this->ask_for_partner_optin) {
|
||||
$format['optin'] = (new FormField())
|
||||
->setName('optin')
|
||||
->setType('checkbox')
|
||||
->setLabel(
|
||||
$this->translator->trans(
|
||||
'Receive offers from our partners',
|
||||
[],
|
||||
'Shop.Theme.Customeraccount'
|
||||
)
|
||||
)
|
||||
->setRequired($this->partner_optin_is_required);
|
||||
}
|
||||
|
||||
// ToDo, replace the hook exec with HookFinder when the associated PR will be merged
|
||||
$additionalCustomerFormFields = Hook::exec('additionalCustomerFormFields', ['fields' => &$format], null, true);
|
||||
|
||||
if (is_array($additionalCustomerFormFields)) {
|
||||
foreach ($additionalCustomerFormFields as $moduleName => $additionnalFormFields) {
|
||||
if (!is_array($additionnalFormFields)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
foreach ($additionnalFormFields as $formField) {
|
||||
$formField->moduleName = $moduleName;
|
||||
$format[$moduleName . '_' . $formField->getName()] = $formField;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: TVA etc.?
|
||||
|
||||
return $this->addConstraints($format);
|
||||
}
|
||||
|
||||
private function addConstraints(array $format)
|
||||
{
|
||||
$constraints = Customer::$definition['fields'];
|
||||
|
||||
foreach ($format as $field) {
|
||||
if (!empty($constraints[$field->getName()]['validate'])) {
|
||||
$field->addConstraint(
|
||||
$constraints[$field->getName()]['validate']
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
return $format;
|
||||
}
|
||||
}
|
||||
122
classes/form/CustomerLoginForm.php
Normal file
122
classes/form/CustomerLoginForm.php
Normal file
@@ -0,0 +1,122 @@
|
||||
<?php
|
||||
/**
|
||||
* Copyright since 2007 PrestaShop SA and Contributors
|
||||
* PrestaShop is an International Registered Trademark & Property of PrestaShop SA
|
||||
*
|
||||
* NOTICE OF LICENSE
|
||||
*
|
||||
* This source file is subject to the Open Software License (OSL 3.0)
|
||||
* that is bundled with this package in the file LICENSE.md.
|
||||
* It is also available through the world-wide-web at this URL:
|
||||
* https://opensource.org/licenses/OSL-3.0
|
||||
* If you did not receive a copy of the license and are unable to
|
||||
* obtain it through the world-wide-web, please send an email
|
||||
* to license@prestashop.com so we can send you a copy immediately.
|
||||
*
|
||||
* DISCLAIMER
|
||||
*
|
||||
* Do not edit or add to this file if you wish to upgrade PrestaShop to newer
|
||||
* versions in the future. If you wish to customize PrestaShop for your
|
||||
* needs please refer to https://devdocs.prestashop.com/ for more information.
|
||||
*
|
||||
* @author PrestaShop SA and Contributors <contact@prestashop.com>
|
||||
* @copyright Since 2007 PrestaShop SA and Contributors
|
||||
* @license https://opensource.org/licenses/OSL-3.0 Open Software License (OSL 3.0)
|
||||
*/
|
||||
use PrestaShop\PrestaShop\Core\Util\InternationalizedDomainNameConverter;
|
||||
use Symfony\Component\Translation\TranslatorInterface;
|
||||
|
||||
class CustomerLoginFormCore extends AbstractForm
|
||||
{
|
||||
private $context;
|
||||
private $urls;
|
||||
|
||||
protected $template = 'customer/_partials/login-form.tpl';
|
||||
|
||||
/**
|
||||
* @var InternationalizedDomainNameConverter
|
||||
*/
|
||||
private $IDNConverter;
|
||||
|
||||
public function __construct(
|
||||
Smarty $smarty,
|
||||
Context $context,
|
||||
TranslatorInterface $translator,
|
||||
CustomerLoginFormatter $formatter,
|
||||
array $urls
|
||||
) {
|
||||
parent::__construct(
|
||||
$smarty,
|
||||
$translator,
|
||||
$formatter
|
||||
);
|
||||
|
||||
$this->context = $context;
|
||||
$this->translator = $translator;
|
||||
$this->formatter = $formatter;
|
||||
$this->urls = $urls;
|
||||
$this->constraintTranslator = new ValidateConstraintTranslator(
|
||||
$this->translator
|
||||
);
|
||||
$this->IDNConverter = new InternationalizedDomainNameConverter();
|
||||
}
|
||||
|
||||
public function submit()
|
||||
{
|
||||
if ($this->validate()) {
|
||||
Hook::exec('actionAuthenticationBefore');
|
||||
|
||||
$customer = new Customer();
|
||||
$authentication = $customer->getByEmail(
|
||||
$this->getValue('email'),
|
||||
$this->getValue('password')
|
||||
);
|
||||
|
||||
if (isset($authentication->active) && !$authentication->active) {
|
||||
$this->errors[''][] = $this->translator->trans('Your account isn\'t available at this time, please contact us', [], 'Shop.Notifications.Error');
|
||||
} elseif (!$authentication || !$customer->id || $customer->is_guest) {
|
||||
$this->errors[''][] = $this->translator->trans('Authentication failed.', [], 'Shop.Notifications.Error');
|
||||
} else {
|
||||
$this->context->updateCustomer($customer);
|
||||
|
||||
Hook::exec('actionAuthentication', ['customer' => $this->context->customer]);
|
||||
|
||||
// Login information have changed, so we check if the cart rules still apply
|
||||
CartRule::autoRemoveFromCart($this->context);
|
||||
CartRule::autoAddToCart($this->context);
|
||||
}
|
||||
}
|
||||
|
||||
return !$this->hasErrors();
|
||||
}
|
||||
|
||||
public function fillWith(array $params = [])
|
||||
{
|
||||
if (!empty($params['email'])) {
|
||||
// In some cases, browsers convert non ASCII chars (from input type="email") to "punycode",
|
||||
// we need to convert it back
|
||||
$params['email'] = $this->IDNConverter->emailToUtf8($params['email']);
|
||||
}
|
||||
|
||||
return parent::fillWith($params);
|
||||
}
|
||||
|
||||
public function getTemplateVariables()
|
||||
{
|
||||
if (!$this->formFields) {
|
||||
$this->formFields = $this->formatter->getFormat();
|
||||
}
|
||||
|
||||
return [
|
||||
'action' => $this->action,
|
||||
'urls' => $this->urls,
|
||||
'formFields' => array_map(
|
||||
function (FormField $field) {
|
||||
return $field->toArray();
|
||||
},
|
||||
$this->formFields
|
||||
),
|
||||
'errors' => $this->getErrors(),
|
||||
];
|
||||
}
|
||||
}
|
||||
67
classes/form/CustomerLoginFormatter.php
Normal file
67
classes/form/CustomerLoginFormatter.php
Normal file
@@ -0,0 +1,67 @@
|
||||
<?php
|
||||
/**
|
||||
* Copyright since 2007 PrestaShop SA and Contributors
|
||||
* PrestaShop is an International Registered Trademark & Property of PrestaShop SA
|
||||
*
|
||||
* NOTICE OF LICENSE
|
||||
*
|
||||
* This source file is subject to the Open Software License (OSL 3.0)
|
||||
* that is bundled with this package in the file LICENSE.md.
|
||||
* It is also available through the world-wide-web at this URL:
|
||||
* https://opensource.org/licenses/OSL-3.0
|
||||
* If you did not receive a copy of the license and are unable to
|
||||
* obtain it through the world-wide-web, please send an email
|
||||
* to license@prestashop.com so we can send you a copy immediately.
|
||||
*
|
||||
* DISCLAIMER
|
||||
*
|
||||
* Do not edit or add to this file if you wish to upgrade PrestaShop to newer
|
||||
* versions in the future. If you wish to customize PrestaShop for your
|
||||
* needs please refer to https://devdocs.prestashop.com/ for more information.
|
||||
*
|
||||
* @author PrestaShop SA and Contributors <contact@prestashop.com>
|
||||
* @copyright Since 2007 PrestaShop SA and Contributors
|
||||
* @license https://opensource.org/licenses/OSL-3.0 Open Software License (OSL 3.0)
|
||||
*/
|
||||
use Symfony\Component\Translation\TranslatorInterface;
|
||||
|
||||
class CustomerLoginFormatterCore implements FormFormatterInterface
|
||||
{
|
||||
private $translator;
|
||||
|
||||
public function __construct(TranslatorInterface $translator)
|
||||
{
|
||||
$this->translator = $translator;
|
||||
}
|
||||
|
||||
public function getFormat()
|
||||
{
|
||||
return [
|
||||
'back' => (new FormField())
|
||||
->setName('back')
|
||||
->setType('hidden'),
|
||||
'email' => (new FormField())
|
||||
->setName('email')
|
||||
->setType('email')
|
||||
->setAutocompleteAttribute('email')
|
||||
->setRequired(true)
|
||||
->setLabel($this->translator->trans(
|
||||
'Email',
|
||||
[],
|
||||
'Shop.Forms.Labels'
|
||||
))
|
||||
->addConstraint('isEmail'),
|
||||
'password' => (new FormField())
|
||||
->setName('password')
|
||||
->setType('password')
|
||||
->setAutocompleteAttribute('current-password')
|
||||
->setRequired(true)
|
||||
->setLabel($this->translator->trans(
|
||||
'Password',
|
||||
[],
|
||||
'Shop.Forms.Labels'
|
||||
))
|
||||
->addConstraint('isPasswd'),
|
||||
];
|
||||
}
|
||||
}
|
||||
232
classes/form/CustomerPersister.php
Normal file
232
classes/form/CustomerPersister.php
Normal file
@@ -0,0 +1,232 @@
|
||||
<?php
|
||||
/**
|
||||
* Copyright since 2007 PrestaShop SA and Contributors
|
||||
* PrestaShop is an International Registered Trademark & Property of PrestaShop SA
|
||||
*
|
||||
* NOTICE OF LICENSE
|
||||
*
|
||||
* This source file is subject to the Open Software License (OSL 3.0)
|
||||
* that is bundled with this package in the file LICENSE.md.
|
||||
* It is also available through the world-wide-web at this URL:
|
||||
* https://opensource.org/licenses/OSL-3.0
|
||||
* If you did not receive a copy of the license and are unable to
|
||||
* obtain it through the world-wide-web, please send an email
|
||||
* to license@prestashop.com so we can send you a copy immediately.
|
||||
*
|
||||
* DISCLAIMER
|
||||
*
|
||||
* Do not edit or add to this file if you wish to upgrade PrestaShop to newer
|
||||
* versions in the future. If you wish to customize PrestaShop for your
|
||||
* needs please refer to https://devdocs.prestashop.com/ for more information.
|
||||
*
|
||||
* @author PrestaShop SA and Contributors <contact@prestashop.com>
|
||||
* @copyright Since 2007 PrestaShop SA and Contributors
|
||||
* @license https://opensource.org/licenses/OSL-3.0 Open Software License (OSL 3.0)
|
||||
*/
|
||||
use PrestaShop\PrestaShop\Core\Crypto\Hashing as Crypto;
|
||||
use Symfony\Component\Translation\TranslatorInterface;
|
||||
|
||||
class CustomerPersisterCore
|
||||
{
|
||||
private $errors = [];
|
||||
private $context;
|
||||
private $crypto;
|
||||
private $translator;
|
||||
private $guest_allowed;
|
||||
|
||||
public function __construct(
|
||||
Context $context,
|
||||
Crypto $crypto,
|
||||
TranslatorInterface $translator,
|
||||
$guest_allowed
|
||||
) {
|
||||
$this->context = $context;
|
||||
$this->crypto = $crypto;
|
||||
$this->translator = $translator;
|
||||
$this->guest_allowed = $guest_allowed;
|
||||
}
|
||||
|
||||
public function getErrors()
|
||||
{
|
||||
return $this->errors;
|
||||
}
|
||||
|
||||
public function save(Customer $customer, $clearTextPassword, $newPassword = '', $passwordRequired = true)
|
||||
{
|
||||
if ($customer->id) {
|
||||
return $this->update($customer, $clearTextPassword, $newPassword, $passwordRequired);
|
||||
}
|
||||
|
||||
return $this->create($customer, $clearTextPassword);
|
||||
}
|
||||
|
||||
private function update(Customer $customer, $clearTextPassword, $newPassword, $passwordRequired = true)
|
||||
{
|
||||
if (!$customer->is_guest && $passwordRequired && !$this->crypto->checkHash(
|
||||
$clearTextPassword,
|
||||
$customer->passwd,
|
||||
_COOKIE_KEY_
|
||||
)) {
|
||||
$msg = $this->translator->trans(
|
||||
'Invalid email/password combination',
|
||||
[],
|
||||
'Shop.Notifications.Error'
|
||||
);
|
||||
$this->errors['email'][] = $msg;
|
||||
$this->errors['password'][] = $msg;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!$customer->is_guest) {
|
||||
$customer->passwd = $this->crypto->hash(
|
||||
$newPassword ? $newPassword : $clearTextPassword,
|
||||
_COOKIE_KEY_
|
||||
);
|
||||
}
|
||||
|
||||
if ($customer->is_guest || !$passwordRequired) {
|
||||
// TODO SECURITY: Audit requested
|
||||
if ($customer->id != $this->context->customer->id) {
|
||||
// Since we're updating a customer without
|
||||
// checking the password, we need to check that
|
||||
// the customer being updated is the one from the
|
||||
// current session.
|
||||
|
||||
// The error message is not great,
|
||||
// but it should only be displayed to hackers
|
||||
// so it should not be an issue :)
|
||||
|
||||
$this->errors['email'][] = $this->translator->trans(
|
||||
'There seems to be an issue with your account, please contact support',
|
||||
[],
|
||||
'Shop.Notifications.Error'
|
||||
);
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
$guest_to_customer = false;
|
||||
|
||||
if ($clearTextPassword && $customer->is_guest) {
|
||||
$guest_to_customer = true;
|
||||
$customer->is_guest = false;
|
||||
$customer->passwd = $this->crypto->hash(
|
||||
$clearTextPassword,
|
||||
_COOKIE_KEY_
|
||||
);
|
||||
}
|
||||
|
||||
if ($customer->is_guest || $guest_to_customer) {
|
||||
// guest cannot update their email to that of an existing real customer
|
||||
if (Customer::customerExists($customer->email, false, true)) {
|
||||
$this->errors['email'][] = $this->translator->trans(
|
||||
'An account was already registered with this email address',
|
||||
[],
|
||||
'Shop.Notifications.Error'
|
||||
);
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if ($customer->email != $this->context->customer->email) {
|
||||
$customer->removeResetPasswordToken();
|
||||
}
|
||||
|
||||
$ok = $customer->save();
|
||||
|
||||
if ($ok) {
|
||||
$this->context->updateCustomer($customer);
|
||||
$this->context->cart->update();
|
||||
Hook::exec('actionCustomerAccountUpdate', [
|
||||
'customer' => $customer,
|
||||
]);
|
||||
if ($guest_to_customer) {
|
||||
$this->sendConfirmationMail($customer);
|
||||
}
|
||||
}
|
||||
|
||||
return $ok;
|
||||
}
|
||||
|
||||
private function create(Customer $customer, $clearTextPassword)
|
||||
{
|
||||
if (!$clearTextPassword) {
|
||||
if (!$this->guest_allowed) {
|
||||
$this->errors['password'][] = $this->translator->trans(
|
||||
'Password is required',
|
||||
[],
|
||||
'Shop.Notifications.Error'
|
||||
);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Warning: this is only safe provided
|
||||
* that guests cannot log in even with the generated
|
||||
* password. That's the case at least at the time of writing.
|
||||
*/
|
||||
$clearTextPassword = $this->crypto->hash(
|
||||
microtime(),
|
||||
_COOKIE_KEY_
|
||||
);
|
||||
|
||||
$customer->is_guest = true;
|
||||
}
|
||||
|
||||
$customer->passwd = $this->crypto->hash(
|
||||
$clearTextPassword,
|
||||
_COOKIE_KEY_
|
||||
);
|
||||
|
||||
if (Customer::customerExists($customer->email, false, true)) {
|
||||
$this->errors['email'][] = $this->translator->trans(
|
||||
'An account was already registered with this email address',
|
||||
[],
|
||||
'Shop.Notifications.Error'
|
||||
);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
$ok = $customer->save();
|
||||
|
||||
if ($ok) {
|
||||
$this->context->updateCustomer($customer);
|
||||
$this->context->cart->update();
|
||||
$this->sendConfirmationMail($customer);
|
||||
Hook::exec('actionCustomerAccountAdd', [
|
||||
'newCustomer' => $customer,
|
||||
]);
|
||||
}
|
||||
|
||||
return $ok;
|
||||
}
|
||||
|
||||
private function sendConfirmationMail(Customer $customer)
|
||||
{
|
||||
if ($customer->is_guest || !Configuration::get('PS_CUSTOMER_CREATION_EMAIL')) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return Mail::Send(
|
||||
$this->context->language->id,
|
||||
'account',
|
||||
$this->translator->trans(
|
||||
'Welcome!',
|
||||
[],
|
||||
'Emails.Subject'
|
||||
),
|
||||
[
|
||||
'{firstname}' => $customer->firstname,
|
||||
'{lastname}' => $customer->lastname,
|
||||
'{email}' => $customer->email,
|
||||
],
|
||||
$customer->email,
|
||||
$customer->firstname . ' ' . $customer->lastname
|
||||
);
|
||||
}
|
||||
}
|
||||
209
classes/form/FormField.php
Normal file
209
classes/form/FormField.php
Normal file
@@ -0,0 +1,209 @@
|
||||
<?php
|
||||
/**
|
||||
* Copyright since 2007 PrestaShop SA and Contributors
|
||||
* PrestaShop is an International Registered Trademark & Property of PrestaShop SA
|
||||
*
|
||||
* NOTICE OF LICENSE
|
||||
*
|
||||
* This source file is subject to the Open Software License (OSL 3.0)
|
||||
* that is bundled with this package in the file LICENSE.md.
|
||||
* It is also available through the world-wide-web at this URL:
|
||||
* https://opensource.org/licenses/OSL-3.0
|
||||
* If you did not receive a copy of the license and are unable to
|
||||
* obtain it through the world-wide-web, please send an email
|
||||
* to license@prestashop.com so we can send you a copy immediately.
|
||||
*
|
||||
* DISCLAIMER
|
||||
*
|
||||
* Do not edit or add to this file if you wish to upgrade PrestaShop to newer
|
||||
* versions in the future. If you wish to customize PrestaShop for your
|
||||
* needs please refer to https://devdocs.prestashop.com/ for more information.
|
||||
*
|
||||
* @author PrestaShop SA and Contributors <contact@prestashop.com>
|
||||
* @copyright Since 2007 PrestaShop SA and Contributors
|
||||
* @license https://opensource.org/licenses/OSL-3.0 Open Software License (OSL 3.0)
|
||||
*/
|
||||
class FormFieldCore
|
||||
{
|
||||
private $name = '';
|
||||
private $type = 'text';
|
||||
private $required = false;
|
||||
private $label = '';
|
||||
private $value = null;
|
||||
private $availableValues = [];
|
||||
private $maxLength = null;
|
||||
private $errors = [];
|
||||
private $constraints = [];
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
private $autocomplete = '';
|
||||
|
||||
public function toArray()
|
||||
{
|
||||
return [
|
||||
'name' => $this->getName(),
|
||||
'type' => $this->getType(),
|
||||
'required' => $this->isRequired(),
|
||||
'label' => $this->getLabel(),
|
||||
'value' => $this->getValue(),
|
||||
'availableValues' => $this->getAvailableValues(),
|
||||
'maxLength' => $this->getMaxLength(),
|
||||
'errors' => $this->getErrors(),
|
||||
'autocomplete' => $this->getAutocompleteAttribute(),
|
||||
];
|
||||
}
|
||||
|
||||
public function setName($name)
|
||||
{
|
||||
$this->name = $name;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getName()
|
||||
{
|
||||
return $this->name;
|
||||
}
|
||||
|
||||
public function setType($type)
|
||||
{
|
||||
$this->type = $type;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getType()
|
||||
{
|
||||
return $this->type;
|
||||
}
|
||||
|
||||
public function setRequired($required)
|
||||
{
|
||||
$this->required = $required;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function isRequired()
|
||||
{
|
||||
return $this->required;
|
||||
}
|
||||
|
||||
public function setLabel($label)
|
||||
{
|
||||
$this->label = $label;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getLabel()
|
||||
{
|
||||
return $this->label;
|
||||
}
|
||||
|
||||
public function setValue($value)
|
||||
{
|
||||
$this->value = $value;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getValue()
|
||||
{
|
||||
return $this->value;
|
||||
}
|
||||
|
||||
public function setAvailableValues(array $availableValues)
|
||||
{
|
||||
$this->availableValues = $availableValues;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getAvailableValues()
|
||||
{
|
||||
return $this->availableValues;
|
||||
}
|
||||
|
||||
public function addAvailableValue($availableValue, $label = null)
|
||||
{
|
||||
if (!$label) {
|
||||
$label = $availableValue;
|
||||
}
|
||||
|
||||
$this->availableValues[$availableValue] = $label;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function setMaxLength($max)
|
||||
{
|
||||
$this->maxLength = (int) $max;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getMaxLength()
|
||||
{
|
||||
return $this->maxLength;
|
||||
}
|
||||
|
||||
public function setErrors(array $errors)
|
||||
{
|
||||
$this->errors = $errors;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getErrors()
|
||||
{
|
||||
return $this->errors;
|
||||
}
|
||||
|
||||
public function addError($errorString)
|
||||
{
|
||||
$this->errors[] = $errorString;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function setConstraints(array $constraints)
|
||||
{
|
||||
$this->constraints = $constraints;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function addConstraint($constraint)
|
||||
{
|
||||
$this->constraints[] = $constraint;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getConstraints()
|
||||
{
|
||||
return $this->constraints;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $autocomplete
|
||||
*
|
||||
* @return FormFieldCore
|
||||
*/
|
||||
public function setAutocompleteAttribute(string $autocomplete): FormFieldCore
|
||||
{
|
||||
$this->autocomplete = $autocomplete;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function getAutocompleteAttribute(): string
|
||||
{
|
||||
return $this->autocomplete;
|
||||
}
|
||||
}
|
||||
29
classes/form/FormFormatterInterface.php
Normal file
29
classes/form/FormFormatterInterface.php
Normal file
@@ -0,0 +1,29 @@
|
||||
<?php
|
||||
/**
|
||||
* Copyright since 2007 PrestaShop SA and Contributors
|
||||
* PrestaShop is an International Registered Trademark & Property of PrestaShop SA
|
||||
*
|
||||
* NOTICE OF LICENSE
|
||||
*
|
||||
* This source file is subject to the Open Software License (OSL 3.0)
|
||||
* that is bundled with this package in the file LICENSE.md.
|
||||
* It is also available through the world-wide-web at this URL:
|
||||
* https://opensource.org/licenses/OSL-3.0
|
||||
* If you did not receive a copy of the license and are unable to
|
||||
* obtain it through the world-wide-web, please send an email
|
||||
* to license@prestashop.com so we can send you a copy immediately.
|
||||
*
|
||||
* DISCLAIMER
|
||||
*
|
||||
* Do not edit or add to this file if you wish to upgrade PrestaShop to newer
|
||||
* versions in the future. If you wish to customize PrestaShop for your
|
||||
* needs please refer to https://devdocs.prestashop.com/ for more information.
|
||||
*
|
||||
* @author PrestaShop SA and Contributors <contact@prestashop.com>
|
||||
* @copyright Since 2007 PrestaShop SA and Contributors
|
||||
* @license https://opensource.org/licenses/OSL-3.0 Open Software License (OSL 3.0)
|
||||
*/
|
||||
interface FormFormatterInterface
|
||||
{
|
||||
public function getFormat();
|
||||
}
|
||||
43
classes/form/FormInterface.php
Normal file
43
classes/form/FormInterface.php
Normal file
@@ -0,0 +1,43 @@
|
||||
<?php
|
||||
/**
|
||||
* Copyright since 2007 PrestaShop SA and Contributors
|
||||
* PrestaShop is an International Registered Trademark & Property of PrestaShop SA
|
||||
*
|
||||
* NOTICE OF LICENSE
|
||||
*
|
||||
* This source file is subject to the Open Software License (OSL 3.0)
|
||||
* that is bundled with this package in the file LICENSE.md.
|
||||
* It is also available through the world-wide-web at this URL:
|
||||
* https://opensource.org/licenses/OSL-3.0
|
||||
* If you did not receive a copy of the license and are unable to
|
||||
* obtain it through the world-wide-web, please send an email
|
||||
* to license@prestashop.com so we can send you a copy immediately.
|
||||
*
|
||||
* DISCLAIMER
|
||||
*
|
||||
* Do not edit or add to this file if you wish to upgrade PrestaShop to newer
|
||||
* versions in the future. If you wish to customize PrestaShop for your
|
||||
* needs please refer to https://devdocs.prestashop.com/ for more information.
|
||||
*
|
||||
* @author PrestaShop SA and Contributors <contact@prestashop.com>
|
||||
* @copyright Since 2007 PrestaShop SA and Contributors
|
||||
* @license https://opensource.org/licenses/OSL-3.0 Open Software License (OSL 3.0)
|
||||
*/
|
||||
use PrestaShop\PrestaShop\Core\Foundation\Templating\RenderableInterface;
|
||||
|
||||
interface FormInterface extends RenderableInterface
|
||||
{
|
||||
public function setAction($action);
|
||||
|
||||
public function fillWith(array $params = []);
|
||||
|
||||
public function submit();
|
||||
|
||||
public function getErrors();
|
||||
|
||||
public function hasErrors();
|
||||
|
||||
public function render(array $extraVariables = []);
|
||||
|
||||
public function setTemplate($template);
|
||||
}
|
||||
Reference in New Issue
Block a user