mirror of
https://github.com/Sylius/Sylius.git
synced 2026-07-14 17:10:53 +00:00
Switch currency
This commit is contained in:
parent
cc32af55b6
commit
21472d7e00
14 changed files with 169 additions and 15 deletions
38
features/frontend/currencies.feature
Normal file
38
features/frontend/currencies.feature
Normal file
|
|
@ -0,0 +1,38 @@
|
|||
Feature: Currencies
|
||||
In order to buy products paying in different currencies
|
||||
As a visitor or as a logged in user
|
||||
I need to be able to switch between multiple currencies
|
||||
|
||||
Background:
|
||||
Given there are following taxonomies defined:
|
||||
| name |
|
||||
| Category |
|
||||
And taxonomy "Category" has following taxons:
|
||||
| Clothing > PHP T-Shirts |
|
||||
And the following products exist:
|
||||
| name | price | taxons |
|
||||
| PHP Top | 5.99 | PHP T-Shirts |
|
||||
And there are following exchange rates:
|
||||
| currency | rate |
|
||||
| EUR | 1 |
|
||||
| USD | 0.76496 |
|
||||
| GBP | 1.13986 |
|
||||
|
||||
Scenario: Switching currency as visitor
|
||||
Given I am on the store homepage
|
||||
When I follow "$"
|
||||
Then I should see product prices in "$"
|
||||
When I follow "€"
|
||||
Then I should see product prices in "€"
|
||||
When I follow "£"
|
||||
Then I should see product prices in "£"
|
||||
|
||||
Scenario: Switching currency as logged in user
|
||||
Given I am logged in user
|
||||
And I am on the store homepage
|
||||
When I follow "$"
|
||||
Then I should see product prices in "$"
|
||||
When I follow "€"
|
||||
Then I should see product prices in "€"
|
||||
When I follow "£"
|
||||
Then I should see product prices in "£"
|
||||
|
|
@ -14,25 +14,46 @@ namespace Sylius\Bundle\CoreBundle\Context;
|
|||
use Sylius\Bundle\MoneyBundle\Context\CurrencyContext as BaseCurrencyContext;
|
||||
use Symfony\Component\Security\Core\SecurityContextInterface;
|
||||
use Symfony\Component\HttpFoundation\Session\SessionInterface;
|
||||
use Doctrine\Common\Persistence\ObjectManager;
|
||||
|
||||
class CurrencyContext extends BaseCurrencyContext
|
||||
{
|
||||
protected $securityContext;
|
||||
protected $userManager;
|
||||
|
||||
public function __construct(SecurityContextInterface $securityContext, SessionInterface $session, $defaultCurrency)
|
||||
public function __construct(SecurityContextInterface $securityContext, SessionInterface $session, ObjectManager $userManager, $defaultCurrency)
|
||||
{
|
||||
$this->securityContext = $securityContext;
|
||||
$this->userManager = $userManager;
|
||||
|
||||
parent::__construct($session, $defaultCurrency);
|
||||
}
|
||||
|
||||
public function getCurrency()
|
||||
{
|
||||
if ((null !== $token = $this->securityContext->getToken()) && is_object($user = $token->getUser())) {
|
||||
return $user->getCurrency();
|
||||
if (null === $user = $this->getUser()) {
|
||||
return parent::getCurrency();
|
||||
}
|
||||
|
||||
return $user->getCurrency();
|
||||
}
|
||||
|
||||
return parent::getCurrency();
|
||||
public function setCurrency($currency)
|
||||
{
|
||||
if (null === $user = $this->getUser()) {
|
||||
return parent::setCurrency($currency);
|
||||
}
|
||||
|
||||
$user->setCurrency($currency);
|
||||
|
||||
$this->userManager->persist($user);
|
||||
$this->userManager->flush();
|
||||
}
|
||||
|
||||
protected function getUser()
|
||||
{
|
||||
if ((null !== $token = $this->securityContext->getToken()) && is_object($user = $token->getUser())) {
|
||||
return $user;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -12,7 +12,6 @@
|
|||
namespace Sylius\Bundle\CoreBundle\DataFixtures\ORM;
|
||||
|
||||
use Doctrine\Common\Persistence\ObjectManager;
|
||||
use Symfony\Component\Intl\Intl;
|
||||
|
||||
/**
|
||||
* Default exchange rate fixtures.
|
||||
|
|
@ -28,10 +27,10 @@ class LoadExchangeRatesData extends DataFixture
|
|||
{
|
||||
$exchangeRateRepository = $this->getExchangeRateRepository();
|
||||
|
||||
foreach (Intl::getCurrencyBundle()->getCurrencyNames() as $name => $iso) {
|
||||
foreach (array('EUR', 'USD', 'GBP') as $currency) {
|
||||
$exchangeRate = $exchangeRateRepository->createNew();
|
||||
|
||||
$exchangeRate->setCurrency($name);
|
||||
$exchangeRate->setCurrency($currency);
|
||||
$exchangeRate->setRate($this->faker->randomFloat(null, 0, 100));
|
||||
|
||||
$manager->persist($exchangeRate);
|
||||
|
|
|
|||
|
|
@ -220,6 +220,7 @@
|
|||
<service id="sylius.currency_context" class="%sylius.currency_context.class%">
|
||||
<argument type="service" id="security.context" />
|
||||
<argument type="service" id="session" />
|
||||
<argument type="service" id="sylius.manager.user" />
|
||||
<argument>%sylius.money.currency%</argument>
|
||||
</service>
|
||||
</services>
|
||||
|
|
|
|||
|
|
@ -18,10 +18,11 @@ class CurrencyContext extends ObjectBehavior
|
|||
/**
|
||||
* @param Symfony\Component\Security\Core\SecurityContextInterface $securityContext
|
||||
* @param Symfony\Component\HttpFoundation\Session\SessionInterface $session
|
||||
* @param use Doctrine\Common\Persistence\ObjectManager $userManager
|
||||
*/
|
||||
function let($securityContext, $session)
|
||||
function let($securityContext, $session, $userManager)
|
||||
{
|
||||
$this->beConstructedWith($securityContext, $session, 'EUR');
|
||||
$this->beConstructedWith($securityContext, $session, $userManager, 'EUR');
|
||||
}
|
||||
|
||||
function it_is_initializable()
|
||||
|
|
@ -58,4 +59,29 @@ class CurrencyContext extends ObjectBehavior
|
|||
|
||||
$this->getCurrency()->shouldReturn('PLN');
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Symfony\Component\Security\Core\Authentication\Token\TokenInterface $token
|
||||
*/
|
||||
function it_sets_currency_to_session_if_there_is_no_user($token, $securityContext, $session)
|
||||
{
|
||||
$securityContext->getToken()->shouldBeCalled()->willReturn($token);
|
||||
$token->getUser()->shouldBeCalled()->willReturn(null);
|
||||
$session->set('currency', 'PLN')->shouldBeCalled();
|
||||
|
||||
$this->setCurrency('PLN');
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Sylius\Bundle\CoreBundle\Entity\User $user
|
||||
* @param Symfony\Component\Security\Core\Authentication\Token\TokenInterface $token
|
||||
*/
|
||||
function it_sets_currency_to_user_if_authenticated($user, $token, $securityContext)
|
||||
{
|
||||
$securityContext->getToken()->shouldBeCalled()->willReturn($token);
|
||||
$token->getUser()->shouldBeCalled()->willReturn($user);
|
||||
$user->setCurrency('PLN')->shouldBeCalled();
|
||||
|
||||
$this->setCurrency('PLN');
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -156,6 +156,7 @@ class DataContext extends BehatContext implements KernelAwareInterface
|
|||
$user->setEmail($email);
|
||||
$user->setEnabled('yes' === $enabled);
|
||||
$user->setPlainPassword($password);
|
||||
$user->setCurrency('EUR');
|
||||
|
||||
if (null !== $address) {
|
||||
$user->setShippingAddress($this->createAddress($address));
|
||||
|
|
|
|||
|
|
@ -467,6 +467,14 @@ class WebUser extends MinkContext implements KernelAwareInterface
|
|||
));
|
||||
}
|
||||
|
||||
/**
|
||||
* @Then /^I should see product prices in "([^"]*)"$/
|
||||
*/
|
||||
public function iShouldSeeProductPricesIn($currency)
|
||||
{
|
||||
$this->assertSession()->elementExists('css', sprintf('span.label:contains("%s")', $currency));
|
||||
}
|
||||
|
||||
/**
|
||||
* @Given /^I leave "([^"]*)" empty$/
|
||||
* @Given /^I leave "([^"]*)" field blank/
|
||||
|
|
|
|||
|
|
@ -20,6 +20,7 @@ use Sylius\Bundle\TaxonomiesBundle\Model\TaxonInterface;
|
|||
use Symfony\Component\HttpFoundation\Request;
|
||||
use Symfony\Component\Security\Core\SecurityContextInterface;
|
||||
use Symfony\Component\Translation\TranslatorInterface;
|
||||
use Symfony\Component\Intl\Intl;
|
||||
|
||||
/**
|
||||
* Frontend menu builder.
|
||||
|
|
@ -28,6 +29,12 @@ use Symfony\Component\Translation\TranslatorInterface;
|
|||
*/
|
||||
class FrontendMenuBuilder extends MenuBuilder
|
||||
{
|
||||
/**
|
||||
* Currency repository.
|
||||
*
|
||||
* @var RepositoryInterface
|
||||
*/
|
||||
protected $exchangeRateRepository;
|
||||
/**
|
||||
* Taxonomy repository.
|
||||
*
|
||||
|
|
@ -62,6 +69,7 @@ class FrontendMenuBuilder extends MenuBuilder
|
|||
FactoryInterface $factory,
|
||||
SecurityContextInterface $securityContext,
|
||||
TranslatorInterface $translator,
|
||||
RepositoryInterface $exchangeRateRepository,
|
||||
RepositoryInterface $taxonomyRepository,
|
||||
CartProviderInterface $cartProvider,
|
||||
SyliusMoneyExtension $moneyExtension
|
||||
|
|
@ -69,6 +77,7 @@ class FrontendMenuBuilder extends MenuBuilder
|
|||
{
|
||||
parent::__construct($factory, $securityContext, $translator);
|
||||
|
||||
$this->exchangeRateRepository = $exchangeRateRepository;
|
||||
$this->taxonomyRepository = $taxonomyRepository;
|
||||
$this->cartProvider = $cartProvider;
|
||||
$this->moneyExtension = $moneyExtension;
|
||||
|
|
@ -85,7 +94,7 @@ class FrontendMenuBuilder extends MenuBuilder
|
|||
{
|
||||
$menu = $this->factory->createItem('root', array(
|
||||
'childrenAttributes' => array(
|
||||
'class' => 'nav nav-pills pull-right'
|
||||
'class' => 'nav nav-pills'
|
||||
)
|
||||
));
|
||||
|
||||
|
|
@ -96,14 +105,14 @@ class FrontendMenuBuilder extends MenuBuilder
|
|||
$menu->addChild('cart', array(
|
||||
'route' => 'sylius_cart_summary',
|
||||
'linkAttributes' => array('title' => $this->translate('sylius.frontend.menu.main.cart', array(
|
||||
'%items%' => $cart->getTotalItems(),
|
||||
'%total%' => $this->moneyExtension->formatMoney($cart->getTotal())
|
||||
'%items%' => $cart->getTotalItems(),
|
||||
'%total%' => $this->moneyExtension->formatMoney($cart->getTotal())
|
||||
))),
|
||||
'labelAttributes' => array('icon' => 'icon-shopping-cart icon-large')
|
||||
))->setLabel($this->translate('sylius.frontend.menu.main.cart', array(
|
||||
'%items%' => $cart->getTotalItems(),
|
||||
'%total%' => $this->moneyExtension->formatMoney($cart->getTotal())
|
||||
)));
|
||||
'%items%' => $cart->getTotalItems(),
|
||||
'%total%' => $this->moneyExtension->formatMoney($cart->getTotal())
|
||||
)));
|
||||
|
||||
if ($this->securityContext->isGranted('ROLE_USER')) {
|
||||
$menu->addChild('account', array(
|
||||
|
|
@ -140,6 +149,31 @@ class FrontendMenuBuilder extends MenuBuilder
|
|||
return $menu;
|
||||
}
|
||||
|
||||
/**
|
||||
* Builds frontend currency menu.
|
||||
*
|
||||
* @return ItemInterface
|
||||
*/
|
||||
public function createCurrencyMenu()
|
||||
{
|
||||
$menu = $this->factory->createItem('root', array(
|
||||
'childrenAttributes' => array(
|
||||
'class' => 'nav nav-pills'
|
||||
)
|
||||
));
|
||||
|
||||
foreach ($this->exchangeRateRepository->findAll() as $exchangeRate)
|
||||
{
|
||||
$menu->addChild($exchangeRate->getCurrency(), array(
|
||||
'route' => 'sylius_currency_change',
|
||||
'routeParameters' => array('currency' => $exchangeRate->getCurrency()),
|
||||
'linkAttributes' => array('title' => $this->translate('sylius.frontend.menu.currency', array('%currency%' => $exchangeRate->getCurrency()))),
|
||||
))->setLabel(Intl::getCurrencyBundle()->getCurrencySymbol($exchangeRate->getCurrency()));
|
||||
}
|
||||
|
||||
return $menu;
|
||||
}
|
||||
|
||||
/**
|
||||
* Builds frontend taxonomies menu.
|
||||
*
|
||||
|
|
|
|||
|
|
@ -121,3 +121,7 @@ div.footer ul li a {
|
|||
float: none;
|
||||
margin-right: 0;
|
||||
}
|
||||
|
||||
div.currency-menu {
|
||||
margin-right: 50px;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,7 @@
|
|||
# This file is part of the Sylius package.
|
||||
# (c) Paweł Jędrzejewski
|
||||
|
||||
sylius_currency_change:
|
||||
pattern: /change/{currency}
|
||||
defaults:
|
||||
_controller: sylius.controller.currency:changeAction
|
||||
|
|
@ -5,6 +5,10 @@ sylius_homepage:
|
|||
pattern: /
|
||||
defaults: { _controller: sylius.controller.frontend.homepage:mainAction }
|
||||
|
||||
sylius_currency:
|
||||
resource: @SyliusWebBundle/Resources/config/routing/frontend/currency.yml
|
||||
prefix: /currency
|
||||
|
||||
sylius_product:
|
||||
resource: @SyliusWebBundle/Resources/config/routing/frontend/product.yml
|
||||
|
||||
|
|
|
|||
|
|
@ -44,6 +44,7 @@
|
|||
<argument type="service" id="knp_menu.factory" />
|
||||
<argument type="service" id="security.context" />
|
||||
<argument type="service" id="translator" />
|
||||
<argument type="service" id="sylius.repository.exchange_rate" />
|
||||
<argument type="service" id="sylius.repository.taxonomy" />
|
||||
<argument type="service" id="sylius.cart_provider" />
|
||||
<argument type="service" id="sylius.twig.money" />
|
||||
|
|
@ -58,6 +59,9 @@
|
|||
<argument type="service" id="request" />
|
||||
<tag name="knp_menu.menu" alias="sylius.frontend.main" />
|
||||
</service>
|
||||
<service id="sylius.menu.frontend.currency" class="Knp\Menu\MenuItem" factory-service="sylius.menu_builder.frontend" factory-method="createCurrencyMenu">
|
||||
<tag name="knp_menu.menu" alias="sylius.frontend.currency" />
|
||||
</service>
|
||||
<service id="sylius.menu.frontend.taxonomies" class="Knp\Menu\MenuItem" factory-service="sylius.menu_builder.frontend" factory-method="createTaxonomiesMenu" scope="request">
|
||||
<argument type="service" id="request" />
|
||||
<tag name="knp_menu.menu" alias="sylius.frontend.taxonomies" />
|
||||
|
|
|
|||
|
|
@ -230,6 +230,10 @@
|
|||
<source>sylius.frontend.menu.main.administration</source>
|
||||
<target>Administration</target>
|
||||
</trans-unit>
|
||||
<trans-unit id="72a1c20506c99bf710d871e649d73b7a" resname="sylius.frontend.menu.currency">
|
||||
<source>sylius.frontend.menu.currency</source>
|
||||
<target>Show prices in %currency%</target>
|
||||
</trans-unit>
|
||||
<trans-unit id="f3c562d05786e3056e97da27f1fac4d3" resname="sylius.frontend.menu.main.cart">
|
||||
<source>sylius.frontend.menu.main.cart</source>
|
||||
<target>View cart (%items%) %total%</target>
|
||||
|
|
|
|||
|
|
@ -36,6 +36,9 @@
|
|||
<div class="masthead pull-right">
|
||||
{{ knp_menu_render('sylius.frontend.main', {'template': 'SyliusWebBundle:Frontend:menu.html.twig'}) }}
|
||||
</div>
|
||||
<div class="currency-menu masthead pull-right">
|
||||
{{ knp_menu_render('sylius.frontend.currency', {'template': 'SyliusWebBundle:Frontend:menu.html.twig'}) }}
|
||||
</div>
|
||||
<h1 class="logo"><a href="{{ path('sylius_homepage') }}" title="{{ 'sylius.logo'|trans }}"><img src="{{ asset('assets/img/logo.png') }}" alt="{{ 'sylius.logo'|trans }}"><span>{{ 'sylius.logo'|trans }}</span></a></h1>
|
||||
{% endblock %}
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue