From 4fc8682b26b599be2c095fd16b4716fe8db4e7e8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Wojciech=20B=C5=82oszyk?= Date: Thu, 2 Jan 2020 16:25:36 +0100 Subject: [PATCH] Add profile to CustomerBundle --- UPGRADE-3.x.md | 6 ++ composer.json | 2 +- docs/reference/bundles/customer.rst | 13 +++ .../Block/ProfileMenuBlockService.php | 82 ++++++++++++++++ .../Controller/DashboardController.php | 27 ++++++ .../Compiler/GlobalVariablesCompilerPass.php | 30 ++++++ .../DependencyInjection/Configuration.php | 95 +++++++++++++++++++ .../SonataCustomerExtension.php | 13 ++- .../Menu/ProfileMenuBuilder.php | 84 ++++++++++++++++ src/CustomerBundle/Menu/ProfileMenuEvent.php | 38 ++++++++ src/CustomerBundle/Resources/config/block.xml | 7 ++ src/CustomerBundle/Resources/config/menu.xml | 11 +++ .../Resources/config/routing/customer.xml | 3 + src/CustomerBundle/Resources/config/twig.xml | 3 + .../SonataCustomerBundle.en.xliff | 8 ++ .../SonataCustomerBundle.fr.xliff | 8 ++ .../SonataCustomerBundle.ru.xliff | 8 ++ .../Resources/views/Addresses/list.html.twig | 2 +- .../Resources/views/Addresses/new.html.twig | 2 +- .../Resources/views/Profile/action.html.twig | 33 +++++++ .../Profile/action_with_user_menu.html.twig | 43 +++++++++ .../views/Profile/dashboard.html.twig | 47 +++++++++ src/CustomerBundle/SonataCustomerBundle.php | 2 + src/CustomerBundle/Twig/GlobalVariables.php | 35 +++++++ .../Resources/views/Invoice/view.html.twig | 2 +- .../Resources/views/Order/index.html.twig | 2 +- .../Resources/views/Order/view.html.twig | 2 +- .../Controller/CustomerControllerTest.php | 35 +++++++ .../Menu/ProfileMenuBuilderTest.php | 42 ++++++++ 29 files changed, 678 insertions(+), 7 deletions(-) create mode 100644 src/CustomerBundle/Block/ProfileMenuBlockService.php create mode 100644 src/CustomerBundle/Controller/DashboardController.php create mode 100644 src/CustomerBundle/DependencyInjection/Compiler/GlobalVariablesCompilerPass.php create mode 100644 src/CustomerBundle/Menu/ProfileMenuBuilder.php create mode 100644 src/CustomerBundle/Menu/ProfileMenuEvent.php create mode 100644 src/CustomerBundle/Resources/config/menu.xml create mode 100644 src/CustomerBundle/Resources/views/Profile/action.html.twig create mode 100644 src/CustomerBundle/Resources/views/Profile/action_with_user_menu.html.twig create mode 100644 src/CustomerBundle/Resources/views/Profile/dashboard.html.twig create mode 100644 src/CustomerBundle/Twig/GlobalVariables.php create mode 100644 tests/CustomerBundle/Controller/CustomerControllerTest.php create mode 100644 tests/CustomerBundle/Menu/ProfileMenuBuilderTest.php diff --git a/UPGRADE-3.x.md b/UPGRADE-3.x.md index 2798f3a6d..75928a4bb 100644 --- a/UPGRADE-3.x.md +++ b/UPGRADE-3.x.md @@ -4,6 +4,12 @@ UPGRADE 3.x UPGRADE FROM 3.0 to 3.1 ======================= +## Added missing profile part to CustomerBundle + +Profile dependencies are no longer fetched from SonataUserBundle, but you can +use this profile by change configuration (template and menu_builder). + + ## Deprecated not passing dependencies to `Sonata\PaymentBundle\Controller\PaymentController` Dependencies are no longer fetched from the container, so if you manually diff --git a/composer.json b/composer.json index 905abf6c7..2bc92da8d 100644 --- a/composer.json +++ b/composer.json @@ -22,7 +22,7 @@ "knplabs/knp-paginator-bundle": "^2.6", "kriswallsmith/buzz": "^0.15 || 0.16.0", "sonata-project/admin-bundle": "^3.29", - "sonata-project/block-bundle": "^3.8", + "sonata-project/block-bundle": "^3.18.3", "sonata-project/classification-bundle": "^3.3", "sonata-project/comment-bundle": "^3.1", "sonata-project/core-bundle": "^3.15.1", diff --git a/docs/reference/bundles/customer.rst b/docs/reference/bundles/customer.rst index e49f177bc..427ab2198 100644 --- a/docs/reference/bundles/customer.rst +++ b/docs/reference/bundles/customer.rst @@ -24,6 +24,19 @@ The bundle allows you to configure the entity classes; you'll also need to regis .. code-block:: yaml sonata_customer: + profile: + template: 'SonataCustomerBundle:Profile:action.html.twig' # or 'SonataCustomerBundle:Profile:action_with_user_menu.html.twig' + menu_builder: 'sonata.customer.profile.menu_builder.default' + + menu: + - { route: 'sonata_customer_dashboard', label: 'link_list_dashboard', domain: 'SonataCustomerBundle', route_parameters: {}} + - { route: 'sonata_customer_addresses', label: 'link_list_addresses', domain: 'SonataCustomerBundle', route_parameters: {}} + - { route: 'sonata_order_index', label: 'order_list', domain: 'SonataOrderBundle', route_parameters: {}} + + blocks: + - { position: left, type: sonata.order.block.recent_orders, settings: { title: Recent Orders, number: 5, mode: public }} + - { position: right, type: sonata.news.block.recent_posts, settings: { title: Recent Posts, number: 5, mode: public }} + - { position: right, type: sonata.news.block.recent_comments, settings: { title: Recent Comments, number: 5, mode: public }} class: customer: App\Sonata\CustomerBundle\Entity\Customer address: App\Sonata\CustomerBundle\Entity\Address diff --git a/src/CustomerBundle/Block/ProfileMenuBlockService.php b/src/CustomerBundle/Block/ProfileMenuBlockService.php new file mode 100644 index 000000000..33ecf6457 --- /dev/null +++ b/src/CustomerBundle/Block/ProfileMenuBlockService.php @@ -0,0 +1,82 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Sonata\CustomerBundle\Block; + +use Knp\Menu\ItemInterface; +use Knp\Menu\Provider\MenuProviderInterface; +use Sonata\BlockBundle\Block\BlockContextInterface; +use Sonata\BlockBundle\Block\Service\MenuBlockService; +use Symfony\Bundle\FrameworkBundle\Templating\EngineInterface; +use Symfony\Component\OptionsResolver\OptionsResolver; + +/** + * @author Hugo Briand + */ +final class ProfileMenuBlockService extends MenuBlockService +{ + private $menuBuilder; + + /** + * @param object $menuBuilder + */ + public function __construct(string $name, EngineInterface $templating, MenuProviderInterface $menuProvider, $menuBuilder) + { + parent::__construct($name, $templating, $menuProvider, []); + + if (!\is_object($menuBuilder) || !method_exists($menuBuilder, 'createProfileMenu')) { + throw new \InvalidArgumentException( + 'Argument 4 should be object with public function "createProfileMenu(array $itemOptions = [])"' + ); + } + + $this->menuBuilder = $menuBuilder; + } + + public function getName() + { + return 'Ecommerce Profile Menu'; + } + + public function configureSettings(OptionsResolver $resolver) + { + parent::configureSettings($resolver); + + $resolver->setDefaults([ + 'cache_policy' => 'private', + 'menu_template' => 'SonataBlockBundle:Block:block_side_menu_template.html.twig', + ]); + } + + protected function getMenu(BlockContextInterface $blockContext): ItemInterface + { + $settings = $blockContext->getSettings(); + + $menu = parent::getMenu($blockContext); + + if (null === $menu || '' === $menu) { + $menu = $this->menuBuilder->createProfileMenu( + [ + 'childrenAttributes' => ['class' => $settings['menu_class']], + 'attributes' => ['class' => $settings['children_class']], + ] + ); + + if (method_exists($menu, 'setCurrentUri')) { + $menu->setCurrentUri($settings['current_uri']); + } + } + + return $menu; + } +} diff --git a/src/CustomerBundle/Controller/DashboardController.php b/src/CustomerBundle/Controller/DashboardController.php new file mode 100644 index 000000000..4d921bb85 --- /dev/null +++ b/src/CustomerBundle/Controller/DashboardController.php @@ -0,0 +1,27 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Sonata\CustomerBundle\Controller; + +use Symfony\Bundle\FrameworkBundle\Controller\Controller; +use Symfony\Component\HttpFoundation\Response; + +final class DashboardController extends Controller +{ + public function dashboardAction(): Response + { + return $this->render('SonataCustomerBundle:Profile:dashboard.html.twig', [ + 'blocks' => $this->container->getParameter('sonata.customer.profile.blocks'), + ]); + } +} diff --git a/src/CustomerBundle/DependencyInjection/Compiler/GlobalVariablesCompilerPass.php b/src/CustomerBundle/DependencyInjection/Compiler/GlobalVariablesCompilerPass.php new file mode 100644 index 000000000..8705431d8 --- /dev/null +++ b/src/CustomerBundle/DependencyInjection/Compiler/GlobalVariablesCompilerPass.php @@ -0,0 +1,30 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Sonata\CustomerBundle\DependencyInjection\Compiler; + +use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface; +use Symfony\Component\DependencyInjection\ContainerBuilder; +use Symfony\Component\DependencyInjection\Reference; + +/** + * @author Thomas Rabaix + */ +final class GlobalVariablesCompilerPass implements CompilerPassInterface +{ + public function process(ContainerBuilder $container) + { + $container->getDefinition('twig') + ->addMethodCall('addGlobal', ['sonata_customer', new Reference('sonata.customer.twig.global')]); + } +} diff --git a/src/CustomerBundle/DependencyInjection/Configuration.php b/src/CustomerBundle/DependencyInjection/Configuration.php index 41c12e2b3..f8f69ac6f 100644 --- a/src/CustomerBundle/DependencyInjection/Configuration.php +++ b/src/CustomerBundle/DependencyInjection/Configuration.php @@ -30,6 +30,7 @@ public function getConfigTreeBuilder() $node = $treeBuilder->root('sonata_customer'); $this->addModelSection($node); + $this->addProfileSection($node); return $treeBuilder; } @@ -63,4 +64,98 @@ private function addModelSection(ArrayNodeDefinition $node): void ->end() ; } + + private function addProfileSection(ArrayNodeDefinition $node): void + { + $node + ->children() + ->arrayNode('profile') + ->addDefaultsIfNotSet() + ->fixXmlConfig('block') + ->children() + ->scalarNode('template')->defaultValue('SonataCustomerBundle:Profile:action.html.twig')->cannotBeEmpty()->end() + ->scalarNode('menu_builder')->defaultValue('sonata.customer.profile.menu_builder.default')->cannotBeEmpty()->end() + ->arrayNode('blocks') + ->defaultValue($this->getProfileBlocksDefaultValues()) + ->prototype('array') + ->fixXmlConfig('setting') + ->children() + ->scalarNode('type')->cannotBeEmpty()->end() + ->arrayNode('settings') + ->useAttributeAsKey('id') + ->prototype('variable')->defaultValue([])->end() + ->end() + ->scalarNode('position')->defaultValue('right')->end() + ->end() + ->end() + ->end() + ->arrayNode('menu') + ->prototype('array') + ->addDefaultsIfNotSet() + ->cannotBeEmpty() + ->children() + ->scalarNode('route')->cannotBeEmpty()->end() + ->arrayNode('route_parameters') + ->defaultValue([]) + ->prototype('array')->end() + ->end() + ->scalarNode('label')->cannotBeEmpty()->end() + ->scalarNode('domain')->defaultValue('messages')->end() + ->end() + ->end() + ->defaultValue($this->getProfileMenuDefaultValues()) + ->end() + ->end() + ->end() + ->end() + ; + } + + /** + * Returns default values for profile menu (to avoid BC Break). + */ + private function getProfileMenuDefaultValues(): array + { + return [ + [ + 'route' => 'sonata_customer_dashboard', + 'label' => 'link_list_dashboard', + 'domain' => 'SonataCustomerBundle', + 'route_parameters' => [], + ], + [ + 'route' => 'sonata_customer_addresses', + 'label' => 'link_list_addresses', + 'domain' => 'SonataCustomerBundle', + 'route_parameters' => [], + ], + [ + 'route' => 'sonata_order_index', + 'label' => 'order_list', + 'domain' => 'SonataOrderBundle', + 'route_parameters' => [], + ], + ]; + } + + private function getProfileBlocksDefaultValues(): array + { + return [ + [ + 'position' => 'left', + 'type' => 'sonata.order.block.recent_orders', + 'settings' => ['title' => 'Recent Orders', 'number' => 5, 'mode' => 'public'], + ], + [ + 'position' => 'right', + 'type' => 'sonata.news.block.recent_posts', + 'settings' => ['title' => 'Recent Posts', 'number' => 5, 'mode' => 'public'], + ], + [ + 'position' => 'right', + 'type' => 'sonata.news.block.recent_comments', + 'settings' => ['title' => 'Recent Comments', 'number' => 5, 'mode' => 'public'], + ], + ]; + } } diff --git a/src/CustomerBundle/DependencyInjection/SonataCustomerExtension.php b/src/CustomerBundle/DependencyInjection/SonataCustomerExtension.php index a70339cdc..5f80c5c33 100644 --- a/src/CustomerBundle/DependencyInjection/SonataCustomerExtension.php +++ b/src/CustomerBundle/DependencyInjection/SonataCustomerExtension.php @@ -55,8 +55,9 @@ public function load(array $configs, ContainerBuilder $container): void $loader = new XmlFileLoader($container, new FileLocator(__DIR__.'/../Resources/config')); $loader->load('block.xml'); - $loader->load('orm.xml'); $loader->load('form.xml'); + $loader->load('menu.xml'); + $loader->load('orm.xml'); $loader->load('twig.xml'); if (isset($bundles['FOSRestBundle'], $bundles['NelmioApiDocBundle'])) { @@ -69,6 +70,7 @@ public function load(array $configs, ContainerBuilder $container): void $loader->load('admin.xml'); } + $this->configureCustomerProfile($container, $config); $this->registerDoctrineMapping($config); $this->registerParameters($container, $config); } @@ -157,4 +159,13 @@ public function registerDoctrineMapping(array $config): void 'orphanRemoval' => false, ]); } + + private function configureCustomerProfile(ContainerBuilder $container, array $config) + { + $container->setParameter('sonata.customer.profile.blocks', $config['profile']['blocks']); + $container->setParameter('sonata.customer.profile.template', $config['profile']['template']); + + $container->setAlias('sonata.customer.profile.menu_builder', $config['profile']['menu_builder']); + $container->getDefinition('sonata.customer.profile.menu_builder.default')->replaceArgument(2, $config['profile']['menu']); + } } diff --git a/src/CustomerBundle/Menu/ProfileMenuBuilder.php b/src/CustomerBundle/Menu/ProfileMenuBuilder.php new file mode 100644 index 000000000..de8888e17 --- /dev/null +++ b/src/CustomerBundle/Menu/ProfileMenuBuilder.php @@ -0,0 +1,84 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Sonata\CustomerBundle\Menu; + +use Knp\Menu\FactoryInterface; +use Knp\Menu\ItemInterface; +use Symfony\Component\EventDispatcher\EventDispatcherInterface; +use Symfony\Component\Translation\TranslatorInterface; + +/** + * @author Hugo Briand + */ +final class ProfileMenuBuilder +{ + /** + * @var FactoryInterface + */ + private $factory; + + /** + * @var array + */ + private $routes; + + /** + * @var TranslatorInterface + */ + private $translator; + + /** + * @var EventDispatcherInterface + */ + private $eventDispatcher; + + /** + * @param array $routes Routes to add to the menu (format: [['label' => ..., 'route' => ...]]) + */ + public function __construct(FactoryInterface $factory, TranslatorInterface $translator, array $routes, EventDispatcherInterface $eventDispatcher) + { + $this->factory = $factory; + $this->translator = $translator; + $this->routes = $routes; + $this->eventDispatcher = $eventDispatcher; + } + + /** + * @param array $itemOptions The options given to the created menuItem + */ + public function createProfileMenu(array $itemOptions = []): ItemInterface + { + $menu = $this->factory->createItem('customer_profile', $itemOptions); + + $this->buildProfileMenu($menu, $itemOptions); + + return $menu; + } + + /** + * @param ItemInterface $menu The item to fill with $routes + */ + public function buildProfileMenu(ItemInterface $menu, array $itemOptions = []) + { + foreach ($this->routes as $route) { + $menu->addChild( + $this->translator->trans($route['label'], [], $route['domain']), + array_merge($itemOptions, ['route' => $route['route'], 'routeParameters' => $route['route_parameters']]) + ); + } + + $event = new ProfileMenuEvent($menu); + $this->eventDispatcher->dispatch('sonata.customer.profile.configure_menu', $event); + } +} diff --git a/src/CustomerBundle/Menu/ProfileMenuEvent.php b/src/CustomerBundle/Menu/ProfileMenuEvent.php new file mode 100644 index 000000000..c5e2055e1 --- /dev/null +++ b/src/CustomerBundle/Menu/ProfileMenuEvent.php @@ -0,0 +1,38 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Sonata\CustomerBundle\Menu; + +use Knp\Menu\ItemInterface; +use Symfony\Component\EventDispatcher\Event; + +/** + * @author Hugo Briand + */ +final class ProfileMenuEvent extends Event +{ + /** + * @var ItemInterface + */ + private $menu; + + public function __construct(ItemInterface $menu) + { + $this->menu = $menu; + } + + public function getMenu(): ItemInterface + { + return $this->menu; + } +} diff --git a/src/CustomerBundle/Resources/config/block.xml b/src/CustomerBundle/Resources/config/block.xml index 4b59b168f..01e1bcb5c 100644 --- a/src/CustomerBundle/Resources/config/block.xml +++ b/src/CustomerBundle/Resources/config/block.xml @@ -8,5 +8,12 @@ + + + sonata.customer.block.profile_menu + + + + diff --git a/src/CustomerBundle/Resources/config/menu.xml b/src/CustomerBundle/Resources/config/menu.xml new file mode 100644 index 000000000..d72b1c98f --- /dev/null +++ b/src/CustomerBundle/Resources/config/menu.xml @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/src/CustomerBundle/Resources/config/routing/customer.xml b/src/CustomerBundle/Resources/config/routing/customer.xml index 213efec2f..46f518ac0 100644 --- a/src/CustomerBundle/Resources/config/routing/customer.xml +++ b/src/CustomerBundle/Resources/config/routing/customer.xml @@ -1,5 +1,8 @@ + + SonataCustomerBundle:Dashboard:dashboard + SonataCustomerBundle:Customer:addresses diff --git a/src/CustomerBundle/Resources/config/twig.xml b/src/CustomerBundle/Resources/config/twig.xml index 8952e3711..796c83d51 100644 --- a/src/CustomerBundle/Resources/config/twig.xml +++ b/src/CustomerBundle/Resources/config/twig.xml @@ -5,5 +5,8 @@ + + %sonata.customer.profile.template% + diff --git a/src/CustomerBundle/Resources/translations/SonataCustomerBundle.en.xliff b/src/CustomerBundle/Resources/translations/SonataCustomerBundle.en.xliff index 295d784fa..8374c9494 100644 --- a/src/CustomerBundle/Resources/translations/SonataCustomerBundle.en.xliff +++ b/src/CustomerBundle/Resources/translations/SonataCustomerBundle.en.xliff @@ -3,6 +3,10 @@ + + sonata_profile_title + Dashboard + customer Customer @@ -249,6 +253,10 @@ link_list_addresses Addresses + + link_list_dashboard + Dashboard + diff --git a/src/CustomerBundle/Resources/translations/SonataCustomerBundle.fr.xliff b/src/CustomerBundle/Resources/translations/SonataCustomerBundle.fr.xliff index 36dca1e5a..371dc7ac1 100644 --- a/src/CustomerBundle/Resources/translations/SonataCustomerBundle.fr.xliff +++ b/src/CustomerBundle/Resources/translations/SonataCustomerBundle.fr.xliff @@ -3,6 +3,10 @@ + + sonata_profile_title + Mon tableau de bord + customer Client @@ -249,6 +253,10 @@ link_list_addresses Adresses + + link_list_dashboard + Mon tableau de bord + diff --git a/src/CustomerBundle/Resources/translations/SonataCustomerBundle.ru.xliff b/src/CustomerBundle/Resources/translations/SonataCustomerBundle.ru.xliff index c565c838e..60800a42e 100644 --- a/src/CustomerBundle/Resources/translations/SonataCustomerBundle.ru.xliff +++ b/src/CustomerBundle/Resources/translations/SonataCustomerBundle.ru.xliff @@ -3,6 +3,10 @@ + + sonata_profile_title + Профиль + customer Покупатель @@ -249,6 +253,10 @@ link_list_addresses Адреса + + link_list_dashboard + Профиль + diff --git a/src/CustomerBundle/Resources/views/Addresses/list.html.twig b/src/CustomerBundle/Resources/views/Addresses/list.html.twig index b64699350..22dbf87a6 100644 --- a/src/CustomerBundle/Resources/views/Addresses/list.html.twig +++ b/src/CustomerBundle/Resources/views/Addresses/list.html.twig @@ -1,4 +1,4 @@ -{% extends "@SonataUser/Profile/action.html.twig" %} +{% extends sonata_customer.profileTemplate %} {% block sonata_profile_title %}{% trans from 'SonataCustomerBundle' %}address_list{% endtrans %}{% endblock %} diff --git a/src/CustomerBundle/Resources/views/Addresses/new.html.twig b/src/CustomerBundle/Resources/views/Addresses/new.html.twig index b64a7f33a..a6cc02474 100644 --- a/src/CustomerBundle/Resources/views/Addresses/new.html.twig +++ b/src/CustomerBundle/Resources/views/Addresses/new.html.twig @@ -8,7 +8,7 @@ For the full copyright and license information, please view the LICENSE file that was distributed with this source code. #} -{% extends "@SonataUser/Profile/action.html.twig" %} +{% extends sonata_customer.profileTemplate %} {% block sonata_profile_title %}{% trans from 'SonataCustomerBundle' %}address_new{% endtrans %}{% endblock %} diff --git a/src/CustomerBundle/Resources/views/Profile/action.html.twig b/src/CustomerBundle/Resources/views/Profile/action.html.twig new file mode 100644 index 000000000..f3bddec6a --- /dev/null +++ b/src/CustomerBundle/Resources/views/Profile/action.html.twig @@ -0,0 +1,33 @@ +{# +This file is part of the Sonata package. +(c) Thomas Rabaix +For the full copyright and license information, please view the LICENSE +file that was distributed with this source code. +#} + +{% block sonata_page_breadcrumb %} + {% if breadcrumb_context is not defined %} + {% set breadcrumb_context = 'user_index' %} + {% endif %} +
+ {{ sonata_block_render_event('breadcrumb', { 'context': breadcrumb_context, 'current_uri': app.request.requestUri }) }} +
+{% endblock %} + +

