Skip to content
This repository has been archived by the owner on Jul 22, 2022. It is now read-only.

Commit

Permalink
Add ProfileBundle
Browse files Browse the repository at this point in the history
  • Loading branch information
wbloszyk committed Dec 23, 2019
1 parent 43a2ba4 commit 42feffa
Show file tree
Hide file tree
Showing 30 changed files with 942 additions and 8 deletions.
5 changes: 5 additions & 0 deletions UPGRADE-3.x.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,11 @@ UPGRADE 3.x
UPGRADE FROM 3.0 to 3.1
=======================

## Added missing profile part by add ProfileBundle

Some part of ecommerce used SonataUserBundle profile part. SonataUserBundle drop profile
part on v4.0. To keep functionality and place to add new feature ProfileBundle was added.

## Deprecated not passing dependencies to `Sonata\PaymentBundle\Controller\PaymentController`

Dependencies are no longer fetched from the container, so if you manually
Expand Down
6 changes: 4 additions & 2 deletions composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,8 @@
"Sonata\\OrderBundle\\": "src/OrderBundle",
"Sonata\\PaymentBundle\\": "src/PaymentBundle",
"Sonata\\PriceBundle\\": "src/PriceBundle",
"Sonata\\ProductBundle\\": "src/ProductBundle"
"Sonata\\ProductBundle\\": "src/ProductBundle",
"Sonata\\ProfileBundle\\": "src/ProfileBundle"
}
},
"autoload-dev": {
Expand All @@ -103,7 +104,8 @@
"Sonata\\OrderBundle\\Tests\\": "tests/OrderBundle",
"Sonata\\PaymentBundle\\Tests\\": "tests/PaymentBundle",
"Sonata\\PriceBundle\\Tests\\": "tests/PriceBundle",
"Sonata\\ProductBundle\\Tests\\": "tests/ProductBundle"
"Sonata\\ProductBundle\\Tests\\": "tests/ProductBundle",
"Sonata\\ProfileBundle\\Tests\\": "tests/ProfileBundle"
}
}
}
3 changes: 2 additions & 1 deletion docs/reference/bundles/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -14,4 +14,5 @@ Here are the various bundles composing Sonata e-commerce:
delivery
order
Payment <payment/index>
invoice
invoice
profile
51 changes: 51 additions & 0 deletions docs/reference/bundles/profile.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
.. index::
single: Profile

=======
Profile
=======

Architecture
============

For more information about our position regarding *product* architecture, you can read: :doc:`../architecture/product`.

FOSUSerBundle / SonataUserBundle integration
============================================

To enhance your project integrations with third parties bundles, the ``SonataProfileBundle`` has extendable menu and templates.

You can easily add your user profile to the shop profile by extending menu (exemple below) and ``@SonataProfile/action.html.twig`` template.

Configuration
=============

The bundle allows you to configure the menu and the dashboard blocks.

.. code-block:: yaml
sonata_profile:
override_sonata_user_bundle_profile: false
template: 'SonataProfileBundle::action.html.twig'
dashboard:
blocks:
- { position: left, type: sonata.block.service.text, settings: { content: "<h2>Welcome!</h2> <p>This is a sample shop profile dashboard, feel free to override it in the configuration! Want to make this text dynamic? For instance display the user's name? Create a dedicated block and edit the configuration!</p>"} }
- { position: left, type: sonata.order.block.recent_orders, settings: { title: Recent Orders, number: 5, mode: public }}
#- { position: right, type: sonata.timeline.block.timeline, settings: { max_per_page: 15 }}
- { 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 }}
menu:
- { route: 'sonata_profile_dashboard', label: 'Dashboard', domain: 'SonataProfileBundle'}
# You can add user profile here
#- { route: 'fos_user_profile_edit', label: 'link_edit_profile', domain: 'SonataUserBundle'}
#- { route: 'fos_user_change_password', label: 'title_user_edit_password', domain: 'SonataUserBundle'}
- { route: 'sonata_customer_addresses', label: 'link_list_addresses', domain: 'SonataCustomerBundle'}
- { route: 'sonata_order_index', label: 'order_list', domain: 'SonataOrderBundle'}
Blocks
======

