Merge pull request #371 from roadster31/coupons

Coupons
This commit is contained in:
Manuel Raynaud
2014-05-05 10:58:59 +02:00
46 changed files with 1094 additions and 1152 deletions

View File

@@ -27,7 +27,7 @@ use Thelia\Condition\Implementation\ConditionInterface;
class ConditionCollection implements Iterator, Countable, ArrayAccess
{
/** @var array Array of ConditionInterface */
protected $conditions = array();
protected $conditions = [];
/**
* (PHP 5 >= 5.0.0)
@@ -180,7 +180,7 @@ class ConditionCollection implements Iterator, Countable, ArrayAccess
*/
public function __toString()
{
$arrayToSerialize = array();
$arrayToSerialize = [];
/** @var ConditionInterface $condition */
foreach ($this as $condition) {
$arrayToSerialize[] = $condition->getSerializableCondition();

View File

@@ -61,7 +61,7 @@ class ConditionFactory
);
$collection[] = $conditionNone;
}
$serializableConditions = array();
$serializableConditions = [];
/** @var $condition ConditionInterface */
foreach ($collection as $condition) {
$serializableConditions[] = $condition->getSerializableCondition();

View File

@@ -18,6 +18,7 @@ use Thelia\Condition\SerializableCondition;
use Thelia\Core\Translation\Translator;
use Thelia\Coupon\FacadeInterface;
use Thelia\Exception\InvalidConditionValueException;
use Thelia\Model\Base\CurrencyQuery;
use Thelia\Model\Currency;
use Thelia\Type\FloatType;
@@ -35,10 +36,10 @@ abstract class ConditionAbstract implements ConditionInterface
protected $serviceId = null;
/** @var array Available Operators (Operators::CONST) */
protected $availableOperators = array();
protected $availableOperators = [];
/** @var array Parameters validating parameters against */
protected $validators = array();
protected $validators = [];
/** @var FacadeInterface Provide necessary value from Thelia */
protected $facade = null;
@@ -47,10 +48,10 @@ abstract class ConditionAbstract implements ConditionInterface
protected $translator = null;
/** @var array Operators set by Admin in BackOffice */
protected $operators = array();
protected $operators = [];
/** @var array Values set by Admin in BackOffice */
protected $values = array();
protected $values = [];
/** @var ConditionEvaluator Conditions validator */
protected $conditionValidator = null;
@@ -86,9 +87,9 @@ abstract class ConditionAbstract implements ConditionInterface
{
$this->validators = $this->generateInputs();
$translatedInputs = array();
$translatedInputs = [];
foreach ($this->validators as $key => $validator) {
$translatedOperators = array();
$translatedOperators = [];
foreach ($validator['availableOperators'] as $availableOperators) {
$translatedOperators[$availableOperators] = Operators::getI18n(
$this->translator,
@@ -99,7 +100,7 @@ abstract class ConditionAbstract implements ConditionInterface
$validator['availableOperators'] = $translatedOperators;
$translatedInputs[$key] = $validator;
}
$validators = array();
$validators = [];
$validators['inputs'] = $translatedInputs;
$validators['setOperators'] = $this->operators;
$validators['setValues'] = $this->values;
@@ -216,27 +217,21 @@ abstract class ConditionAbstract implements ConditionInterface
*/
protected function drawBackOfficeInputOperators($inputKey)
{
$selectHtml = '';
$optionHtml = '';
$inputs = $this->getValidators();
if (isset($inputs['inputs'][$inputKey])) {
$operators = $inputs['inputs'][$inputKey]['availableOperators'];
foreach ($operators as $key => $operator) {
$selected = '';
if (isset($this->operators) && isset($this->operators[$inputKey]) && $this->operators[$inputKey] == $key) {
$selected = ' selected="selected"';
}
$optionHtml .= '<option value="' . $key . '" '. $selected . '>' . $operator . '</option>';
}
$html = '';
$selectHtml .= '
<select class="form-control" id="' . $inputKey . '-operator" name="' . $inputKey . '[operator]">
' . $optionHtml . '
</select>
';
$inputs = $this->getValidators();
if (isset($inputs['inputs'][$inputKey])) {
$html = $this->facade->getParser()->render('coupon/condition-fragments/condition-selector.html', [
'operators' => $inputs['inputs'][$inputKey]['availableOperators'],
'value' => isset($this->operators[$inputKey]) ? $this->operators[$inputKey] : '',
'inputKey' => $inputKey
]
);
}
return $selectHtml;
return $html;
}
/**
@@ -251,26 +246,19 @@ abstract class ConditionAbstract implements ConditionInterface
protected function drawBackOfficeBaseInputsText($label, $inputKey)
{
$operatorSelectHtml = $this->drawBackOfficeInputOperators($inputKey);
$currentValue = '';
if (isset($this->values) && isset($this->values[$inputKey])) {
$currentValue = $this->values[$inputKey];
}
$html = '
<div id="condition-add-operators-values" class="form-group col-md-6">
<label for="operator">' . $label . '</label>
<div class="row">
<div class="col-lg-6">
' . $operatorSelectHtml . '
</div>
<div class="input-group col-lg-6">
<input type="text" class="form-control" id="' . $inputKey . '-value" name="' . $inputKey . '[value]" value="' . $currentValue . '">
</div>
</div>
</div>
';
return $html;
return $this->facade->getParser()->render('coupon/conditions-fragments/base-input-text.html', [
'label' => $label,
'inputKey' => $inputKey,
'currentValue' => $currentValue,
'operatorSelectHtml' => $operatorSelectHtml
]
);
}
/**
@@ -285,23 +273,39 @@ abstract class ConditionAbstract implements ConditionInterface
*/
protected function drawBackOfficeInputQuantityValues($inputKey, $max = 10, $min = 0)
{
$selectHtml = '';
$optionHtml = '';
for ($i = $min; $i <= $max; $i++) {
$selected = '';
if (isset($this->values) && isset($this->values[$inputKey]) && $this->values[$inputKey] == $i) {
$selected = ' selected="selected"';
}
$optionHtml .= '<option value="' . $i . '" ' . $selected . '>' . $i . '</option>';
}
$selectHtml .= '
<select class="form-control" id="' . $inputKey . '-value" name="' . $inputKey . '[value]">
' . $optionHtml . '
</select>
';
return $selectHtml;
return $this->facade->getParser()->render('coupon/condition-fragments/quantity-selector.html', [
'min' => $min,
'max' => $max,
'value' => isset($this->values[$inputKey]) ? $this->values[$inputKey] : '',
'inputKey' => $inputKey
]
);
}
}
/**
* Draw the currency input displayed in the BackOffice
* allowing Admin to set its Coupon Conditions
*
* @param string $inputKey Input key (ex: self::INPUT1)
*
* @return string HTML string
*/
protected function drawBackOfficeCurrencyInput($inputKey)
{
$currencies = CurrencyQuery::create()->find();
$cleanedCurrencies = [];
/** @var Currency $currency */
foreach ($currencies as $currency) {
$cleanedCurrencies[$currency->getCode()] = $currency->getSymbol();
}
return $this->facade->getParser()->render('coupon/condition-fragments/currency-selector.html', [
'currencies' => $cleanedCurrencies,
'value' => isset($this->values[$inputKey]) ? $this->values[$inputKey] : '',
'inputKey' => $inputKey
]
);
}
}

View File

@@ -25,7 +25,7 @@ class MatchForEveryone extends ConditionAbstract
protected $serviceId = 'thelia.condition.match_for_everyone';
/** @var array Available Operators (Operators::CONST) */
protected $availableOperators = array();
protected $availableOperators = [];
/**
* Check validators relevancy and store them
@@ -51,8 +51,8 @@ class MatchForEveryone extends ConditionAbstract
*/
protected function setValidators()
{
$this->operators = array();
$this->values = array();
$this->operators = [];
$this->values = [];
return $this;
}
@@ -75,8 +75,8 @@ class MatchForEveryone extends ConditionAbstract
public function getName()
{
return $this->translator->trans(
'Everybody can use it (no condition)',
array(),
'Unconditional usage',
[],
'condition'
);
}
@@ -90,8 +90,8 @@ class MatchForEveryone extends ConditionAbstract
public function getToolTip()
{
$toolTip = $this->translator->trans(
'Will return always true',
array(),
'This condition is always true',
[],
'condition'
);
@@ -107,8 +107,8 @@ class MatchForEveryone extends ConditionAbstract
public function getSummary()
{
$toolTip = $this->translator->trans(
'Will return always true',
array(),
'Unconditionnal usage',
[],
'condition'
);
@@ -122,7 +122,7 @@ class MatchForEveryone extends ConditionAbstract
*/
protected function generateInputs()
{
return array();
return [];
}
/**

View File

@@ -153,7 +153,7 @@ class MatchForTotalAmount extends ConditionAbstract
{
return $this->translator->trans(
'By cart total amount',
array(),
[],
'condition'
);
}
@@ -168,7 +168,7 @@ class MatchForTotalAmount extends ConditionAbstract
{
$toolTip = $this->translator->trans(
'Check the total Cart amount in the given currency',
array(),
[],
'condition'
);
@@ -208,7 +208,7 @@ class MatchForTotalAmount extends ConditionAbstract
protected function generateInputs()
{
$currencies = CurrencyQuery::create()->find();
$cleanedCurrencies = array();
$cleanedCurrencies = [];
/** @var Currency $currency */
foreach ($currencies as $currency) {
$cleanedCurrencies[$currency->getCode()] = $currency->getSymbol();
@@ -240,7 +240,7 @@ class MatchForTotalAmount extends ConditionAbstract
{
$labelPrice = $this->facade
->getTranslator()
->trans('Price', array(), 'condition');
->trans('Cart total amount is', [], 'condition');
$html = $this->drawBackOfficeBaseInputsText($labelPrice, self::INPUT1);
@@ -258,66 +258,17 @@ class MatchForTotalAmount extends ConditionAbstract
*/
protected function drawBackOfficeBaseInputsText($label, $inputKey)
{
$operatorSelectHtml = $this->drawBackOfficeInputOperators(self::INPUT1);
$currencySelectHtml = $this->drawBackOfficeCurrencyInput(self::INPUT2);
$selectedAmount = '';
if (isset($this->values) && isset($this->values[$inputKey])) {
$selectedAmount = $this->values[$inputKey];
}
return $this->facade->getParser()->render('coupon/condition-fragments/cart-total-amount-condition.html', [
'label' => $label,
'inputKey' => $inputKey,
'value' => isset($this->values[$inputKey]) ? $this->values[$inputKey] : '',
$html = '
<label for="operator">' . $label . '</label>
<div class="row">
<div class="col-lg-6">
' . $operatorSelectHtml . '
</div>
<div class="input-group col-lg-3">
<input type="text" class="form-control" id="' . self::INPUT1 . '-value" name="' . self::INPUT1 . '[value]" value="' . $selectedAmount . '">
</div>
<div class="input-group col-lg-3">
<input type="hidden" id="' . self::INPUT2 . '-operator" name="' . self::INPUT2 . '[operator]" value="==" />
' . $currencySelectHtml . '
</div>
</div>
';
'field_1_name' => self::INPUT1,
'field_2_name' => self::INPUT2,
return $html;
'operatorSelectHtml' => $this->drawBackOfficeInputOperators(self::INPUT1),
'currencySelectHtml' => $this->drawBackOfficeCurrencyInput(self::INPUT2),
]
);
}
/**
* Draw the currency input displayed in the BackOffice
* allowing Admin to set its Coupon Conditions
*
* @param string $inputKey Input key (ex: self::INPUT1)
*
* @return string HTML string
*/
protected function drawBackOfficeCurrencyInput($inputKey)
{
$optionHtml = '';
$currencies = CurrencyQuery::create()->find();
$cleanedCurrencies = array();
/** @var Currency $currency */
foreach ($currencies as $currency) {
$cleanedCurrencies[$currency->getCode()] = $currency->getSymbol();
}
foreach ($cleanedCurrencies as $key => $cleanedCurrency) {
$selected = '';
if (isset($this->values) && isset($this->values[$inputKey]) && $this->values[$inputKey] == $key) {
$selected = ' selected="selected"';
}
$optionHtml .= '<option value="' . $key . '" ' . $selected . '>' . $cleanedCurrency . '</option>';
}
$selectHtml = '
<select class="form-control" id="' . $inputKey . '-value" name="' . $inputKey . '[value]">
' . $optionHtml . '
</select>
';
return $selectHtml;
}
}
}

View File

@@ -127,8 +127,8 @@ class MatchForXArticles extends ConditionAbstract
public function getName()
{
return $this->translator->trans(
'By number of articles in cart',
array(),
'Cart item count condition',
[],
'condition'
);
}
@@ -142,8 +142,8 @@ class MatchForXArticles extends ConditionAbstract
public function getToolTip()
{
$toolTip = $this->translator->trans(
'Check the amount of product in the Cart',
array(),
'The cart item count should match the condition',
[],
'condition'
);
@@ -163,7 +163,7 @@ class MatchForXArticles extends ConditionAbstract
);
$toolTip = $this->translator->trans(
'If cart products quantity is <strong>%operator%</strong> %quantity%',
'If cart item count is <strong>%operator%</strong> %quantity%',
array(
'%operator%' => $i18nOperator,
'%quantity%' => $this->values[self::INPUT1]
@@ -200,7 +200,7 @@ class MatchForXArticles extends ConditionAbstract
{
$labelQuantity = $this->facade
->getTranslator()
->trans('Quantity', array(), 'condition');
->trans('Cart item count is', [], 'condition');
$html = $this->drawBackOfficeBaseInputsText($labelQuantity, self::INPUT1);
@@ -218,24 +218,11 @@ class MatchForXArticles extends ConditionAbstract
*/
protected function drawBackOfficeBaseInputsText($label, $inputKey)
{
$operatorSelectHtml = $this->drawBackOfficeInputOperators($inputKey);
$quantitySelectHtml = $this->drawBackOfficeInputQuantityValues($inputKey, 20, 1);
$html = '
<div id="condition-add-operators-values" class="form-group col-md-6">
<label for="operator">' . $label . '</label>
<div class="row">
<div class="col-lg-6">
' . $operatorSelectHtml . '
</div>
<div class="input-group col-lg-6">
' . $quantitySelectHtml . '
</div>
</div>
</div>
';
return $html;
return $this->facade->getParser()->render('coupon/condition-fragments/cart-item-count-condition.html', [
'label' => $label,
'operatorSelectHtml' => $this->drawBackOfficeInputOperators($inputKey),
'quantitySelectHtml' => $this->drawBackOfficeInputQuantityValues($inputKey, 20, 1)
]
);
}
}
}

View File

@@ -54,57 +54,57 @@ abstract class Operators
switch ($operator) {
case self::INFERIOR:
$ret = $translator->trans(
'inferior to',
array(),
'Less than',
[],
'condition'
);
break;
case self::INFERIOR_OR_EQUAL:
$ret = $translator->trans(
'inferior or equal to',
array(),
'Less than or equals',
[],
'condition'
);
break;
case self::EQUAL:
$ret = $translator->trans(
'equal to',
array(),
'Equals',
[],
'condition'
);
break;
case self::SUPERIOR_OR_EQUAL:
$ret = $translator->trans(
'superior or equal to',
array(),
'Greater than or equals',
[],
'condition'
);
break;
case self::SUPERIOR:
$ret = $translator->trans(
'superior to',
array(),
'Greater than',
[],
'condition'
);
break;
case self::DIFFERENT:
$ret = $translator->trans(
'different from',
array(),
'Not equals',
[],
'condition'
);
break;
case self::IN:
$ret = $translator->trans(
'in',
array(),
'In',
[],
'condition'
);
break;
case self::OUT:
$ret = $translator->trans(
'not in',
array(),
'Not in',
[],
'condition'
);
break;
@@ -113,4 +113,4 @@ abstract class Operators
return $ret;
}
}
}

View File

@@ -25,9 +25,9 @@ class SerializableCondition
public $conditionServiceId = null;
/** @var array Operators set by Admin for this Condition */
public $operators = array();
public $operators = [];
/** @var array Values set by Admin for this Condition */
public $values = array();
public $values = [];
}

View File

@@ -27,7 +27,6 @@ return array(
'Alerts' => 'Alertes',
'Alpha code 2 *' => 'Code Alpha 2 *',
'Alpha code 3 *' => 'Code Alpha 3 *',
'Amount removed from the cart' => 'Montant déduit du panier',
'Apply exchange rates on price in %sym' => 'Appliquer le taux de change sur le prix en %sym',
'Attribute ID:Attribute AV ID' => 'Déclinaison ID : Valeur de déclinaison ID',
'Auth mode' => 'Mode d\'authentification',
@@ -37,14 +36,15 @@ return array(
'Bad tax list JSON' => 'Mauvais JSON de la liste des taxes',
'Business ID' => 'ID du business',
'By cart total amount' => 'Montant total du panier',
'By number of articles in cart' => 'Nombre d\'articles dans le panier',
'Cannot find a default country. Please define one.' => 'Impossible de trouver un pays par défaut. Veuillez en définir un.',
'Cannot find the shop country. Please select a shop country.' => 'Impossible de trouver le pays du magasin. Veuillez en sélectionner un.',
'Cannot instanciante module "%name%": the namespace is null. Maybe the model is not loaded ?' => 'Ne peut instancier le module "%name%": le namespace est null. Peut-être que le modèle n\'est pas chargé ?',
'Cart item count condition' => 'Nombre d\'articles dans le panier',
'Cart item count is' => 'Le nombre d\'articles dans le panier est',
'Cart total amount is' => 'Le total du panier est',
'Category title *' => 'Titre de la catégorie *',
'Cellphone' => 'Numéro de portable',
'Chapo' => 'Chapeau',
'Check the amount of product in the Cart' => 'Applique une condition sur le nombre total d\'articles dans le panier',
'Check the total Cart amount in the given currency' => 'Applique une condition sur le montant total du panier dans la devise indiquée.',
'City' => 'Ville',
'Combination builder' => 'générateur de combinaison',
@@ -61,6 +61,7 @@ return array(
'Country title *' => 'Pays *',
'Critical' => 'Critique',
'Current Password' => 'Mot de passe actuel.',
'Date \'%date\' is invalid, please enter a valid date using %fmt format' => 'La date \'%date\' est incorrecte, merci d\'indiquer une date au format %fmt',
'Debug' => 'Debug',
'Default folder *' => 'Dossier par défaut *',
'Default product category *' => 'Catégorie du produit par défaut *',
@@ -71,6 +72,7 @@ return array(
'Description' => 'Description',
'Detailed description' => 'Description détaillée',
'Disabled' => 'Désactivé',
'Discount amount' => 'Montant de la remise',
'Document deleted successfully' => 'Le document a été supprimé.',
'Document position updated' => 'La position du document a été modfiée',
'EAN Code' => 'Code EAN',
@@ -79,10 +81,10 @@ return array(
'Emergency' => 'Urgence',
'Enable remote SMTP use' => 'Activer l\'utilisation d\'un serveur SMTP distant.',
'Encryption' => 'Chiffrement',
'Equals' => 'Egal à',
'Error during %action process : %error. Exception was %exc' => 'Erreur lors de %action: %error. Exception: %exc ',
'Error occured while processing order ref. %ref, ID %id: %err' => 'Un erreur est survenue paedant le traitement de la commande ref. %ref, ID %id; %err',
'Errors' => 'Erreurs',
'Everybody can use it (no condition)' => 'Tout le monde peut l\'utiliser (pas de condition)',
'Fail to delete document for %id% with parent id %parentId% (Exception : %e%)' => 'Echec lors de la suppression du document %id% avec l\'ID parent %parentId% (Exception : %e%)',
'Fail to delete image for %id% with parent id %parentId% (Exception : %e%)' => 'Echec lors de la suppression de l\'image %id% avec l\'ID parent %parentId% (Exception : %e%)',
'Fail to update document position' => 'La position du document e n\'a pas pu être modfiée',
@@ -96,8 +98,11 @@ return array(
'File is too heavy, please retry with a file having a size less than %size%.' => 'La taille du fichier est trop importante, et doit être inféreiure à %size%.',
'First Name' => 'Prénom',
'Firstname' => 'Prénom',
'Fixed Amount Discount' => 'Remise d\'un montant fixe',
'Folder title *' => 'Titre du dossier *',
'Full Name' => 'Nom complet',
'Greater than' => 'Supérieur à',
'Greater than or equals' => 'Supérieur ou égal à',
'HTML Message' => 'Message au format HTML',
'Host' => 'Nom de l\'hôte',
'I would like to receive the newsletter or the latest news.' => 'Je souhaite recevoir la lettre d\'information ou les dernières actualités.',
@@ -105,11 +110,12 @@ return array(
'ISO 639-1 Code' => 'Code ISO 639-1',
'ISO Code *' => 'Code ISO *',
'If a translation is missing or incomplete :' => 'Si une traduction est manquante ou incomplète :',
'If cart products quantity is <strong>%operator%</strong> %quantity%' => 'Si le nombre total d\'articles dans le panier est <strong>%operator%</strong> %quantity%',
'If cart item count is <strong>%operator%</strong> %quantity%' => 'Le nombre d\'articles dans le panier est <strong>%operator%</strong> %quantity% ',
'If cart total amount is <strong>%operator%</strong> %amount% %currency%' => 'Si le total du panier est <strong>%operator%</strong> %amount% %currency% ',
'Image position updated' => 'La position de l\'image a été modfiée',
'Images deleted successfully' => 'L\'image a été supprimée.',
'Impossible to delete a customer who already have orders' => 'Impossible de supprimer un client si celui-ci a déjà une commande',
'In' => 'Compris dans',
'Information' => 'Information',
'Invalid product_sale_elements' => 'product_sale_elements invalide',
'Invalid value "%value" for "%param" parameter in loop type: %type, name: %name' => 'La valeur "%value" est invalide pour le paramètre "%param" dans la boucle type: %type, nom: %name ',
@@ -118,6 +124,8 @@ return array(
'Language name' => 'Nom de la langue',
'Last Name' => 'Nom',
'Lastname' => 'Nom',
'Less than' => 'Inférieur à',
'Less than or equals' => 'Inférieur ou égal à',
'Log format *' => 'Format des logs *',
'Log level *' => 'Niveau de log *',
'Login' => 'Connexion',
@@ -149,7 +157,9 @@ return array(
'No module found for code \'%item\'' => 'Aucun module trouvé pour \'%item\' ',
'No pagination currently defined for loop name \'%name\'' => 'La pagination n\'est pas définie pour la boucle \'%name\'',
'No, I am a new customer.' => 'Non, je suis un nouveau client.',
'Not equals' => 'Différent de',
'Not found' => 'Non trouvé.',
'Not in' => 'Non compris dans',
'Notices' => 'Notices',
'Order address ID not found' => 'ID de l\'adresse de la commande non trouvé',
'Order ref. %ref is now unpaid.' => 'La commande %ref, ID %id est désormais non payée',
@@ -160,8 +170,8 @@ return array(
'Password' => 'Mot de passe',
'Password *' => 'Mot de passe *',
'Password confirmation' => 'Confirmation du mot de passe.',
'Percent Discount' => 'Remise en pourcentage de la commande',
'Percentage of the product price' => 'Pourcentage du prix du produit',
'Percentage removed from the cart' => 'Pourcentage déduit du panier',
'Phone' => 'Téléphone',
'Please accept the Terms and conditions in order to register.' => 'Veuillez accepter les termes et conditions pour vous inscrire.',
'Please check your input: %error' => 'Merci de vérifier votre saisie: %error',
@@ -174,7 +184,6 @@ return array(
'Preferred locale' => 'locale souhaitée',
'Prevent mailing template modification or deletion, except for super-admin' => 'Prévenir la suppression ou la modification ds templates de mail, excepté pour les super-administrateurs.',
'Prevent variable modification or deletion, except for super-admin' => 'Prévenir la suppression ou la modification de variables, excepté pour les super-administrateurs.',
'Price' => 'Prix',
'Price currency *' => 'Devise *',
'Processing cancelation of payment for order ref. %ref' => 'Traitement de l\'annulation du paiement de la commande %ref, ID %id',
'Processing confirmation of order ref. %ref, ID %id' => 'Traitement de la confirmation de la commande %ref, ID %id',
@@ -204,7 +213,6 @@ return array(
'Reference *' => 'Référence *',
'Related loop name \'%name\'\' is not defined.' => 'La boucle \'%name\' n\'est pas définie.',
'Remember me ?' => 'Se souvenir de moi ?',
'Remove X amount to total cart' => 'Enlève un montant fixe du total du panier',
'Remove X percent to total cart' => 'Enlève un pourcentage du panier total',
'Replace by the default language' => 'Remplacer par la langue par défaut',
'Replace current document by this file' => 'Remplacer le document courant par ce fichier',
@@ -218,6 +226,7 @@ return array(
'Shipping zone name' => 'Nom de la zone de livraison',
'Show redirections *' => 'Montrer les redirections *',
'Sorry, an error occured: %msg' => 'Désolé, une erreur est survenue : %msg',
'Sorry, an error occurred: %err' => 'Désolé, une erreur est survenue: %err',
'Sorry, you are not allowed to perform this action.' => 'Désolé, vous n\'êtes pas autorisé à réaliser cette action.',
'Sorry, you\'re not allowed to perform this action' => 'Désolé, vous n\'êtes pas autorisé à réaliser cette action.',
'Source IP' => 'IP source',
@@ -243,13 +252,15 @@ return array(
'Text File' => 'Fichier texte',
'Text Message' => 'Message au format texte',
'The TaxEngine should be passed to this form before using it.' => 'Le moteur de taxe doit être passé au formulaire avant d\'être utilisé.',
'The cart item count should match the condition' => 'Le nombre d\'articles dans le panier doit vérifier la condition',
'The image which replaces an undefined country flag (%file) was not found. Please check unknown-flag-path configuration variable, and check that the image exists.' => 'L\'image qui remplace un drapeau de pays manquant (%file) n\'a pas été trouvée. Merci de vérifier la variable de configuration unknown-flag-path.',
'The loop name \'%name\' is already defined in %className class' => 'La boucle \'%name\' est déjà définir dans la classe %className',
'This category is online.' => 'Cette catégorie est en ligne.',
'This condition is always true' => 'Cette condition est troujours vérifiée',
'This content is online.' => 'Ce contenu est en ligne.',
'This coupon does not exists' => 'Ce code promo n\'existe pas',
'This coupon will remove the entered amount to the customer total checkout. If the discount is superior to the total checkout price the customer will only pay the postage. Unless if the coupon is set to remove postage too.' => 'Ce code promo retire le montant indiqué du total de la commande. Si ce montant est supérieur au total de la commande, le client ne paiera que les frais de port, à moins que ce code promo n\'offre aussi les frais de port.',
'This coupon will remove the entered percentage to the customer total checkout. If the discount is superior to the total checkout price the customer will only pay the postage. Unless if the coupon is set to remove postage too.' => 'Ce code promo retire le pourcentage indiqué du total de la commande. Si ce montant est supérieur au total de la commande, le client ne paiera que les frais de port, à moins que ce code promo n\'offre aussi les frais de port.',
'This coupon will offert a flat percentage off a shopper\'s entire order (not applied to shipping costs or tax rates). If the discount is greater than the total order corst, the customer will only pay the shipping, or nothing if the coupon also provides free shipping.' => 'Ce code promo retire le pourcentage indiqué du total de la commande, hors frais de port et taxes. Si la remise est supérieur au total de la commande, seul le port sera facturé, à moins que le code promo n\'offre aussi les frais port.',
'This coupon will subtracts a set amount from the total cost of an order. If the discount is greater than the total order corst, the customer will only pay the shipping, or nothing if the coupon also provides free shipping.' => 'Ce code promo retire le montant indiqué du total de la commande, hors frais de port et taxes. Si la remise est supérieur au total de la commande, seul le port sera facturé, à moins que le code promo n\'offre aussi les frais port.',
'This email already exists.' => 'Cette adresse email existe déjà',
'This email does not exists' => 'Cette adresse email n\'existe pas',
'This extension must be installed and loaded' => 'Cette extension doit être installée et chargée.',
@@ -267,6 +278,8 @@ return array(
'Type' => 'Type',
'Unable to process your request. Please try again (%err).' => 'Echec lors du traitement de votre requête. Merci de ré-essayer (%err).',
'Unavailable' => 'Non disponible.',
'Unconditional usage' => 'Utilisable sans conditions',
'Unconditionnal usage' => 'Utilisable sans conditions',
'Undefined loop argument "%name"' => 'Argument de boucle invalide: "%name" ',
'Undefined search mode \'%mode\'' => 'Mode de recherche \'%mode\' invalide',
'Undefined translation type: %item' => 'Type de traduction inconnu:%item ',
@@ -278,7 +291,6 @@ return array(
'Value *' => 'Valeur *',
'Warnings' => 'Avertissements',
'Weight' => 'Poids',
'Will return always true' => 'Retourne toujours "vrai"',
'Yes, I have a password :' => 'Oui, j\'ai un mot de passe :',
'You are already registered!' => 'Vous êtes déjà enregistré !',
'You can only upload images (.png, .jpg, .jpeg, .gif)' => 'Seules les images sont autorisées (.png, .jpg, .jpeg, .gif)',
@@ -288,21 +300,13 @@ return array(
'Zip code' => 'Code postal',
'date format' => 'Format de date',
'delivery module %s is not a Thelia\Module\DeliveryModuleInterface' => 'le module de livraison %s n\'est pas un Thelia\Module\DeliveryModuleInterface',
'different from' => 'différent de',
'equal to' => 'égal à',
'in' => 'est parmis',
'inferior or equal to' => 'inférieur ou égal à',
'inferior to' => 'inférieur à',
'language locale' => 'Langue locale',
'mailing system modification' => 'Modification du système d\'envoi de mail.',
'not in' => 'n\'est pas parmis',
'password confirmation is not the same as password field' => 'le mot de passe de confirmation n\'est pas le même que le champ mot de passe',
'password must be composed of at least 4 characters' => 'le mot de passe doit être composé d\'au moins 4 caractères',
'payment module %s is not a Thelia\Module\PaymentModuleInterface' => 'Le module de paiement %s n\'est pas une instance de Thelia\Module\PaymentModuleInterface ',
'permanent discount (in percent)' => 'Remise permanente (en pourcentage)',
'quantity value is not valid' => 'la valeur de la quantité n\'est pas valide',
'superior or equal to' => 'supérieur ou égal à',
'superior to' => 'supérieur à',
'this product id does not exists : %d' => 'l\'id du produit %d n\'existe pas',
'time format' => 'Format d\'heure',
);

View File

@@ -512,10 +512,6 @@
<default key="_controller">Thelia\Controller\Admin\CouponController::updateAction</default>
<requirement key="couponId">\d+</requirement>
</route>
<route id="admin.coupon.read" path="/admin/coupon/read/{couponId}">
<default key="_controller">Thelia\Controller\Admin\CouponController::readAction</default>
<requirement key="couponId">\d+</requirement>
</route>
<route id="admin.coupon.draw.inputs.ajax" path="/admin/coupon/draw/inputs/{couponServiceId}">
<default key="_controller">Thelia\Controller\Admin\CouponController::getBackOfficeInputsAjaxAction</default>
<requirement key="couponServiceId">.*</requirement>
@@ -549,7 +545,7 @@
<!-- Routes to the Config (system variables) controller -->
<route id="admin.configuration.inedx" path="/admin/configuration">
<route id="admin.configuration.index" path="/admin/configuration">
<default key="_controller">Thelia\Controller\Admin\ConfigurationController::indexAction</default>
</route>

View File

@@ -34,6 +34,7 @@ use Thelia\Log\Tlog;
use Thelia\Model\Coupon;
use Thelia\Model\CouponQuery;
use Thelia\Model\Lang;
use Thelia\Model\LangQuery;
use Thelia\Tools\I18n;
use Thelia\Tools\Rest\ResponseRest;
@@ -53,54 +54,13 @@ class CouponController extends BaseAdminController
*/
public function browseAction()
{
$this->checkAuth(AdminResources::COUPON, array(), AccessManager::VIEW);
$args['urlReadCoupon'] = $this->getRoute(
'admin.coupon.read',
array('couponId' => 0),
Router::ABSOLUTE_URL
);
$args['urlEditCoupon'] = $this->getRoute(
'admin.coupon.update',
array('couponId' => 0),
Router::ABSOLUTE_URL
);
$args['urlCreateCoupon'] = $this->getRoute(
'admin.coupon.create',
array(),
Router::ABSOLUTE_URL
);
return $this->render('coupon-list', $args);
}
/**
* Manage Coupons read display
*
* @param int $couponId Coupon Id
*
* @return \Thelia\Core\HttpFoundation\Response
*/
public function readAction($couponId)
{
$this->checkAuth(AdminResources::COUPON, array(), AccessManager::VIEW);
$coupon = CouponQuery::create()->findPk($couponId);
if ($coupon === null) {
return $this->pageNotFound();
if (null !== $response = $this->checkAuth(AdminResources::COUPON, [], AccessManager::VIEW)) {
return $response;
}
$args['couponId'] = $couponId;
$args['urlEditCoupon'] = $this->getRoute(
'admin.coupon.update',
array('couponId' => $couponId),
Router::ABSOLUTE_URL
);
$args['coupon_order'] = $this->getListOrderFromSession('coupon', 'coupon_order', 'code');
return $this->render('coupon-read', $args);
return $this->render('coupon-list', $args);
}
/**
@@ -110,24 +70,17 @@ class CouponController extends BaseAdminController
*/
public function createAction()
{
// Check current user authorization
$response = $this->checkAuth(AdminResources::COUPON, array(), AccessManager::CREATE);
if ($response !== null) {
if (null !== $response = $this->checkAuth(AdminResources::COUPON, [], AccessManager::CREATE)) {
return $response;
}
// Parameters given to the template
$args = array();
$args = [];
$i18n = new I18n();
/** @var Lang $lang */
$lang = $this->getSession()->getLang();
$eventToDispatch = TheliaEvents::COUPON_CREATE;
if ($this->getRequest()->isMethod('POST')) {
$this->validateCreateOrUpdateForm(
$i18n,
$lang,
$eventToDispatch,
'created',
'creation'
@@ -135,15 +88,14 @@ class CouponController extends BaseAdminController
} else {
// If no input for expirationDate, now + 2 months
$defaultDate = new \DateTime();
$args['defaultDate'] = $defaultDate->modify('+2 month')
->format('Y-m-d');
$args['defaultDate'] = $defaultDate->modify('+2 month')->format($this->getDefaultDateFormat());
}
$args['dateFormat'] = $this->getSession()->getLang()->getDateFormat();
$args['dateFormat'] = $this->getDefaultDateFormat();
$args['availableCoupons'] = $this->getAvailableCoupons();
$args['urlAjaxAdminCouponDrawInputs'] = $this->getRoute(
'admin.coupon.draw.inputs.ajax',
array('couponServiceId' => 'couponServiceId'),
['couponServiceId' => 'couponServiceId'],
Router::ABSOLUTE_URL
);
$args['formAction'] = 'admin/coupon/create';
@@ -163,9 +115,7 @@ class CouponController extends BaseAdminController
*/
public function updateAction($couponId)
{
// Check current user authorization
$response = $this->checkAuth(AdminResources::COUPON, array(), AccessManager::UPDATE);
if ($response !== null) {
if (null !== $response = $this->checkAuth(AdminResources::COUPON, [], AccessManager::UPDATE)) {
return $response;
}
@@ -183,18 +133,13 @@ class CouponController extends BaseAdminController
$couponManager = $couponFactory->buildCouponFromModel($coupon);
// Parameters given to the template
$args = array();
$args = [];
$i18n = new I18n();
/** @var Lang $lang */
$lang = $this->getSession()->getLang();
$eventToDispatch = TheliaEvents::COUPON_UPDATE;
// Update
if ($this->getRequest()->isMethod('POST')) {
$this->validateCreateOrUpdateForm(
$i18n,
$lang,
$eventToDispatch,
'updated',
'update',
@@ -209,7 +154,7 @@ class CouponController extends BaseAdminController
$coupon->getSerializedConditions()
);
$data = array(
$data = [
'code' => $coupon->getCode(),
'title' => $coupon->getTitle(),
'amount' => $coupon->getAmount(),
@@ -217,14 +162,14 @@ class CouponController extends BaseAdminController
'shortDescription' => $coupon->getShortDescription(),
'description' => $coupon->getDescription(),
'isEnabled' => $coupon->getIsEnabled(),
'expirationDate' => $coupon->getExpirationDate('Y-m-d'),
'expirationDate' => $coupon->getExpirationDate($this->getDefaultDateFormat()),
'isAvailableOnSpecialOffers' => $coupon->getIsAvailableOnSpecialOffers(),
'isCumulative' => $coupon->getIsCumulative(),
'isRemovingPostage' => $coupon->getIsRemovingPostage(),
'maxUsage' => $coupon->getMaxUsage(),
'conditions' => $conditions,
'locale' => $this->getCurrentEditionLocale(),
);
];
$args['conditions'] = $this->cleanConditionForTemplate($conditions);
@@ -234,50 +179,53 @@ class CouponController extends BaseAdminController
// Pass it to the parser
$this->getParserContext()->addForm($changeForm);
}
$args['couponCode'] = $coupon->getCode();
$args['availableCoupons'] = $this->getAvailableCoupons();
$args['couponInputsHtml'] = $couponManager->drawBackOfficeInputs();
$args['urlAjaxAdminCouponDrawInputs'] = $this->getRoute(
'admin.coupon.draw.inputs.ajax',
array('couponServiceId' => 'couponServiceId'),
['couponServiceId' => 'couponServiceId'],
Router::ABSOLUTE_URL
);
$args['availableConditions'] = $this->getAvailableConditions();
$args['urlAjaxGetConditionInputFromServiceId'] = $this->getRoute(
'admin.coupon.draw.condition.read.inputs.ajax',
array('conditionId' => 'conditionId'),
['conditionId' => 'conditionId'],
Router::ABSOLUTE_URL
);
$args['urlAjaxGetConditionInputFromConditionInterface'] = $this->getRoute(
'admin.coupon.draw.condition.update.inputs.ajax',
array(
[
'couponId' => $couponId,
'conditionIndex' => 8888888
),
],
Router::ABSOLUTE_URL
);
$args['urlAjaxSaveConditions'] = $this->getRoute(
'admin.coupon.condition.save',
array('couponId' => $couponId),
['couponId' => $couponId],
Router::ABSOLUTE_URL
);
$args['urlAjaxDeleteConditions'] = $this->getRoute(
'admin.coupon.condition.delete',
array(
[
'couponId' => $couponId,
'conditionIndex' => 8888888
),
],
Router::ABSOLUTE_URL
);
$args['urlAjaxGetConditionSummaries'] = $this->getRoute(
'admin.coupon.draw.condition.summaries.ajax',
array('couponId' => $couponId),
['couponId' => $couponId],
Router::ABSOLUTE_URL
);
$args['formAction'] = 'admin/coupon/update/' . $couponId;
$args['dateFormat'] = $this->getDefaultDateFormat();
return $this->render('coupon-update', $args);
}
@@ -290,31 +238,44 @@ class CouponController extends BaseAdminController
*/
public function getConditionEmptyInputAjaxAction($conditionId)
{
$this->checkAuth(AdminResources::COUPON, array(), AccessManager::VIEW);
if (null !== $response = $this->checkAuth(AdminResources::COUPON, [], AccessManager::VIEW)) {
return $response;
}
$this->checkXmlHttpRequest();
/** @var ConditionFactory $conditionFactory */
$conditionFactory = $this->container->get('thelia.condition.factory');
$inputs = $conditionFactory->getInputsFromServiceId($conditionId);
if (!$this->container->has($conditionId)) {
return false;
if (! empty($conditionId)) {
/** @var ConditionFactory $conditionFactory */
$conditionFactory = $this->container->get('thelia.condition.factory');
$inputs = $conditionFactory->getInputsFromServiceId($conditionId);
if (!$this->container->has($conditionId)) {
return false;
}
if ($inputs === null) {
return $this->pageNotFound();
}
/** @var ConditionInterface $condition */
$condition = $this->container->get($conditionId);
$html = $condition->drawBackOfficeInputs();
$serviceId = $condition->getServiceId();
}
/** @var ConditionInterface $condition */
$condition = $this->container->get($conditionId);
if ($inputs === null) {
return $this->pageNotFound();
else {
$html = '';
$serviceId = '';
}
return $this->render(
'coupon/condition-input-ajax',
array(
'inputsDrawn' => $condition->drawBackOfficeInputs(),
'conditionServiceId' => $condition->getServiceId(),
'conditionIndex' => -1,
)
[
'inputsDrawn' => $html,
'conditionServiceId' => $serviceId,
'conditionIndex' => ''
]
);
}
@@ -328,7 +289,9 @@ class CouponController extends BaseAdminController
*/
public function getConditionToUpdateInputAjaxAction($couponId, $conditionIndex)
{
$this->checkAuth(AdminResources::COUPON, array(), AccessManager::VIEW);
if (null !== $response = $this->checkAuth(AdminResources::COUPON, [], AccessManager::VIEW)) {
return $response;
}
$this->checkXmlHttpRequest();
@@ -363,13 +326,11 @@ class CouponController extends BaseAdminController
}
return $this->render(
'coupon/condition-input-ajax',
array(
'coupon/condition-input-ajax', [
'inputsDrawn' => $condition->drawBackOfficeInputs(),
'conditionServiceId' => $condition->getServiceId(),
'conditionIndex' => $conditionIndex,
)
]
);
}
@@ -382,7 +343,9 @@ class CouponController extends BaseAdminController
*/
public function saveConditionsAction($couponId)
{
$this->checkAuth(AdminResources::COUPON, array(), AccessManager::VIEW);
if (null !== $response = $this->checkAuth(AdminResources::COUPON, [], AccessManager::UPDATE)) {
return $response;
}
$this->checkXmlHttpRequest();
@@ -429,7 +392,9 @@ class CouponController extends BaseAdminController
*/
public function deleteConditionsAction($couponId, $conditionIndex)
{
$this->checkAuth(AdminResources::COUPON, array(), AccessManager::VIEW);
if (null !== $response = $this->checkAuth(AdminResources::COUPON, [], AccessManager::UPDATE)) {
return $response;
}
$this->checkXmlHttpRequest();
@@ -457,41 +422,6 @@ class CouponController extends BaseAdminController
return new Response();
}
/**
* Build a Coupon from its form
*
* @param array $data Form data
*
* @return Coupon
*/
protected function buildCouponFromForm(array $data)
{
$couponBeingCreated = new Coupon();
$couponBeingCreated->setCode($data['code']);
$couponBeingCreated->setType($data['type']);
$couponBeingCreated->setTitle($data['title']);
$couponBeingCreated->setShortDescription($data['shortDescription']);
$couponBeingCreated->setDescription($data['description']);
$couponBeingCreated->setAmount($data['amount']);
$couponBeingCreated->setIsEnabled($data['isEnabled']);
$couponBeingCreated->setExpirationDate($data['expirationDate']);
$couponBeingCreated->setSerializedConditions(
new ConditionCollection(
array()
)
);
$couponBeingCreated->setIsCumulative($data['isCumulative']);
$couponBeingCreated->setIsRemovingPostage(
$data['isRemovingPostage']
);
$couponBeingCreated->setMaxUsage($data['maxUsage']);
$couponBeingCreated->setIsAvailableOnSpecialOffers(
$data['isAvailableOnSpecialOffers']
);
return $couponBeingCreated;
}
/**
* Log error message
*
@@ -517,8 +447,6 @@ class CouponController extends BaseAdminController
/**
* Validate the CreateOrUpdate form
*
* @param I18n $i18n Local code (fr_FR)
* @param Lang $lang Local variables container
* @param string $eventToDispatch Event which will activate actions
* @param string $log created|edited
* @param string $action creation|edition
@@ -526,15 +454,15 @@ class CouponController extends BaseAdminController
*
* @return $this
*/
protected function validateCreateOrUpdateForm(I18n $i18n, Lang $lang, $eventToDispatch, $log, $action, Coupon $model = null)
protected function validateCreateOrUpdateForm($eventToDispatch, $log, $action, Coupon $model = null)
{
// Create the form from the request
$creationForm = new CouponCreationForm($this->getRequest());
$couponForm = new CouponCreationForm($this->getRequest());
$message = false;
try {
// Check the form against conditions violations
$form = $this->validateForm($creationForm, 'POST');
$form = $this->validateForm($couponForm, 'POST');
$couponEvent = $this->feedCouponCreateOrUpdateEvent($form, $model);
@@ -553,31 +481,39 @@ class CouponController extends BaseAdminController
)
);
$this->redirect(
str_replace(
'{id}',
$couponEvent->getCouponModel()->getId(),
$creationForm->getSuccessUrl()
)
);
if ($this->getRequest()->get('save_mode') == 'stay') {
$this->redirect(
str_replace(
'{id}',
$couponEvent->getCouponModel()->getId(),
$couponForm->getSuccessUrl()
)
);
} catch (FormValidationException $e) {
exit();
}
// Redirect to the success URL
$this->redirectToRoute('admin.coupon.list');
} catch (FormValidationException $ex) {
// Invalid data entered
$message = 'Please check your input:';
$message = $this->createStandardFormValidationErrorMessage($ex);
} catch (\Exception $e) {
} catch (\Exception $ex) {
// Any other error
$message = 'Sorry, an error occurred:';
$this->logError($action, $message, $e);
$message = $this->getTranslator()->trans('Sorry, an error occurred: %err', ['%err' => $ex->getMessage()]);
$this->logError($action, $message, $ex);
}
if ($message !== false) {
// Mark the form as with error
$creationForm->setErrorMessage($message);
$couponForm->setErrorMessage($message);
// Send the form and the error to the parser
$this->getParserContext()
->addForm($creationForm)
->addForm($couponForm)
->setGeneralError($message);
}
@@ -594,10 +530,10 @@ class CouponController extends BaseAdminController
/** @var CouponManager $couponManager */
$couponManager = $this->container->get('thelia.coupon.manager');
$availableConditions = $couponManager->getAvailableConditions();
$cleanedConditions = array();
$cleanedConditions = [];
/** @var ConditionInterface $availableCondition */
foreach ($availableConditions as $availableCondition) {
$condition = array();
$condition = [];
$condition['serviceId'] = $availableCondition->getServiceId();
$condition['name'] = $availableCondition->getName();
$condition['toolTip'] = $availableCondition->getToolTip();
@@ -617,10 +553,10 @@ class CouponController extends BaseAdminController
/** @var CouponManager $couponManager */
$couponManager = $this->container->get('thelia.coupon.manager');
$availableCoupons = $couponManager->getAvailableCoupons();
$cleanedCoupons = array();
$cleanedCoupons = [];
/** @var CouponInterface $availableCoupon */
foreach ($availableCoupons as $availableCoupon) {
$condition = array();
$condition = [];
$condition['serviceId'] = $availableCoupon->getServiceId();
$condition['name'] = $availableCoupon->getName();
$condition['toolTip'] = $availableCoupon->getToolTip();
@@ -640,17 +576,17 @@ class CouponController extends BaseAdminController
*/
protected function cleanConditionForTemplate(ConditionCollection $conditions)
{
$cleanedConditions = array();
$cleanedConditions = [];
/** @var $condition ConditionInterface */
foreach ($conditions as $index => $condition) {
$temp = array(
$temp = [
'serviceId' => $condition->getServiceId(),
'index' => $index,
'name' => $condition->getName(),
'toolTip' => $condition->getToolTip(),
'summary' => $condition->getSummary(),
'validators' => $condition->getValidators()
);
];
$cleanedConditions[] = $temp;
}
@@ -667,7 +603,10 @@ class CouponController extends BaseAdminController
*/
public function getBackOfficeInputsAjaxAction($couponServiceId)
{
$this->checkAuth(AdminResources::COUPON, array(), AccessManager::VIEW);
if (null !== $response = $this->checkAuth(AdminResources::COUPON, [], AccessManager::VIEW)) {
return $response;
}
$this->checkXmlHttpRequest();
/** @var CouponInterface $coupon */
@@ -692,7 +631,10 @@ class CouponController extends BaseAdminController
*/
public function getBackOfficeConditionSummariesAjaxAction($couponId)
{
$this->checkAuth(AdminResources::COUPON, array(), AccessManager::VIEW);
if (null !== $response = $this->checkAuth(AdminResources::COUPON, [], AccessManager::VIEW)) {
return $response;
}
$this->checkXmlHttpRequest();
/** @var Coupon $coupon */
@@ -710,7 +652,7 @@ class CouponController extends BaseAdminController
return $this->pageNotFound();
}
$args = array();
$args = [];
$args['conditions'] = $this->cleanConditionForTemplate($couponManager->getConditions());
return $this->render('coupon/conditions', $args);
@@ -761,7 +703,7 @@ class CouponController extends BaseAdminController
$serviceId = $data['type'];
/** @var CouponInterface $couponManager */
$couponManager = $this->container->get($serviceId);
$effects = array(CouponAbstract::INPUT_AMOUNT_NAME => $data[CouponAbstract::INPUT_AMOUNT_NAME]);
$effects = [CouponAbstract::INPUT_AMOUNT_NAME => $data[CouponAbstract::INPUT_AMOUNT_NAME]];
$effects = $this->addExtendedLogic($effects, $couponManager->getExtendedInputs());
$couponEvent = new CouponCreateOrUpdateEvent(
@@ -772,7 +714,7 @@ class CouponController extends BaseAdminController
$data['shortDescription'],
$data['description'],
$data['isEnabled'],
\DateTime::createFromFormat('Y-m-d', $data['expirationDate']),
\DateTime::createFromFormat($this->getDefaultDateFormat(), $data['expirationDate']),
$data['isAvailableOnSpecialOffers'],
$data['isCumulative'],
$data['isRemovingPostage'],
@@ -798,8 +740,8 @@ class CouponController extends BaseAdminController
$request = $this->getRequest();
$post = $request->request->getIterator();
$serviceId = $request->request->get('categoryCondition');
$operators = array();
$values = array();
$operators = [];
$values = [];
foreach ($post as $key => $input) {
if (isset($input['operator']) && isset($input['value'])) {
$operators[$key] = $input['operator'];
@@ -857,4 +799,8 @@ class CouponController extends BaseAdminController
);
}
protected function getDefaultDateFormat()
{
return LangQuery::create()->findOneByByDefault(true)->getDateFormat();
}
}

View File

@@ -25,6 +25,9 @@ use Thelia\Core\Template\Loop\Argument\ArgumentCollection;
use Thelia\Coupon\Type\CouponInterface;
use Thelia\Model\Coupon as MCoupon;
use Thelia\Model\CouponQuery;
use Thelia\Model\Map\CouponTableMap;
use Thelia\Type\EnumListType;
use Thelia\Type\TypeCollection;
/**
* Coupon Loop
@@ -44,7 +47,23 @@ class Coupon extends BaseI18nLoop implements PropelSearchLoopInterface
{
return new ArgumentCollection(
Argument::createIntListTypeArgument('id'),
Argument::createBooleanOrBothTypeArgument('is_enabled')
Argument::createBooleanOrBothTypeArgument('is_enabled'),
new Argument(
'order',
new TypeCollection(
new EnumListType(array(
'id', 'id-reverse',
'code', 'code-reverse',
'title', 'title-reverse',
'enabled', 'enabled-reverse',
'expiration-date', 'expiration-date-reverse',
'days-left', 'days-left-reverse',
'usages-left', 'usages-left-reverse'
)
)
),
'code'
)
);
}
@@ -66,6 +85,63 @@ class Coupon extends BaseI18nLoop implements PropelSearchLoopInterface
$search->filterByIsEnabled($isEnabled ? true : false);
}
$search->addAsColumn('days_left', 'DATEDIFF('.CouponTableMap::EXPIRATION_DATE.', CURDATE()) - 1');
$orders = $this->getOrder();
foreach ($orders as $order) {
switch ($order) {
case 'id':
$search->orderById(Criteria::ASC);
break;
case 'id-reverse':
$search->orderById(Criteria::DESC);
break;
case 'code':
$search->orderByCode(Criteria::ASC);
break;
case 'code-reverse':
$search->orderByCode(Criteria::DESC);
break;
case 'title':
$search->addAscendingOrderByColumn('i18n_TITLE');
break;
case 'title-reverse':
$search->addDescendingOrderByColumn('i18n_TITLE');
break;
case 'enabled':
$search->orderByIsEnabled(Criteria::ASC);
break;
case 'enabled-reverse':
$search->orderByIsEnabled(Criteria::DESC);
break;
case 'expiration-date':
$search->orderByExpirationDate(Criteria::ASC);
break;
case 'expiration-date-reverse':
$search->orderByExpirationDate(Criteria::DESC);
break;
case 'usages-left':
$search->orderByMaxUsage(Criteria::ASC);
break;
case 'usages-left-reverse':
$search->orderByMaxUsage(Criteria::DESC);
break;
case 'days-left':
$search->addAscendingOrderByColumn('days_left');
break;
case 'days-left-reverse':
$search->addDescendingOrderByColumn('days_left');
break;
}
}
return $search;
}
@@ -81,7 +157,9 @@ class Coupon extends BaseI18nLoop implements PropelSearchLoopInterface
/** @var MCoupon $coupon */
foreach ($loopResult->getResultDataCollection() as $coupon) {
$loopResultRow = new LoopResultRow($coupon);
$conditions = $conditionFactory->unserializeConditionCollection(
$coupon->getSerializedConditions()
);
@@ -103,10 +181,6 @@ class Coupon extends BaseI18nLoop implements PropelSearchLoopInterface
$coupon->getExpirationDate()
);
$now = time();
$datediff = $coupon->getExpirationDate()->getTimestamp() - $now;
$daysLeftBeforeExpiration = floor($datediff/(60*60*24));
$cleanedConditions = array();
/** @var ConditionInterface $condition */
foreach ($conditions as $condition) {
@@ -116,14 +190,16 @@ class Coupon extends BaseI18nLoop implements PropelSearchLoopInterface
);
$cleanedConditions[] = $temp;
}
$loopResultRow->set("ID", $coupon->getId())
$loopResultRow
->set("ID", $coupon->getId())
->set("IS_TRANSLATED", $coupon->getVirtualColumn('IS_TRANSLATED'))
->set("LOCALE", $this->locale)
->set("CODE", $coupon->getCode())
->set("TITLE", $coupon->getVirtualColumn('i18n_TITLE'))
->set("SHORT_DESCRIPTION", $coupon->getVirtualColumn('i18n_SHORT_DESCRIPTION'))
->set("DESCRIPTION", $coupon->getVirtualColumn('i18n_DESCRIPTION'))
->set("EXPIRATION_DATE", $coupon->getExpirationDate($lang->getDateFormat()))
->set("EXPIRATION_DATE", $coupon->getExpirationDate())
->set("USAGE_LEFT", $coupon->getMaxUsage())
->set("IS_CUMULATIVE", $coupon->getIsCumulative())
->set("IS_REMOVING_POSTAGE", $coupon->getIsRemovingPostage())
@@ -132,7 +208,7 @@ class Coupon extends BaseI18nLoop implements PropelSearchLoopInterface
->set("AMOUNT", $coupon->getAmount())
->set("APPLICATION_CONDITIONS", $cleanedConditions)
->set("TOOLTIP", $couponManager->getToolTip())
->set("DAY_LEFT_BEFORE_EXPIRATION", $daysLeftBeforeExpiration)
->set("DAY_LEFT_BEFORE_EXPIRATION", max(0, $coupon->getVirtualColumn('days_left')))
->set("SERVICE_ID", $couponManager->getServiceId());
$loopResult->addRow($loopResultRow);
}

View File

@@ -18,6 +18,8 @@ use Symfony\Component\Translation\Translator;
use Symfony\Component\Translation\TranslatorInterface;
use Thelia\Condition\ConditionEvaluator;
use Thelia\Core\HttpFoundation\Request;
use Thelia\Core\Template\ParserInterface;
use Thelia\Core\Template\TemplateHelper;
use Thelia\Model\Coupon;
use Thelia\Model\CouponQuery;
use Thelia\Cart\CartTrait;
@@ -43,6 +45,9 @@ class BaseFacade implements FacadeInterface
/** @var Translator Service Translator */
protected $translator = null;
/** @var ParserInterface The thelia parser */
private $parser = null;
/**
* Constructor
*
@@ -197,6 +202,23 @@ class BaseFacade implements FacadeInterface
return $this->container->get('thelia.translator');
}
/**
* Return platform Parser
*
* @return ParserInterface
*/
public function getParser()
{
if ($this->parser == null) {
$this->parser = $this->container->get('thelia.parser');
// Define the current back-office template that should be used
$this->parser->setTemplateDefinition(TemplateHelper::getInstance()->getActiveAdminTemplate());
}
return $this->parser;
}
/**
* Return the main currency
* THe one used to set prices in BackOffice

View File

@@ -17,6 +17,7 @@ use Symfony\Component\DependencyInjection\ContainerInterface;
use Symfony\Component\Translation\TranslatorInterface;
use Thelia\Condition\ConditionEvaluator;
use Thelia\Core\HttpFoundation\Request;
use Thelia\Core\Template\ParserInterface;
use Thelia\Model\Coupon;
/**
@@ -129,6 +130,12 @@ interface FacadeInterface
* @return TranslatorInterface
*/
public function getTranslator();
/**
* Return platform ParserInterface
*
* @return ParserInterface
*/
public function getParser();
/**
* Return the main currency

View File

@@ -350,22 +350,16 @@ abstract class CouponAbstract implements CouponInterface
/**
* Draw the input displayed in the BackOffice
* allowing Admin to set its Coupon effect
* Override this method to do something useful
*
* @return string HTML string
*/
public function drawBackOfficeInputs()
{
$label = $this->getInputName();
$value = $this->amount;
$html = '
<div class="form-group input-' . self::INPUT_AMOUNT_NAME . ' ">
<label for="' . self::INPUT_AMOUNT_NAME . '" class="control-label">' . $label . '</label>
<input id="' . self::INPUT_AMOUNT_NAME . '" type="text" class="form-control" name="thelia_coupon_creation[' . self::INPUT_AMOUNT_NAME . ']" value="' . $value . '" placeholder="14.50">
</div>
';
return $html;
public function drawBackOfficeInputs() {
return $this->facade->getParser()->render('coupon/type-fragments/remove-x.html', [
'label' => $this->getInputName(),
'fieldName' => self::INPUT_AMOUNT_NAME,
'value' => $this->amount
]);
}
/**

View File

@@ -33,7 +33,7 @@ class RemoveXAmount extends CouponAbstract
{
return $this->facade
->getTranslator()
->trans('Remove X amount to total cart', array(), 'coupon');
->trans('Fixed Amount Discount', array(), 'coupon');
}
/**
@@ -45,7 +45,7 @@ class RemoveXAmount extends CouponAbstract
{
return $this->facade
->getTranslator()
->trans('Amount removed from the cart', array(), 'coupon');
->trans('Discount amount', array(), 'coupon');
}
/**
@@ -58,11 +58,20 @@ class RemoveXAmount extends CouponAbstract
$toolTip = $this->facade
->getTranslator()
->trans(
'This coupon will remove the entered amount to the customer total checkout. If the discount is superior to the total checkout price the customer will only pay the postage. Unless if the coupon is set to remove postage too.',
'This coupon will subtracts a set amount from the total cost of an order. If the discount is greater than the total order corst, the customer will only pay the shipping, or nothing if the coupon also provides free shipping.',
array(),
'coupon'
);
return $toolTip;
}
public function drawBackOfficeInputs()
{
return $this->facade->getParser()->render('coupon/type-fragments/remove-x-amount.html', [
'label' => $this->getInputName(),
'fieldName' => self::INPUT_AMOUNT_NAME,
'value' => $this->amount
]);
}
}

View File

@@ -116,7 +116,7 @@ class RemoveXPercent extends CouponAbstract
{
return $this->facade
->getTranslator()
->trans('Percentage removed from the cart', array(), 'coupon');
->trans('Percent Discount', array(), 'coupon');
}
/**
@@ -129,7 +129,7 @@ class RemoveXPercent extends CouponAbstract
$toolTip = $this->facade
->getTranslator()
->trans(
'This coupon will remove the entered percentage to the customer total checkout. If the discount is superior to the total checkout price the customer will only pay the postage. Unless if the coupon is set to remove postage too.',
'This coupon will offert a flat percentage off a shopper\'s entire order (not applied to shipping costs or tax rates). If the discount is greater than the total order corst, the customer will only pay the shipping, or nothing if the coupon also provides free shipping.',
array(),
'coupon'
);
@@ -145,17 +145,12 @@ class RemoveXPercent extends CouponAbstract
*/
public function drawBackOfficeInputs()
{
$labelPercentage = $this->getInputName();
$html = '
<input type="hidden" name="thelia_coupon_creation[' . self::INPUT_AMOUNT_NAME . ']" value="0"/>
<div class="form-group input-' . self::INPUT_PERCENTAGE_NAME . '">
<label for="' . self::INPUT_PERCENTAGE_NAME . '" class="control-label">' . $labelPercentage . '</label>
<input id="' . self::INPUT_PERCENTAGE_NAME . '" class="form-control" name="' . self::INPUT_EXTENDED__NAME . '[' . self::INPUT_PERCENTAGE_NAME . ']' . '" type="text" value="' . $this->percentage . '"/>
</div>
';
return $html;
return $this->facade->getParser()->render('coupon/type-fragments/remove-x-percent.html', [
'label' => $this->getInputName(),
'typeKey' => self::INPUT_AMOUNT_NAME,
'fieldId' => self::INPUT_PERCENTAGE_NAME,
'fieldName' => self::INPUT_EXTENDED__NAME,
'value' => $this->percentage
]);
}
}

View File

@@ -12,10 +12,13 @@
namespace Thelia\Form;
use Symfony\Component\Validator\Constraints\Date;
use Symfony\Component\Validator\Constraints\Callback;
use Symfony\Component\Validator\Constraints\GreaterThanOrEqual;
use Symfony\Component\Validator\Constraints\NotBlank;
use Symfony\Component\Validator\Constraints\NotEqualTo;
use Symfony\Component\Validator\ExecutionContextInterface;
use Thelia\Core\Translation\Translator;
use Thelia\Model\Base\LangQuery;
/**
* Allow to build a form Coupon
@@ -95,7 +98,11 @@ class CouponCreationForm extends BaseForm
array(
'constraints' => array(
new NotBlank(),
new Date()
new Callback(array(
"methods" => array(
array($this, "checkLocalizedDate"),
),
))
)
)
)
@@ -120,11 +127,7 @@ class CouponCreationForm extends BaseForm
array(
'constraints' => array(
new NotBlank(),
new GreaterThanOrEqual(
array(
'value' => -1
)
)
new GreaterThanOrEqual(['value' => -1])
)
)
)
@@ -139,6 +142,24 @@ class CouponCreationForm extends BaseForm
);
}
/**
* Validate a date entered with the default Language date format.
*
* @param string $value
* @param ExecutionContextInterface $context
*/
public function checkLocalizedDate($value, ExecutionContextInterface $context)
{
$format = LangQuery::create()->findOneByByDefault(true)->getDateFormat();
if (false === \DateTime::createFromFormat($format, $value)) {
$context->addViolation(Translator::getInstance()->trans("Date '%date' is invalid, please enter a valid date using %fmt format", [
'%fmt' => $format,
'%date' => $value
]));
}
}
/**
* Get form name
*

View File

@@ -1,223 +1,203 @@
<?php
/**********************************************************************************/
/* */
/* Thelia */
/* */
/* Copyright (c) OpenStudio */
/* email : info@thelia.net */
/* web : http://www.thelia.net */
/* */
/* This program is free software; you can redistribute it and/or modify */
/* it under the terms of the GNU General Public License as published by */
/* the Free Software Foundation; either version 3 of the License */
/* */
/* This program is distributed in the hope that it will be useful, */
/* but WITHOUT ANY WARRANTY; without even the implied warranty of */
/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */
/* GNU General Public License for more details. */
/* */
/* You should have received a copy of the GNU General Public License */
/* along with this program. If not, see <http://www.gnu.org/licenses/>. */
/* */
/**********************************************************************************/
namespace Thelia\Model;
use Propel\Runtime\Propel;
use Thelia\Model\Base\Coupon as BaseCoupon;
use Thelia\Model\Exception\InvalidArgumentException;
use Thelia\Model\Map\CouponTableMap;
/**
* Used to provide an effect (mostly a discount)
* at the end of the Customer checkout tunnel
* It will be usable for a Customer only if it matches the Coupon criteria (Rules)
*
* @package Coupon
* @author Guillaume MOREL <gmorel@openstudio.fr>
*
*/
class Coupon extends BaseCoupon
{
use \Thelia\Model\Tools\ModelEventDispatcherTrait;
/**
* Create or Update this Coupon
*
* @param string $code Coupon Code
* @param string $title Coupon title
* @param array $effects Ready to be serialized in JSON effect params
* @param string $type Coupon type
* @param bool $isRemovingPostage Is removing Postage
* @param string $shortDescription Coupon short description
* @param string $description Coupon description
* @param boolean $isEnabled Enable/Disable
* @param \DateTime $expirationDate Coupon expiration date
* @param boolean $isAvailableOnSpecialOffers Is available on special offers
* @param boolean $isCumulative Is cumulative
* @param int $maxUsage Coupon quantity
* @param string $defaultSerializedRule Serialized default rule added if none found
* @param string $locale Coupon Language code ISO (ex: fr_FR)
*
* @throws \Exception
*/
public function createOrUpdate($code, $title, array $effects, $type, $isRemovingPostage, $shortDescription, $description, $isEnabled, $expirationDate, $isAvailableOnSpecialOffers, $isCumulative, $maxUsage, $defaultSerializedRule, $locale = null)
{
$this->setCode($code)
->setType($type)
->setEffects($effects)
->setIsRemovingPostage($isRemovingPostage)
->setIsEnabled($isEnabled)
->setExpirationDate($expirationDate)
->setIsAvailableOnSpecialOffers($isAvailableOnSpecialOffers)
->setIsCumulative($isCumulative)
->setMaxUsage($maxUsage);
$this->setTitle($title)
->setShortDescription($shortDescription)
->setDescription($description);
// If no rule given, set default rule
if (null === $this->getSerializedConditions()) {
$this->setSerializedConditions($defaultSerializedRule);
}
// Set object language (i18n)
if (!is_null($locale)) {
$this->setLocale($locale);
}
$con = Propel::getWriteConnection(CouponTableMap::DATABASE_NAME);
$con->beginTransaction();
try {
$this->save($con);
$con->commit();
} catch (\Exception $e) {
$con->rollback();
throw $e;
}
}
/**
* Create or Update this coupon condition
*
* @param string $serializableConditions Serialized conditions ready to be saved
* @param string $locale Coupon Language code ISO (ex: fr_FR)
*
* @throws \Exception
*/
public function createOrUpdateConditions($serializableConditions, $locale)
{
$this->setSerializedConditions($serializableConditions);
// Set object language (i18n)
if (!is_null($locale)) {
$this->setLocale($locale);
}
$con = Propel::getWriteConnection(CouponTableMap::DATABASE_NAME);
$con->beginTransaction();
try {
$this->save($con);
$con->commit();
} catch (\Exception $e) {
$con->rollback();
throw $e;
}
}
/**
* Set Coupon amount
*
* @param float $amount Amount deduced from the Cart
*
* @return $this
*/
public function setAmount($amount)
{
$effects = $this->unserializeEffects($this->getSerializedEffects());
$effects['amount'] = floatval($amount);
$this->setEffects($effects);
return $this;
}
/**
* Get the amount removed from the coupon to the cart
*
* @return float
*/
public function getAmount()
{
$amount = $this->getEffects()['amount'];
return floatval($amount);
}
/**
* Get the Coupon effects
*
* @return array
* @throws Exception\InvalidArgumentException
*/
public function getEffects()
{
$effects = $this->unserializeEffects($this->getSerializedEffects());
if (null === $effects['amount']) {
throw new InvalidArgumentException('Missing key \'amount\' in Coupon effect coming from database');
}
return $effects;
}
/**
* Get the Coupon effects
*
* @param array $effects Effect ready to be serialized
* Needs at least the key 'amount'
* with the amount removed from the cart
*
* @throws Exception\InvalidArgumentException
* @return $this
*/
public function setEffects(array $effects)
{
if (null === $effects['amount']) {
throw new InvalidArgumentException('Missing key \'amount\' in Coupon effect ready to be serialized array');
}
$this->setSerializedEffects($this->serializeEffects($effects));
return $this;
}
/**
* Return unserialized effects
*
* @param string $serializedEffects Serialized effect string to unserialize
*
* @return array
*/
public function unserializeEffects($serializedEffects)
{
$effects = json_decode($serializedEffects, true);
return $effects;
}
/**
* Return serialized effects
*
* @param array $unserializedEffects Unserialized array string to serialize
*
* @return string
*/
public function serializeEffects(array $unserializedEffects)
{
$effects = json_encode($unserializedEffects);
return $effects;
}
}
<?php
/**********************************************************************************/
/* */
/* Thelia */
/* */
/* Copyright (c) OpenStudio */
/* email : info@thelia.net */
/* web : http://www.thelia.net */
/* */
/* This program is free software; you can redistribute it and/or modify */
/* it under the terms of the GNU General Public License as published by */
/* the Free Software Foundation; either version 3 of the License */
/* */
/* This program is distributed in the hope that it will be useful, */
/* but WITHOUT ANY WARRANTY; without even the implied warranty of */
/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */
/* GNU General Public License for more details. */
/* */
/* You should have received a copy of the GNU General Public License */
/* along with this program. If not, see <http://www.gnu.org/licenses/>. */
/* */
/**********************************************************************************/
namespace Thelia\Model;
use Propel\Runtime\Propel;
use Thelia\Model\Base\Coupon as BaseCoupon;
use Thelia\Model\Exception\InvalidArgumentException;
use Thelia\Model\Map\CouponTableMap;
/**
* Used to provide an effect (mostly a discount)
* at the end of the Customer checkout tunnel
* It will be usable for a Customer only if it matches the Coupon criteria (Rules)
*
* @package Coupon
* @author Guillaume MOREL <gmorel@openstudio.fr>
*
*/
class Coupon extends BaseCoupon
{
use \Thelia\Model\Tools\ModelEventDispatcherTrait;
/**
* Create or Update this Coupon
*
* @param string $code Coupon Code
* @param string $title Coupon title
* @param array $effects Ready to be serialized in JSON effect params
* @param string $type Coupon type
* @param bool $isRemovingPostage Is removing Postage
* @param string $shortDescription Coupon short description
* @param string $description Coupon description
* @param boolean $isEnabled Enable/Disable
* @param \DateTime $expirationDate Coupon expiration date
* @param boolean $isAvailableOnSpecialOffers Is available on special offers
* @param boolean $isCumulative Is cumulative
* @param int $maxUsage Coupon quantity
* @param string $defaultSerializedRule Serialized default rule added if none found
* @param string $locale Coupon Language code ISO (ex: fr_FR)
*
* @throws \Exception
*/
public function createOrUpdate($code, $title, array $effects, $type, $isRemovingPostage, $shortDescription, $description, $isEnabled, $expirationDate, $isAvailableOnSpecialOffers, $isCumulative, $maxUsage, $defaultSerializedRule, $locale = null)
{
$this
->setCode($code)
->setType($type)
->setEffects($effects)
->setIsRemovingPostage($isRemovingPostage)
->setIsEnabled($isEnabled)
->setExpirationDate($expirationDate)
->setIsAvailableOnSpecialOffers($isAvailableOnSpecialOffers)
->setIsCumulative($isCumulative)
->setMaxUsage($maxUsage)
->setLocale($locale)
->setTitle($title)
->setShortDescription($shortDescription)
->setDescription($description);
// If no rule given, set default rule
if (null === $this->getSerializedConditions()) {
$this->setSerializedConditions($defaultSerializedRule);
}
$this->save();
}
/**
* Create or Update this coupon condition
*
* @param string $serializableConditions Serialized conditions ready to be saved
* @param string $locale Coupon Language code ISO (ex: fr_FR)
*
* @throws \Exception
*/
public function createOrUpdateConditions($serializableConditions, $locale)
{
$this->setSerializedConditions($serializableConditions);
// Set object language (i18n)
if (!is_null($locale)) {
$this->setLocale($locale);
}
$this->save();
}
/**
* Set Coupon amount
*
* @param float $amount Amount deduced from the Cart
*
* @return $this
*/
public function setAmount($amount)
{
$effects = $this->unserializeEffects($this->getSerializedEffects());
$effects['amount'] = floatval($amount);
$this->setEffects($effects);
return $this;
}
/**
* Get the amount removed from the coupon to the cart
*
* @return float
*/
public function getAmount()
{
$amount = $this->getEffects()['amount'];
return floatval($amount);
}
/**
* Get the Coupon effects
*
* @return array
* @throws Exception\InvalidArgumentException
*/
public function getEffects()
{
$effects = $this->unserializeEffects($this->getSerializedEffects());
if (null === $effects['amount']) {
throw new InvalidArgumentException('Missing key \'amount\' in Coupon effect coming from database');
}
return $effects;
}
/**
* Get the Coupon effects
*
* @param array $effects Effect ready to be serialized
* Needs at least the key 'amount'
* with the amount removed from the cart
*
* @throws Exception\InvalidArgumentException
* @return $this
*/
public function setEffects(array $effects)
{
if (null === $effects['amount']) {
throw new InvalidArgumentException('Missing key \'amount\' in Coupon effect ready to be serialized array');
}
$this->setSerializedEffects($this->serializeEffects($effects));
return $this;
}
/**
* Return unserialized effects
*
* @param string $serializedEffects Serialized effect string to unserialize
*
* @return array
*/
public function unserializeEffects($serializedEffects)
{
$effects = json_decode($serializedEffects, true);
return $effects;
}
/**
* Return serialized effects
*
* @param array $unserializedEffects Unserialized array string to serialize
*
* @return string
*/
public function serializeEffects(array $unserializedEffects)
{
$effects = json_encode($unserializedEffects);
return $effects;
}
}

View File

@@ -44,35 +44,35 @@ class OperatorsTest extends \PHPUnit_Framework_TestCase
->will($this->returnCallback((array($this, 'callbackI18n'))));
$actual = Operators::getI18n($stubTranslator, Operators::INFERIOR);
$expected = 'inferior to';
$expected = 'Less than';
$this->assertEquals($expected, $actual);
$actual = Operators::getI18n($stubTranslator, Operators::INFERIOR_OR_EQUAL);
$expected = 'inferior or equal to';
$expected = 'Less than or equals';
$this->assertEquals($expected, $actual);
$actual = Operators::getI18n($stubTranslator, Operators::EQUAL);
$expected = 'equal to';
$expected = 'Equals';
$this->assertEquals($expected, $actual);
$actual = Operators::getI18n($stubTranslator, Operators::SUPERIOR_OR_EQUAL);
$expected = 'superior or equal to';
$expected = 'Greater than or equals';
$this->assertEquals($expected, $actual);
$actual = Operators::getI18n($stubTranslator, Operators::SUPERIOR);
$expected = 'superior to';
$expected = 'Greater than';
$this->assertEquals($expected, $actual);
$actual = Operators::getI18n($stubTranslator, Operators::DIFFERENT);
$expected = 'different from';
$expected = 'Not equals';
$this->assertEquals($expected, $actual);
$actual = Operators::getI18n($stubTranslator, Operators::IN);
$expected = 'in';
$expected = 'In';
$this->assertEquals($expected, $actual);
$actual = Operators::getI18n($stubTranslator, Operators::OUT);
$expected = 'not in';
$expected = 'Not in';
$this->assertEquals($expected, $actual);
$actual = Operators::getI18n($stubTranslator, 'unexpected operator');