{% block sonata_profile_title %}{% trans from 'SonataCustomerBundle' %}sonata_profile_title{% endtrans %}{% endblock %}

+ +
+ +
+ {% block sonata_profile_menu %} + {{ sonata_block_render({'type': 'sonata.customer.block.profile_menu'}, {'current_uri': app.request.requestUri}) }} + {% endblock %} +
+ +
+ {% include 'SonataCoreBundle:FlashMessage:render.html.twig' %} + + {% block sonata_profile_content '' %} +
+ +
diff --git a/src/CustomerBundle/Resources/views/Profile/action_with_user_menu.html.twig b/src/CustomerBundle/Resources/views/Profile/action_with_user_menu.html.twig new file mode 100644 index 000000000..80b07d342 --- /dev/null +++ b/src/CustomerBundle/Resources/views/Profile/action_with_user_menu.html.twig @@ -0,0 +1,43 @@ +{# +This file is part of the Sonata package. +(c) Thomas Rabaix +For the full copyright and license information, please view the LICENSE +file that was distributed with this source code. +#} + +{% block sonata_page_breadcrumb %} + {% if breadcrumb_context is not defined %} + {% set breadcrumb_context = 'user_index' %} + {% endif %} +
+ {{ sonata_block_render_event('breadcrumb', { 'context': breadcrumb_context, 'current_uri': app.request.requestUri }) }} +
+{% endblock %} + +

{% block sonata_profile_title %}{% trans from 'SonataCustomerBundle' %}sonata_profile_title{% endtrans %}{% endblock %}

+ +
+ +
+ {% block sonata_profile_menu %} + + {% block sonata_customer_profile_menu %} +

{% trans from 'SonataCustomerBundle' %}customer{% endtrans %}

+ {{ sonata_block_render({'type': 'sonata.customer.block.profile_menu'}, {'current_uri': app.request.requestUri}) }} + {% endblock %} + + {% block sonata_user_profile_menu %} +

{% trans from 'SonataUserBundle' %}show.label_username{% endtrans %}

+ {{ sonata_block_render({'type': 'sonata.user.block.profile_menu'}, {'current_uri': app.request.requestUri}) }} + {% endblock %} + + {% endblock %} +
+ +
+ {% include 'SonataCoreBundle:FlashMessage:render.html.twig' %} + + {% block sonata_profile_content '' %} +
+ +
diff --git a/src/CustomerBundle/Resources/views/Profile/dashboard.html.twig b/src/CustomerBundle/Resources/views/Profile/dashboard.html.twig new file mode 100644 index 000000000..79b856bc0 --- /dev/null +++ b/src/CustomerBundle/Resources/views/Profile/dashboard.html.twig @@ -0,0 +1,47 @@ +{# +This file is part of the Sonata package. +(c) Thomas Rabaix +For the full copyright and license information, please view the LICENSE +file that was distributed with this source code. +#} + +{% extends sonata_customer.profileTemplate %} + +{% block sonata_profile_content %} + {% sonata_template_box 'This is the shop profile template. Feel free to override it.' %} + +
+ {% set has_center = false %} + {% for block in blocks %} + {% if block.position == 'center' %} + {% set has_center = true %} + {% endif %} + {% endfor %} + +
+ {% for block in blocks %} + {% if block.position == 'left' %} + {{ sonata_block_render({ 'type': block.type, 'settings': block.settings}) }} + {% endif %} + {% endfor %} +
+ + {% if has_center %} +
+ {% for block in blocks %} + {% if block.position == 'center' %} + {{ sonata_block_render({ 'type': block.type, 'settings': block.settings}) }} + {% endif %} + {% endfor %} +
+ {% endif %} + +
+ {% for block in blocks %} + {% if block.position == 'right' %} + {{ sonata_block_render({ 'type': block.type, 'settings': block.settings}) }} + {% endif %} + {% endfor %} +
+
+{% endblock %} diff --git a/src/CustomerBundle/SonataCustomerBundle.php b/src/CustomerBundle/SonataCustomerBundle.php index a341d4013..a63bd41ce 100644 --- a/src/CustomerBundle/SonataCustomerBundle.php +++ b/src/CustomerBundle/SonataCustomerBundle.php @@ -14,6 +14,7 @@ namespace Sonata\CustomerBundle; use Sonata\CoreBundle\Form\FormHelper; +use Sonata\CustomerBundle\DependencyInjection\Compiler\GlobalVariablesCompilerPass; use Sonata\CustomerBundle\Form\Type\AddressType; use Sonata\CustomerBundle\Form\Type\AddressTypeType; use Sonata\CustomerBundle\Form\Type\ApiAddressType; @@ -25,6 +26,7 @@ class SonataCustomerBundle extends Bundle { public function build(ContainerBuilder $container): void { + $container->addCompilerPass(new GlobalVariablesCompilerPass()); $this->registerFormMapping(); } diff --git a/src/CustomerBundle/Twig/GlobalVariables.php b/src/CustomerBundle/Twig/GlobalVariables.php new file mode 100644 index 000000000..1cd598f9c --- /dev/null +++ b/src/CustomerBundle/Twig/GlobalVariables.php @@ -0,0 +1,35 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Sonata\CustomerBundle\Twig; + +/** + * @author Thomas Rabaix + */ +final class GlobalVariables +{ + /** + * @var string + */ + protected $profileTemplate; + + public function __construct($profileTemplate) + { + $this->profileTemplate = $profileTemplate; + } + + public function getProfileTemplate(): string + { + return $this->profileTemplate; + } +} diff --git a/src/InvoiceBundle/Resources/views/Invoice/view.html.twig b/src/InvoiceBundle/Resources/views/Invoice/view.html.twig index a2f5f5915..903227bad 100644 --- a/src/InvoiceBundle/Resources/views/Invoice/view.html.twig +++ b/src/InvoiceBundle/Resources/views/Invoice/view.html.twig @@ -9,7 +9,7 @@ file that was distributed with this source code. #} -{% extends "@SonataUser/Profile/action.html.twig" %} +{% extends sonata_customer.profileTemplate %} {% block sonata_profile_title %}{% trans from 'SonataInvoiceBundle' %}sonata.invoice.title_invoice{% endtrans %} - {{ invoice.reference }}{% endblock %} diff --git a/src/OrderBundle/Resources/views/Order/index.html.twig b/src/OrderBundle/Resources/views/Order/index.html.twig index fbfd2b723..b7b9de607 100644 --- a/src/OrderBundle/Resources/views/Order/index.html.twig +++ b/src/OrderBundle/Resources/views/Order/index.html.twig @@ -9,7 +9,7 @@ file that was distributed with this source code. #} -{% extends "@SonataUser/Profile/action.html.twig" %} +{% extends sonata_customer.profileTemplate %} {% block sonata_profile_title %}{% trans from 'SonataOrderBundle' %}order_list{% endtrans %}{% endblock %} diff --git a/src/OrderBundle/Resources/views/Order/view.html.twig b/src/OrderBundle/Resources/views/Order/view.html.twig index 67372c327..874391f79 100644 --- a/src/OrderBundle/Resources/views/Order/view.html.twig +++ b/src/OrderBundle/Resources/views/Order/view.html.twig @@ -9,7 +9,7 @@ file that was distributed with this source code. #} -{% extends "@SonataUser/Profile/action.html.twig" %} +{% extends sonata_customer.profileTemplate %} {% block sonata_profile_title %}{% trans from 'SonataOrderBundle' %}sonata.order.title_order{% endtrans %} - {{ order.reference }}{% endblock %} diff --git a/tests/CustomerBundle/Controller/CustomerControllerTest.php b/tests/CustomerBundle/Controller/CustomerControllerTest.php new file mode 100644 index 000000000..ac9704225 --- /dev/null +++ b/tests/CustomerBundle/Controller/CustomerControllerTest.php @@ -0,0 +1,35 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Sonata\CustomerBundle\Tests\Controller; + +use PHPUnit\Framework\TestCase; +use Sonata\CustomerBundle\Controller\CustomerController; + +class CustomerControllerTest extends TestCase +{ + /** + * @var CustomerController + */ + private $controller; + + protected function setUp() + { + $this->controller = new CustomerController(); + } + + public function testItIsInstantiable() + { + $this->assertNotNull($this->controller); + } +} diff --git a/tests/CustomerBundle/Menu/ProfileMenuBuilderTest.php b/tests/CustomerBundle/Menu/ProfileMenuBuilderTest.php new file mode 100644 index 000000000..bb398e70a --- /dev/null +++ b/tests/CustomerBundle/Menu/ProfileMenuBuilderTest.php @@ -0,0 +1,42 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Sonata\CustomerBundle\Tests\Menu; + +use PHPUnit\Framework\TestCase; +use Sonata\CustomerBundle\Menu\ProfileMenuBuilder; + +/** + * @author Hugo Briand + */ +final class ProfileMenuBuilderTest extends TestCase +{ + public function testCreateProfileMenu() + { + $menu = $this->createMock('Knp\Menu\ItemInterface'); + $factory = $this->createMock('Knp\Menu\FactoryInterface'); + + $factory->expects($this->once()) + ->method('createItem') + ->willReturn($menu); + + $translator = $this->createMock('Symfony\Component\Translation\TranslatorInterface'); + $eventDispatcher = $this->createMock('Symfony\Component\EventDispatcher\EventDispatcherInterface'); + + $builder = new ProfileMenuBuilder($factory, $translator, [], $eventDispatcher); + + $genMenu = $builder->createProfileMenu(); + + $this->assertInstanceOf('Knp\Menu\ItemInterface', $genMenu); + } +}