``SonataProfileBundle`` comes with some blocks services:

* ``AccountBlockService``: display the logged in user.
* ``ProfileMenuBlickService``: display the menu added to the bundle configuration.
19 changes: 19 additions & 0 deletions docs/reference/installation.rst
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ are not already enabled:
Sonata\DeliveryBundle\SonataDeliveryBundle::class => ['all' => true],
Sonata\PaymentBundle\SonataPaymentBundle::class => ['all' => true],
Sonata\PriceBundle\SonataPriceBundle::class => ['all' => true],
Sonata\ProfileBundle\SonataProfileBundle::class => ['all' => true],
// ...
new Knp\Bundle\MenuBundle\KnpMenuBundle::class => ['all' => true],
];
Expand All @@ -76,6 +77,7 @@ are not already enabled:
new Sonata\DeliveryBundle\SonataDeliveryBundle(),
new Sonata\PaymentBundle\SonataPaymentBundle(),
new Sonata\PriceBundle\SonataPriceBundle(),
new Sonata\ProfileBundle\SonataProfileBundle(),
// ...
new Knp\Bundle\MenuBundle\KnpMenuBundle(),
);
Expand Down Expand Up @@ -155,6 +157,17 @@ Configuration
sonata_price:
currency: EUR
sonata_profile:
override_sonata_user_bundle_profile: false
template: 'SonataProfileBundle::action.html.twig'
dashboard:
blocks:
- { position: left, type: sonata.order.block.recent_orders, settings: { title: Recent Orders, number: 5, mode: public }}
menu:
- { route: 'sonata_profile_dashboard', label: 'Dashboard', domain: 'SonataProfileBundle'}
- { route: 'sonata_customer_addresses', label: 'link_list_addresses', domain: 'SonataCustomerBundle'}
- { route: 'sonata_order_index', label: 'order_list', domain: 'SonataOrderBundle'}
# Doctrine Configuration
doctrine:
# ...
Expand Down Expand Up @@ -273,6 +286,12 @@ Next, add the correct routing files:
resource: "@SonataInvoiceBundle/Resources/config/routing/invoice.xml"
prefix: /shop/user/invoice
# import this route when you not using SonataUserBundle Profile
# or sonata_profile.override_sonata_user_bundle_profile is set to true
sonata_profile:
resource: '@SonataProfileBundle/Resources/config/routing/profile.xml'
prefix: /shop/profile
.. note::
If you are not using Symfony Flex, routes should be added to ``app/config/routing.yml``.

Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
{% extends "@SonataUser/Profile/action.html.twig" %}
{% extends sonata_profile.template %}


{% block sonata_profile_title %}{% trans from 'SonataCustomerBundle' %}address_list{% endtrans %}{% endblock %}
Expand Down
2 changes: 1 addition & 1 deletion src/CustomerBundle/Resources/views/Addresses/new.html.twig
Original file line number Diff line number Diff line change
Expand Up @@ -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_profile.template %}

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

Expand Down
2 changes: 1 addition & 1 deletion src/InvoiceBundle/Resources/views/Invoice/view.html.twig
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ file that was distributed with this source code.
#}

{% extends "@SonataUser/Profile/action.html.twig" %}
{% extends sonata_profile.template %}


{% block sonata_profile_title %}{% trans from 'SonataInvoiceBundle' %}sonata.invoice.title_invoice{% endtrans %} - {{ invoice.reference }}{% endblock %}
Expand Down
2 changes: 1 addition & 1 deletion src/OrderBundle/Resources/views/Order/index.html.twig
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ file that was distributed with this source code.
#}

{% extends "@SonataUser/Profile/action.html.twig" %}
{% extends sonata_profile.template %}


{% block sonata_profile_title %}{% trans from 'SonataOrderBundle' %}order_list{% endtrans %}{% endblock %}
Expand Down
2 changes: 1 addition & 1 deletion src/OrderBundle/Resources/views/Order/view.html.twig
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ file that was distributed with this source code.
#}

{% extends "@SonataUser/Profile/action.html.twig" %}
{% extends sonata_profile.template %}


{% block sonata_profile_title %}{% trans from 'SonataOrderBundle' %}sonata.order.title_order{% endtrans %} - {{ order.reference }}{% endblock %}
Expand Down
73 changes: 73 additions & 0 deletions src/ProfileBundle/Block/AccountBlockService.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
<?php

