Skip to content

Commit

Permalink
Feature completion listener and form (#11)
Browse files Browse the repository at this point in the history
* add completion listener service

* add completion form and handling

* register completion listener in service xml and set or unset in compilerpass

* do not redirect to confirmation page after completion form and fix tests
  • Loading branch information
alexander-schranz authored and wachterjohannes committed Jun 22, 2016
1 parent c502d99 commit b346e0a
Show file tree
Hide file tree
Showing 18 changed files with 649 additions and 44 deletions.
89 changes: 89 additions & 0 deletions Controller/CompletionController.php
@@ -0,0 +1,89 @@
<?php

/*
* This file is part of Sulu.
*
* (c) MASSIVE ART WebServices GmbH
*
* This source file is subject to the MIT license that is bundled
* with this source code in the file LICENSE.
*/

namespace Sulu\Bundle\CommunityBundle\Controller;

use Sulu\Bundle\CommunityBundle\DependencyInjection\Configuration;
use Sulu\Bundle\CommunityBundle\EventListener\CompletionListener;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpKernel\Exception\HttpException;

/**
* Handles the completion page.
*/
class CompletionController extends AbstractController
{
const TYPE = Configuration::TYPE_COMPLETION;

/**
* Handle registration form.
*
* @param Request $request
*
* @return Response
*/
public function indexAction(Request $request)
{
$user = $this->getUser();

if (!$user) {
throw new HttpException(403, 'You need to be logged in for completion form.');
}

$communityManager = $this->getCommunityManager($this->getWebspaceKey());

// Create Form
$form = $this->createForm(
$communityManager->getConfigTypeProperty(self::TYPE, Configuration::FORM_TYPE),
$user,
$communityManager->getConfigTypeProperty(self::TYPE, Configuration::FORM_TYPE_OPTIONS)
);

$form->handleRequest($request);
$success = false;

// Handle Form Success
if ($form->isSubmitted() && $form->isValid()) {
$user = $form->getData();

// Completion User
$communityManager->completion($user);

// Save User
$this->saveEntities();

// Redirect
$session = $request->getSession();
$redirectTo = $session->get(CompletionListener::SESSION_STORE);

if (!$redirectTo) {
$redirectTo = $communityManager->getConfigTypeProperty(self::TYPE, Configuration::REDIRECT_TO);
} else {
$session->remove(CompletionListener::SESSION_STORE);
}

if ($redirectTo) {
return $this->redirect($redirectTo);
}

$success = true;
}

return $this->renderTemplate(
self::TYPE,
[
'form' => $form->createView(),
'success' => $success,
]
);
}
}
@@ -0,0 +1,56 @@
<?php

/*
* This file is part of Sulu.
*
* (c) MASSIVE ART WebServices GmbH
*
* This source file is subject to the MIT license that is bundled
* with this source code in the file LICENSE.
*/

namespace Sulu\Bundle\CommunityBundle\DependencyInjection\CompilerPass;

use Sulu\Bundle\CommunityBundle\DependencyInjection\Configuration;
use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface;
use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\DependencyInjection\Reference;

/**
* Register the completion listener when validators are configured.
*/
class CommunityValidatorCompilerPass implements CompilerPassInterface
{
const COMPLETION_LISTENER_SERVICE_ID = 'sulu_community.completion_listener';

/**
* {@inheritdoc}
*/
public function process(ContainerBuilder $container)
{
// If no listener exists do nothing
if (!$container->hasDefinition(self::COMPLETION_LISTENER_SERVICE_ID)) {
return;
}

// Create Validator References
$config = $container->getParameter('sulu_community.config');

foreach ($config[Configuration::WEBSPACES] as $webspaceKey => $webspaceConfig) {
// Get Completion Validator
$validatorId = $webspaceConfig[Configuration::TYPE_COMPLETION][Configuration::SERVICE];

if ($validatorId) {
$validators[$webspaceKey] = new Reference($validatorId);
}
}

// Register request listener only when validator exists.
if (!empty($validators)) {
$definition = $container->getDefinition(self::COMPLETION_LISTENER_SERVICE_ID);
$definition->replaceArgument(3, $validators);
} else {
$container->removeDefinition(self::COMPLETION_LISTENER_SERVICE_ID);
}
}
}
25 changes: 25 additions & 0 deletions DependencyInjection/Configuration.php
Expand Up @@ -11,6 +11,7 @@

namespace Sulu\Bundle\CommunityBundle\DependencyInjection;

use Sulu\Bundle\CommunityBundle\Form\Type\CompletionType;
use Sulu\Bundle\CommunityBundle\Form\Type\PasswordForgetType;
use Sulu\Bundle\CommunityBundle\Form\Type\PasswordResetType;
use Sulu\Bundle\CommunityBundle\Form\Type\RegistrationType;
Expand All @@ -36,6 +37,7 @@ class Configuration implements ConfigurationInterface
// Form types
const TYPE_LOGIN = 'login';
const TYPE_REGISTRATION = 'registration';
const TYPE_COMPLETION = 'completion';
const TYPE_CONFIRMATION = 'confirmation';
const TYPE_PASSWORD_FORGET = 'password_forget';
const TYPE_PASSWORD_RESET = 'password_reset';
Expand All @@ -51,6 +53,7 @@ class Configuration implements ConfigurationInterface

// Type configurations
const TEMPLATE = 'template';
const SERVICE = 'service';
const EMBED_TEMPLATE = 'embed_template';
const FORM_TYPE = 'type';
const FORM_TYPE_OPTIONS = 'options';
Expand Down Expand Up @@ -224,6 +227,28 @@ public function getConfigTreeBuilder()
->end()
->end()
->end()
// Completion
->arrayNode(self::TYPE_COMPLETION)
->addDefaultsIfNotSet()
->children()
// Completion Configuration
->scalarNode(self::SERVICE)->defaultValue(null)->end()
->scalarNode(self::TEMPLATE)->defaultValue('SuluCommunityBundle:community:completion.html.twig')->end()
->scalarNode(self::FORM_TYPE)->defaultValue(CompletionType::class)->end()
->arrayNode(self::FORM_TYPE_OPTIONS)
->addDefaultsIfNotSet()
->end()
->scalarNode(self::REDIRECT_TO)->defaultValue('/')->end()
->arrayNode(self::EMAIL)
->addDefaultsIfNotSet()
->children()
->scalarNode(self::EMAIL_SUBJECT)->defaultValue('Completion')->end()
->scalarNode(self::EMAIL_ADMIN_TEMPLATE)->defaultValue(null)->end()
->scalarNode(self::EMAIL_USER_TEMPLATE)->defaultValue(null)->end()
->end()
->end()
->end()
->end()
->end()
->end()
->end()
Expand Down
136 changes: 136 additions & 0 deletions EventListener/CompletionListener.php
@@ -0,0 +1,136 @@
<?php

/*
* This file is part of Sulu.
*
* (c) MASSIVE ART WebServices GmbH
*
* This source file is subject to the MIT license that is bundled
* with this source code in the file LICENSE.
*/

namespace Sulu\Bundle\CommunityBundle\EventListener;

use Sulu\Bundle\CommunityBundle\Validator\User\CompletionInterface;
use Sulu\Bundle\SecurityBundle\Entity\User;
use Sulu\Component\Webspace\Analyzer\RequestAnalyzerInterface;
use Symfony\Component\HttpFoundation\RedirectResponse;
use Symfony\Component\HttpKernel\Event\GetResponseEvent;
use Symfony\Component\Routing\RouterInterface;
use Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorage;

/**
* Validates the current user entity.
*/
class CompletionListener
{
/**
* @var string
*/
const SESSION_STORE = 'sulu_community/completion/redirect_to';

/**
* @var RequestAnalyzerInterface
*/
protected $requestAnalyzer;

/**
* @var RouterInterface
*/
protected $router;

/**
* @var TokenStorage
*/
protected $tokenStorage;

/**
* @var CompletionInterface[]
*/
protected $validators;

/**
* CompletionListener constructor.
*
* @param RequestAnalyzerInterface $requestAnalyzer
* @param RouterInterface $router
* @param TokenStorage $tokenStorage
* @param array $validators
*/
public function __construct(
RequestAnalyzerInterface $requestAnalyzer,
RouterInterface $router,
TokenStorage $tokenStorage,
array $validators
) {
$this->requestAnalyzer = $requestAnalyzer;
$this->router = $router;
$this->tokenStorage = $tokenStorage;
$this->validators = $validators;
}

/**
* Will call a specific user completion validator of a webspace.
*
* @param GetResponseEvent $event
*/
public function onRequest(GetResponseEvent $event)
{
$request = $event->getRequest();
$completionUrl = $this->router->generate('sulu_community.completion');

if (!$event->isMasterRequest()
|| $request->isMethod('post')
|| $request->isXmlHttpRequest()
|| $request->getPathInfo() === $completionUrl
) {
return;
}

$token = $this->tokenStorage->getToken();

/** @var User $user */
$user = $token->getUser();

if (!$user instanceof User) {
// don't do anything if no user is login
return;
}

if ($request->attributes->get('_route') !== 'sulu_community.confirmation') {
$session = $request->getSession();
$session->set(self::SESSION_STORE, $request->getUri());
}

$webspaceKey = $this->requestAnalyzer->getWebspace()->getKey();
$validator = $this->getValidator($webspaceKey);

if ($validator && !$validator->validate($user, $webspaceKey)) {
$response = new RedirectResponse($completionUrl);
$event->setResponse($response);
}
}

/**
* @param CompletionInterface $validator
* @param string $webspaceKey
*/
public function addValidator(CompletionInterface $validator, $webspaceKey)
{
$this->validators[$webspaceKey] = $validator;
}

/**
* @param string $webspaceKey
*
* @return CompletionInterface
*/
protected function getValidator($webspaceKey)
{
if (!isset($this->validators[$webspaceKey])) {
return;
}

return $this->validators[$webspaceKey];
}
}
10 changes: 10 additions & 0 deletions EventListener/MailListener.php
Expand Up @@ -74,6 +74,16 @@ public function sendPasswordResetEmails(CommunityEvent $event)
$this->sendTypeEmails($event, Configuration::TYPE_PASSWORD_RESET);
}

/**
* Send password reset emails.
*
* @param CommunityEvent $event
*/
public function sendCompletionEmails(CommunityEvent $event)
{
$this->sendTypeEmails($event, Configuration::TYPE_COMPLETION);
}

/**
* Send emails for specific type.
*
Expand Down

0 comments on commit b346e0a

Please sign in to comment.