declare(strict_types=1);

/*
* This file is part of the Sonata Project package.
*
* (c) Thomas Rabaix <thomas.rabaix@sonata-project.org>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/

namespace Sonata\ProfileBundle\Block;

use Sonata\BlockBundle\Block\BlockContextInterface;
use Sonata\BlockBundle\Block\Service\AbstractAdminBlockService;
use Symfony\Bundle\FrameworkBundle\Templating\EngineInterface;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\OptionsResolver\OptionsResolver;
use Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorageInterface;
use Symfony\Component\Security\Core\User\UserInterface;

/**
* Render a block with the connection option or the login name.
*
* @author Thomas Rabaix <thomas.rabaix@sonata-project.org>
*/
final class AccountBlockService extends AbstractAdminBlockService
{
/**
* @var TokenStorageInterface
*/
private $tokenStorage;

public function __construct(string $name, EngineInterface $templating, TokenStorageInterface $tokenStorage)
{
parent::__construct($name, $templating);

$this->tokenStorage = $tokenStorage;
}

public function execute(BlockContextInterface $blockContext, Response $response = null)
{
$user = false;
if ($this->tokenStorage->getToken()) {
$user = $this->tokenStorage->getToken()->getUser();
}

if (!$user instanceof UserInterface) {
$user = false;
}

return $this->renderPrivateResponse($blockContext->getTemplate(), [
'user' => $user,
'block' => $blockContext->getBlock(),
'context' => $blockContext,
]);
}

public function configureSettings(OptionsResolver $resolver)
{
$resolver->setDefaults([
'template' => 'SonataProfileBundle:Block:account.html.twig',
'ttl' => 0,
]);
}

public function getName()
{
return 'Account Block';
}
}
76 changes: 76 additions & 0 deletions src/ProfileBundle/Block/ProfileMenuBlockService.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
<?php

declare(strict_types=1);

/*
* This file is part of the Sonata Project package.
*
* (c) Thomas Rabaix <thomas.rabaix@sonata-project.org>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/

namespace Sonata\ProfileBundle\Block;

use Knp\Menu\Provider\MenuProviderInterface;
use Sonata\BlockBundle\Block\BlockContextInterface;
use Sonata\BlockBundle\Block\Service\MenuBlockService;
use Sonata\ProfileBundle\Menu\ProfileMenuBuilder;
use Symfony\Bundle\FrameworkBundle\Templating\EngineInterface;
use Symfony\Component\OptionsResolver\OptionsResolver;

/**
* @author Hugo Briand <briand@ekino.com>
*/
final class ProfileMenuBlockService extends MenuBlockService
{
/**
* @var ProfileMenuBuilder
*/
private $menuBuilder;

public function __construct(string $name, EngineInterface $templating, MenuProviderInterface $menuProvider, ProfileMenuBuilder $menuBuilder)
{
parent::__construct($name, $templating, $menuProvider, []);

$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)
{
$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;
}
}
43 changes: 43 additions & 0 deletions src/ProfileBundle/Controller/ProfileController.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
<?php

declare(strict_types=1);

/*
* This file is part of the Sonata Project package.
*
* (c) Thomas Rabaix <thomas.rabaix@sonata-project.org>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/

namespace Sonata\ProfileBundle\Controller;

use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Security\Core\Exception\AccessDeniedException;
use Symfony\Component\Security\Core\User\UserInterface;

/**
* This class is inspired from the FOS Profile Controller, except :
* - only twig is supported
* - separation of the user authentication form with the profile form.
*/
final class ProfileController extends Controller
{
/**
* @throws AccessDeniedException
*/
public function dashboardAction(): Response
{
$user = $this->getUser();
if (!\is_object($user) || !$user instanceof UserInterface) {
throw new AccessDeniedException('This user does not have access to this section.');
}

return $this->render('SonataProfileBundle::dashboard.html.twig', [
'user' => $user,
'blocks' => $this->container->getParameter('sonata.profile.configuration.profile_blocks'),
]);
}
}
Loading

0 comments on commit 42feffa

Please sign in to comment.