From 4e6c19e90ecd1857974c14f3c52a6fc2209d725c Mon Sep 17 00:00:00 2001 From: Titouan Galopin Date: Sat, 3 Sep 2016 16:19:47 +0200 Subject: [PATCH] Add support of Symfony 3 and drop Symfony < 2.7 --- .travis.yml | 51 ++++++++++++------- Controller/MessageController.php | 28 +++++++--- DependencyInjection/Configuration.php | 4 +- DependencyInjection/FOSMessageExtension.php | 30 ++++++++++- Document/Message.php | 6 +-- Document/Thread.php | 2 +- DocumentManager/MessageManager.php | 8 +-- EntityManager/MessageManager.php | 4 +- FormFactory/AbstractMessageFormFactory.php | 16 ++++-- FormHandler/AbstractMessageFormHandler.php | 43 ++++++++++++++-- FormType/NewThreadMessageFormType.php | 40 +++++++++++++-- FormType/NewThreadMultipleMessageFormType.php | 29 +++++++++-- FormType/RecipientsType.php | 25 +++++++-- FormType/ReplyMessageFormType.php | 30 +++++++++-- Model/MessageMetadata.php | 9 ++-- Model/ParticipantInterface.php | 2 +- Model/ReadableInterface.php | 2 +- Model/Thread.php | 8 +-- Model/ThreadInterface.php | 25 +++------ Model/ThreadMetadata.php | 15 ++---- ModelManager/MessageManagerInterface.php | 2 +- ModelManager/ThreadManagerInterface.php | 2 +- Provider/Provider.php | 1 - README.md | 8 +-- Reader/ReaderInterface.php | 10 ++-- Resources/config/config.xml | 6 +-- Resources/config/form.xml | 12 ++--- Resources/config/routing.xml | 18 +++---- Resources/config/spam_detection.xml | 2 +- Resources/config/validator.xml | 2 +- Resources/doc/99-config-reference.md | 4 +- Resources/doc/99-using-other-user-bundles.md | 3 +- Search/QueryFactory.php | 27 +++++++--- Security/AuthorizerInterface.php | 6 +-- Security/ParticipantProvider.php | 14 ++++- Sender/SenderInterface.php | 4 +- SpamDetection/SpamDetectorInterface.php | 2 +- Twig/Extension/MessageExtension.php | 6 +-- UPGRADING.md | 36 +++++++++++++ Util/LegacyFormHelper.php | 47 +++++++++++++++++ composer.json | 14 +++-- 41 files changed, 432 insertions(+), 171 deletions(-) create mode 100644 UPGRADING.md create mode 100644 Util/LegacyFormHelper.php diff --git a/.travis.yml b/.travis.yml index 4a33db1e..23aff848 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,30 +1,45 @@ language: php -php: - - 5.3 - - 5.4 - - 5.5 - - 5.6 - - hhvm +sudo: false -env: - - SYMFONY_VERSION=2.1.* - - SYMFONY_VERSION=2.2.* - - SYMFONY_VERSION=2.3.* - - SYMFONY_VERSION=dev-master +branches: + only: + - master + +matrix: + include: + - php: 5.3 + env: + - deps=low + - SYMFONY_VERSION=2.7.* + - php: 5.4 + env: + - deps=high + - SYMFONY_VERSION=2.7.* + - php: 5.5 + env: + - deps=low + - SYMFONY_VERSION=2.8.* + - php: 5.6 + env: + - deps=high + - SYMFONY_VERSION=3.0.* + - php: 7.0 + env: + - deps=low + - SYMFONY_VERSION=3.1.* + - php: 7.1 + env: + - deps=high + - SYMFONY_VERSION=3.1.* before_script: - composer require symfony/framework-bundle:${SYMFONY_VERSION} --no-update - - composer update --dev + - if [[ $deps = high ]]; then composer update --no-progress --ansi; fi + - if [[ $deps = low ]]; then composer update --no-progress --ansi --prefer-lowest --prefer-stable; fi script: phpunit --coverage-text notifications: email: - friendsofsymfony-dev@googlegroups.com - -matrix: - allow_failures: - - env: SYMFONY_VERSION=dev-master - - php: 5.6 - - php: hhvm diff --git a/Controller/MessageController.php b/Controller/MessageController.php index ffb9f8a5..86b3b725 100644 --- a/Controller/MessageController.php +++ b/Controller/MessageController.php @@ -2,13 +2,19 @@ namespace FOS\MessageBundle\Controller; -use Symfony\Component\DependencyInjection\ContainerAware; +use Symfony\Component\DependencyInjection\ContainerAwareInterface; +use Symfony\Component\DependencyInjection\ContainerInterface; use Symfony\Component\HttpFoundation\RedirectResponse; use FOS\MessageBundle\Provider\ProviderInterface; use Symfony\Component\HttpFoundation\Response; -class MessageController extends ContainerAware +class MessageController implements ContainerAwareInterface { + /** + * @var ContainerInterface + */ + protected $container; + /** * Displays the authenticated participant inbox * @@ -55,7 +61,7 @@ public function deletedAction() * Displays a thread, also allows to reply to it * * @param string $threadId the thread id - * + * * @return Response */ public function threadAction($threadId) @@ -100,9 +106,9 @@ public function newThreadAction() /** * Deletes a thread - * + * * @param string $threadId the thread id - * + * * @return RedirectResponse */ public function deleteAction($threadId) @@ -116,9 +122,9 @@ public function deleteAction($threadId) /** * Undeletes a thread - * + * * @param string $threadId - * + * * @return RedirectResponse */ public function undeleteAction($threadId) @@ -155,4 +161,12 @@ protected function getProvider() { return $this->container->get('fos_message.provider'); } + + /** + * {@inheritdoc} + */ + public function setContainer(ContainerInterface $container = null) + { + $this->container = $container; + } } diff --git a/DependencyInjection/Configuration.php b/DependencyInjection/Configuration.php index d2f6ebf5..aad92519 100644 --- a/DependencyInjection/Configuration.php +++ b/DependencyInjection/Configuration.php @@ -50,7 +50,7 @@ public function getConfigTreeBuilder() ->addDefaultsIfNotSet() ->children() ->scalarNode('factory')->defaultValue('fos_message.new_thread_form.factory.default')->cannotBeEmpty()->end() - ->scalarNode('type')->defaultValue('fos_message.new_thread_form.type.default')->cannotBeEmpty()->end() + ->scalarNode('type')->defaultValue('FOS\MessageBundle\FormType\NewThreadMessageFormType')->cannotBeEmpty()->end() ->scalarNode('handler')->defaultValue('fos_message.new_thread_form.handler.default')->cannotBeEmpty()->end() ->scalarNode('name')->defaultValue('message')->cannotBeEmpty()->end() ->scalarNode('model')->defaultValue('FOS\MessageBundle\FormModel\NewThreadMessage')->end() @@ -60,7 +60,7 @@ public function getConfigTreeBuilder() ->addDefaultsIfNotSet() ->children() ->scalarNode('factory')->defaultValue('fos_message.reply_form.factory.default')->cannotBeEmpty()->end() - ->scalarNode('type')->defaultValue('fos_message.reply_form.type.default')->cannotBeEmpty()->end() + ->scalarNode('type')->defaultValue('FOS\MessageBundle\FormType\ReplyMessageFormType')->cannotBeEmpty()->end() ->scalarNode('handler')->defaultValue('fos_message.reply_form.handler.default')->cannotBeEmpty()->end() ->scalarNode('name')->defaultValue('message')->cannotBeEmpty()->end() ->scalarNode('model')->defaultValue('FOS\MessageBundle\FormModel\ReplyMessage')->end() diff --git a/DependencyInjection/FOSMessageExtension.php b/DependencyInjection/FOSMessageExtension.php index 15ec2786..9c28742c 100644 --- a/DependencyInjection/FOSMessageExtension.php +++ b/DependencyInjection/FOSMessageExtension.php @@ -2,6 +2,7 @@ namespace FOS\MessageBundle\DependencyInjection; +use FOS\MessageBundle\Util\LegacyFormHelper; use Symfony\Component\Config\Definition\Processor; use Symfony\Component\DependencyInjection\Reference; use Symfony\Component\HttpKernel\DependencyInjection\Extension; @@ -23,6 +24,7 @@ public function load(array $configs, ContainerBuilder $container) if (!in_array(strtolower($config['db_driver']), array('orm', 'mongodb'))) { throw new \InvalidArgumentException(sprintf('Invalid db driver "%s".', $config['db_driver'])); } + $loader->load(sprintf('%s.xml', $config['db_driver'])); $loader->load('config.xml'); $loader->load('form.xml'); @@ -51,10 +53,34 @@ public function load(array $configs, ContainerBuilder $container) $container->setAlias('fos_message.spam_detector', $config['spam_detector']); $container->setAlias('fos_message.twig_extension', $config['twig_extension']); - $container->setAlias('fos_message.new_thread_form.type', $config['new_thread_form']['type']); + // BC management + $newThreadFormType = $config['new_thread_form']['type']; + $replyFormType = $config['reply_form']['type']; + + if (!class_exists($newThreadFormType)) { + @trigger_error('Using a service reference in configuration key "fos_message.new_thread_form.type" is deprecated since version 1.2 and will be removed in 2.0. Use the class name of your form type instead.', E_USER_DEPRECATED); + + // Old syntax (service reference) + $container->setAlias('fos_message.new_thread_form.type', $newThreadFormType); + } else { + // New syntax (class name) + $container->getDefinition('fos_message.new_thread_form.factory.default') + ->replaceArgument(1, $newThreadFormType); + } + + if (!class_exists($replyFormType)) { + @trigger_error('Using a service reference in configuration key "fos_message.reply_form.type" is deprecated since version 1.2 and will be removed in 2.0. Use the class name of your form type instead.', E_USER_DEPRECATED); + + // Old syntax (service reference) + $container->setAlias('fos_message.reply_form.type', $replyFormType); + } else { + // New syntax (class name) + $container->getDefinition('fos_message.reply_form.factory.default') + ->replaceArgument(1, $replyFormType); + } + $container->setAlias('fos_message.new_thread_form.factory', $config['new_thread_form']['factory']); $container->setAlias('fos_message.new_thread_form.handler', $config['new_thread_form']['handler']); - $container->setAlias('fos_message.reply_form.type', $config['reply_form']['type']); $container->setAlias('fos_message.reply_form.factory', $config['reply_form']['factory']); $container->setAlias('fos_message.reply_form.handler', $config['reply_form']['handler']); diff --git a/Document/Message.php b/Document/Message.php index 7f49e0ea..a905df50 100644 --- a/Document/Message.php +++ b/Document/Message.php @@ -10,7 +10,7 @@ abstract class Message extends BaseMessage * Tells if the message is spam or flood * This denormalizes Thread.isSpam * - * @var boolean + * @var bool */ protected $isSpam = false; @@ -23,11 +23,11 @@ abstract class Message extends BaseMessage protected $unreadForParticipants = array(); /** - * @param boolean $isSpam + * @param bool $isSpam */ public function setIsSpam($isSpam) { - $this->isSpam = (boolean) $isSpam; + $this->isSpam = (bool) $isSpam; } /* diff --git a/Document/Thread.php b/Document/Thread.php index f19571c4..43cc9400 100644 --- a/Document/Thread.php +++ b/Document/Thread.php @@ -79,7 +79,7 @@ public function addParticipant(ParticipantInterface $participant) * Tells if the user participates to the conversation * * @param ParticipantInterface $participant - * @return boolean + * @return bool */ public function isParticipant(ParticipantInterface $participant) { diff --git a/DocumentManager/MessageManager.php b/DocumentManager/MessageManager.php index b2a8f718..b73f84e9 100644 --- a/DocumentManager/MessageManager.php +++ b/DocumentManager/MessageManager.php @@ -84,7 +84,7 @@ public function markAsUnreadByParticipant(ReadableInterface $readable, Participa * * @param ThreadInterface $thread * @param ParticipantInterface $participant - * @param boolean $isRead + * @param bool $isRead */ public function markIsReadByThreadAndParticipant(ThreadInterface $thread, ParticipantInterface $participant, $isRead) { @@ -98,7 +98,7 @@ public function markIsReadByThreadAndParticipant(ThreadInterface $thread, Partic * * @param MessageInterface $message * @param ParticipantInterface $participant - * @param boolean $isRead + * @param bool $isRead */ protected function markIsReadByParticipant(MessageInterface $message, ParticipantInterface $participant, $isRead) { @@ -112,7 +112,7 @@ protected function markIsReadByParticipant(MessageInterface $message, Participan * by updating directly the storage * * @param ParticipantInterface $participant - * @param boolean $isRead + * @param bool $isRead * @param \Closure $condition */ protected function markIsReadByCondition(ParticipantInterface $participant, $isRead, \Closure $condition) @@ -132,7 +132,7 @@ protected function markIsReadByCondition(ParticipantInterface $participant, $isR } $queryBuilder - ->field('metadata.$.isRead')->set((boolean) $isRead) + ->field('metadata.$.isRead')->set((bool) $isRead) ->getQuery(array('multiple' => true)) ->execute(); diff --git a/EntityManager/MessageManager.php b/EntityManager/MessageManager.php index 10a5eea7..adcc2bb1 100644 --- a/EntityManager/MessageManager.php +++ b/EntityManager/MessageManager.php @@ -97,7 +97,7 @@ public function markAsUnreadByParticipant(ReadableInterface $readable, Participa * * @param ThreadInterface $thread * @param ParticipantInterface $participant - * @param boolean $isRead + * @param bool $isRead */ public function markIsReadByThreadAndParticipant(ThreadInterface $thread, ParticipantInterface $participant, $isRead) { @@ -111,7 +111,7 @@ public function markIsReadByThreadAndParticipant(ThreadInterface $thread, Partic * * @param MessageInterface $message * @param ParticipantInterface $participant - * @param boolean $isRead + * @param bool $isRead */ protected function markIsReadByParticipant(MessageInterface $message, ParticipantInterface $participant, $isRead) { diff --git a/FormFactory/AbstractMessageFormFactory.php b/FormFactory/AbstractMessageFormFactory.php index 77eef977..aecceceb 100644 --- a/FormFactory/AbstractMessageFormFactory.php +++ b/FormFactory/AbstractMessageFormFactory.php @@ -23,7 +23,7 @@ abstract class AbstractMessageFormFactory /** * The message form type * - * @var AbstractType + * @var AbstractType|string */ protected $formType; @@ -41,8 +41,16 @@ abstract class AbstractMessageFormFactory */ protected $messageClass; - public function __construct(FormFactoryInterface $formFactory, AbstractType $formType, $formName, $messageClass) + public function __construct(FormFactoryInterface $formFactory, $formType, $formName, $messageClass) { + if (!is_string($formType) && !$formType instanceof AbstractType) { + throw new \InvalidArgumentException(sprintf( + 'Form type provided is not valid (class name or instance of %s expected, %s given)', + 'Symfony\Component\Form\AbstractType', + is_object($formType) ? get_class($formType) : gettype($formType) + )); + } + $this->formFactory = $formFactory; $this->formType = $formType; $this->formName = $formName; @@ -56,6 +64,8 @@ public function __construct(FormFactoryInterface $formFactory, AbstractType $for */ protected function createModelInstance() { - return new $this->messageClass(); + $class = $this->messageClass; + + return new $class(); } } diff --git a/FormHandler/AbstractMessageFormHandler.php b/FormHandler/AbstractMessageFormHandler.php index 923aa592..6680fc3a 100644 --- a/FormHandler/AbstractMessageFormHandler.php +++ b/FormHandler/AbstractMessageFormHandler.php @@ -5,6 +5,7 @@ use FOS\MessageBundle\Model\MessageInterface; use Symfony\Component\Form\Form; use Symfony\Component\HttpFoundation\Request; +use Symfony\Component\HttpFoundation\RequestStack; use FOS\MessageBundle\Composer\ComposerInterface; use FOS\MessageBundle\FormModel\AbstractMessage; use FOS\MessageBundle\Security\ParticipantProviderInterface; @@ -23,8 +24,20 @@ abstract class AbstractMessageFormHandler protected $sender; protected $participantProvider; - public function __construct(Request $request, ComposerInterface $composer, SenderInterface $sender, ParticipantProviderInterface $participantProvider) + /** + * @param Request|RequestStack $request + * @param ComposerInterface $composer + * @param SenderInterface $sender + * @param ParticipantProviderInterface $participantProvider + */ + public function __construct($request, ComposerInterface $composer, SenderInterface $sender, ParticipantProviderInterface $participantProvider) { + if ($request instanceof Request) { + @trigger_error(sprintf('Using an instance of "%s" as first parameter of "%s" is deprecated since version 1.3 and won\'t be supported in 2.0. Use an instance of "Symfony\Component\HttpFoundation\RequestStack" instead.', get_class($request), __METHOD__), E_USER_DEPRECATED); + } elseif (!$request instanceof RequestStack) { + throw new \InvalidArgumentException(sprintf('AbstractMessageFormHandler expected a Request or RequestStack, %s given', is_object($request) ? get_class($request) : gettype($request))); + } + $this->request = $request; $this->composer = $composer; $this->sender = $sender; @@ -39,11 +52,13 @@ public function __construct(Request $request, ComposerInterface $composer, Sende */ public function process(Form $form) { - if ('POST' !== $this->request->getMethod()) { + $request = $this->getCurrentRequest(); + + if ('POST' !== $request->getMethod()) { return false; } - $form->bind($this->request); + $form->handleRequest($request); if ($form->isValid()) { return $this->processValidForm($form); @@ -61,7 +76,6 @@ public function process(Form $form) public function processValidForm(Form $form) { $message = $this->composeMessage($form->getData()); - $this->sender->send($message); return $message; @@ -84,4 +98,25 @@ protected function getAuthenticatedParticipant() { return $this->participantProvider->getAuthenticatedParticipant(); } + + /** + * BC layer to retrieve the current request directly or from a stack. + * + * @return Request + */ + private function getCurrentRequest() { + if (!$this->request) { + throw new \RuntimeException('Current request was not provided to the form handler.'); + } + + if ($this->request instanceof Request) { + return $this->request; + } + + if (!$this->request->getCurrentRequest()) { + throw new \RuntimeException('Request stack provided to the form handler did not contains a current request.'); + } + + return $this->request->getCurrentRequest(); + } } diff --git a/FormType/NewThreadMessageFormType.php b/FormType/NewThreadMessageFormType.php index 772e6921..b31f9bfa 100644 --- a/FormType/NewThreadMessageFormType.php +++ b/FormType/NewThreadMessageFormType.php @@ -2,8 +2,10 @@ namespace FOS\MessageBundle\FormType; +use FOS\MessageBundle\Util\LegacyFormHelper; use Symfony\Component\Form\AbstractType; use Symfony\Component\Form\FormBuilderInterface; +use Symfony\Component\OptionsResolver\OptionsResolver; use Symfony\Component\OptionsResolver\OptionsResolverInterface; /** @@ -16,20 +18,48 @@ class NewThreadMessageFormType extends AbstractType public function buildForm(FormBuilderInterface $builder, array $options) { $builder - ->add('recipient', 'fos_user_username', array('label' => 'recipient', 'translation_domain' => 'FOSMessageBundle')) - ->add('subject', 'text', array('label' => 'subject', 'translation_domain' => 'FOSMessageBundle')) - ->add('body', 'textarea', array('label' => 'body', 'translation_domain' => 'FOSMessageBundle')); + ->add('recipient', LegacyFormHelper::getType('FOS\UserBundle\Form\Type\UsernameFormType'), array( + 'label' => 'recipient', + 'translation_domain' => 'FOSMessageBundle' + )) + ->add('subject', LegacyFormHelper::getType('Symfony\Component\Form\Extension\Core\Type\TextType'), array( + 'label' => 'subject', + 'translation_domain' => 'FOSMessageBundle' + )) + ->add('body', LegacyFormHelper::getType('Symfony\Component\Form\Extension\Core\Type\TextareaType'), array( + 'label' => 'body', + 'translation_domain' => 'FOSMessageBundle' + )); } - public function setDefaultOptions(OptionsResolverInterface $resolver) + public function configureOptions(OptionsResolver $resolver) { $resolver->setDefaults(array( 'intention' => 'message', )); } - public function getName() + /** + * {@inheritDoc} + */ + public function getBlockPrefix() { return 'fos_message_new_thread'; } + + /** + * @deprecated To remove when supporting only Symfony 3 + */ + public function setDefaultOptions(OptionsResolverInterface $resolver) + { + $this->configureOptions($resolver); + } + + /** + * @deprecated To remove when supporting only Symfony 3 + */ + public function getName() + { + return $this->getBlockPrefix(); + } } diff --git a/FormType/NewThreadMultipleMessageFormType.php b/FormType/NewThreadMultipleMessageFormType.php index a9836baf..8af2aa21 100644 --- a/FormType/NewThreadMultipleMessageFormType.php +++ b/FormType/NewThreadMultipleMessageFormType.php @@ -1,6 +1,7 @@ add('recipients', 'recipients_selector', array('label' => 'recipients', 'translation_domain' => 'FOSMessageBundle')) - ->add('subject', 'text', array('label' => 'subject', 'translation_domain' => 'FOSMessageBundle')) - ->add('body', 'textarea', array('label' => 'body', 'translation_domain' => 'FOSMessageBundle')); + ->add('recipients', LegacyFormHelper::getType('FOS\MessageBundle\FormType\RecipientsType'), array( + 'label' => 'recipients', + 'translation_domain' => 'FOSMessageBundle' + )) + ->add('subject', LegacyFormHelper::getType('Symfony\Component\Form\Extension\Core\Type\TextType'), array( + 'label' => 'subject', + 'translation_domain' => 'FOSMessageBundle' + )) + ->add('body', LegacyFormHelper::getType('Symfony\Component\Form\Extension\Core\Type\TextareaType'), array( + 'label' => 'body', + 'translation_domain' => 'FOSMessageBundle' + )); } - public function getName() + /** + * {@inheritDoc} + */ + public function getBlockPrefix() { return 'fos_message_new_multiperson_thread'; } + + /** + * @deprecated To remove when supporting only Symfony 3 + */ + public function getName() + { + return $this->getBlockPrefix(); + } } diff --git a/FormType/RecipientsType.php b/FormType/RecipientsType.php index d8cc7090..660f8822 100644 --- a/FormType/RecipientsType.php +++ b/FormType/RecipientsType.php @@ -1,9 +1,11 @@ setDefaults(array( 'invalid_message' => 'The selected recipient does not exist', )); } + public function setDefaultOptions(OptionsResolverInterface $resolver) + { + $this->configureOptions($resolver); + } + /** * {@inheritDoc} */ - public function getParent() + public function getBlockPrefix() { - return 'text'; + return 'recipients_selector'; } /** * {@inheritDoc} */ + public function getParent() + { + return LegacyFormHelper::getType('Symfony\Component\Form\Extension\Core\Type\TextType'); + } + + /** + * @deprecated To remove when supporting only Symfony 3 + */ public function getName() { - return 'recipients_selector'; + return $this->getBlockPrefix(); } } diff --git a/FormType/ReplyMessageFormType.php b/FormType/ReplyMessageFormType.php index c2780ba4..e0bd467a 100644 --- a/FormType/ReplyMessageFormType.php +++ b/FormType/ReplyMessageFormType.php @@ -2,8 +2,10 @@ namespace FOS\MessageBundle\FormType; +use FOS\MessageBundle\Util\LegacyFormHelper; use Symfony\Component\Form\AbstractType; use Symfony\Component\Form\FormBuilderInterface; +use Symfony\Component\OptionsResolver\OptionsResolver; use Symfony\Component\OptionsResolver\OptionsResolverInterface; /** @@ -16,18 +18,40 @@ class ReplyMessageFormType extends AbstractType public function buildForm(FormBuilderInterface $builder, array $options) { $builder - ->add('body', 'textarea', array('label' => 'body', 'translation_domain' => 'FOSMessageBundle')); + ->add('body', LegacyFormHelper::getType('Symfony\Component\Form\Extension\Core\Type\TextareaType'), array( + 'label' => 'body', + 'translation_domain' => 'FOSMessageBundle' + )); } - public function setDefaultOptions(OptionsResolverInterface $resolver) + public function configureOptions(OptionsResolver $resolver) { $resolver->setDefaults(array( 'intention' => 'reply', )); } - public function getName() + /** + * {@inheritDoc} + */ + public function getBlockPrefix() { return 'fos_message_reply_message'; } + + /** + * @deprecated To remove when supporting only Symfony 3 + */ + public function setDefaultOptions(OptionsResolverInterface $resolver) + { + $this->configureOptions($resolver); + } + + /** + * @deprecated To remove when supporting only Symfony 3 + */ + public function getName() + { + return $this->getBlockPrefix(); + } } diff --git a/Model/MessageMetadata.php b/Model/MessageMetadata.php index 39b27871..03261d39 100644 --- a/Model/MessageMetadata.php +++ b/Model/MessageMetadata.php @@ -15,16 +15,13 @@ public function getParticipant() return $this->participant; } - /** - * @param ParticipantInterface $participant - */ public function setParticipant(ParticipantInterface $participant) { $this->participant = $participant; } /** - * @return boolean + * @return bool */ public function getIsRead() { @@ -32,10 +29,10 @@ public function getIsRead() } /** - * @param boolean $isRead + * @param bool $isRead */ public function setIsRead($isRead) { - $this->isRead = (boolean)$isRead; + $this->isRead = (bool)$isRead; } } diff --git a/Model/ParticipantInterface.php b/Model/ParticipantInterface.php index 40222450..3e894a44 100644 --- a/Model/ParticipantInterface.php +++ b/Model/ParticipantInterface.php @@ -14,7 +14,7 @@ interface ParticipantInterface /** * Gets the unique identifier of the participant * - * @return string + * @return mixed */ public function getId(); } diff --git a/Model/ReadableInterface.php b/Model/ReadableInterface.php index 142839b5..2c1d4de4 100644 --- a/Model/ReadableInterface.php +++ b/Model/ReadableInterface.php @@ -15,7 +15,7 @@ public function isReadByParticipant(ParticipantInterface $participant); * Sets whether or not this participant has read this * * @param ParticipantInterface $participant - * @param boolean $isRead + * @param bool $isRead */ public function setIsReadByParticipant(ParticipantInterface $participant, $isRead); } diff --git a/Model/Thread.php b/Model/Thread.php index 7083f24b..241e7536 100644 --- a/Model/Thread.php +++ b/Model/Thread.php @@ -29,7 +29,7 @@ abstract class Thread implements ThreadInterface /** * Tells if the thread is spam or flood * - * @var boolean + * @var bool */ protected $isSpam = false; @@ -135,7 +135,7 @@ public function setSubject($subject) } /** - * @return boolean + * @return bool */ public function getIsSpam() { @@ -143,11 +143,11 @@ public function getIsSpam() } /** - * @param boolean + * @param bool */ public function setIsSpam($isSpam) { - $this->isSpam = (boolean) $isSpam; + $this->isSpam = (bool) $isSpam; } /** diff --git a/Model/ThreadInterface.php b/Model/ThreadInterface.php index 181e928c..cf1f28fb 100644 --- a/Model/ThreadInterface.php +++ b/Model/ThreadInterface.php @@ -19,7 +19,7 @@ public function getId(); public function getSubject(); /** - * @param string + * @param string * @return null */ public function setSubject($subject); @@ -27,28 +27,26 @@ public function setSubject($subject); /** * Gets the messages contained in the thread * - * @return Collection of MessageInterface + * @return MessageInterface[]|Collection */ public function getMessages(); /** * Adds a new message to the thread - * - * @param MessageInterface $message */ public function addMessage(MessageInterface $message); /** * Gets the first message of the thread * - * @return MessageInterface the first message + * @return MessageInterface */ public function getFirstMessage(); /** * Gets the last message of the thread * - * @return MessageInterface the last message + * @return MessageInterface */ public function getLastMessage(); @@ -63,8 +61,6 @@ public function getCreatedBy(); /** * Sets the participant that created the thread * Generally the sender of the first message - * - * @param ParticipantInterface */ public function setCreatedBy(ParticipantInterface $participant); @@ -79,15 +75,13 @@ public function getCreatedAt(); /** * Sets the date this thread was created at * Generally the date of the first message - * - * @param \DateTime $createdAt */ public function setCreatedAt(\DateTime $createdAt); /** * Gets the users participating in this conversation * - * @return ParticipantInterface[] + * @return ParticipantInterface[]|Collection */ public function getParticipants(); @@ -95,16 +89,13 @@ public function getParticipants(); * Tells if the user participates to the conversation * * @param ParticipantInterface $participant - * @return boolean + * @return bool */ public function isParticipant(ParticipantInterface $participant); /** * Adds a participant to the thread * If it already exists, nothing is done. - * - * @param ParticipantInterface $participant - * @return null */ public function addParticipant(ParticipantInterface $participant); @@ -119,14 +110,14 @@ public function isDeletedByParticipant(ParticipantInterface $participant); * Sets whether or not this participant has deleted this thread * * @param ParticipantInterface $participant - * @param boolean $isDeleted + * @param bool $isDeleted */ public function setIsDeletedByParticipant(ParticipantInterface $participant, $isDeleted); /** * Sets the thread as deleted or not deleted for all participants * - * @param boolean $isDeleted + * @param bool $isDeleted */ public function setIsDeleted($isDeleted); diff --git a/Model/ThreadMetadata.php b/Model/ThreadMetadata.php index f988db8a..9c944d69 100644 --- a/Model/ThreadMetadata.php +++ b/Model/ThreadMetadata.php @@ -29,16 +29,13 @@ public function getParticipant() return $this->participant; } - /** - * @param ParticipantInterface - */ public function setParticipant(ParticipantInterface $participant) { $this->participant = $participant; } /** - * @return boolean + * @return bool */ public function getIsDeleted() { @@ -46,11 +43,11 @@ public function getIsDeleted() } /** - * @param boolean $isDeleted + * @param bool $isDeleted */ public function setIsDeleted($isDeleted) { - $this->isDeleted = (boolean)$isDeleted; + $this->isDeleted = (bool)$isDeleted; } /** @@ -61,9 +58,6 @@ public function getLastParticipantMessageDate() return $this->lastParticipantMessageDate; } - /** - * @param \DateTime $date - */ public function setLastParticipantMessageDate(\DateTime $date) { $this->lastParticipantMessageDate = $date; @@ -77,9 +71,6 @@ public function getLastMessageDate() return $this->lastMessageDate; } - /** - * @param \DateTime $date - */ public function setLastMessageDate(\DateTime $date) { $this->lastMessageDate = $date; diff --git a/ModelManager/MessageManagerInterface.php b/ModelManager/MessageManagerInterface.php index 072b0ceb..7210bcfc 100644 --- a/ModelManager/MessageManagerInterface.php +++ b/ModelManager/MessageManagerInterface.php @@ -34,7 +34,7 @@ public function createMessage(); * Saves a message * * @param MessageInterface $message - * @param Boolean $andFlush Whether to flush the changes (default true) + * @param bool $andFlush Whether to flush the changes (default true) */ public function saveMessage(MessageInterface $message, $andFlush = true); diff --git a/ModelManager/ThreadManagerInterface.php b/ModelManager/ThreadManagerInterface.php index 17e848d5..f39e02be 100644 --- a/ModelManager/ThreadManagerInterface.php +++ b/ModelManager/ThreadManagerInterface.php @@ -125,7 +125,7 @@ public function createThread(); * Saves a thread * * @param ThreadInterface $thread - * @param Boolean $andFlush Whether to flush the changes (default true) + * @param bool $andFlush Whether to flush the changes (default true) */ public function saveThread(ThreadInterface $thread, $andFlush = true); diff --git a/Provider/Provider.php b/Provider/Provider.php index 56287583..54f1fbc4 100644 --- a/Provider/Provider.php +++ b/Provider/Provider.php @@ -3,7 +3,6 @@ namespace FOS\MessageBundle\Provider; use FOS\MessageBundle\Model\ParticipantInterface; -use FOS\MessageBundle\Model\ThreadInterface; use Symfony\Component\HttpKernel\Exception\NotFoundHttpException; use Symfony\Component\Security\Core\Exception\AccessDeniedException; use FOS\MessageBundle\ModelManager\ThreadManagerInterface; diff --git a/README.md b/README.md index e171fef3..f373d7a5 100644 --- a/README.md +++ b/README.md @@ -1,13 +1,7 @@ FOSMessageBundle ================ -> A maintainer has been found for this bundle but a new version is being rewritten from scratch. -> This version (1.2) is maintained for bugs and issues but no features will be added. If you need more -> features, don't hesitate to propose them in the library. -> -> [Read more in the new library repository](https://github.com/FriendsOfSymfony/FOSMessage) - -This bundle provides messaging features for a Symfony2 application. Features available include: +This bundle provides messaging features for a Symfony application. Features available include: - Support for both the Doctrine ORM and ODM for message storage - Threaded conversations diff --git a/Reader/ReaderInterface.php b/Reader/ReaderInterface.php index ad1acdb2..0319ffc7 100644 --- a/Reader/ReaderInterface.php +++ b/Reader/ReaderInterface.php @@ -5,23 +5,19 @@ use FOS\MessageBundle\Model\ReadableInterface; /** - * Marks messages and threads as read or unread + * Marks messages and threads as read or unread. * * @author Thibault Duplessis */ interface ReaderInterface { /** - * Marks the readable as read by the current authenticated user - * - * @param ReadableInterface $readable + * Marks the readable as read by the current authenticated user. */ public function markAsRead(ReadableInterface $readable); /** - * Marks the readable as unread by the current authenticated user - * - * @param ReadableInterface $readable + * Marks the readable as unread by the current authenticated user. */ public function markAsUnread(ReadableInterface $readable); } diff --git a/Resources/config/config.xml b/Resources/config/config.xml index 89291466..8734dd5a 100644 --- a/Resources/config/config.xml +++ b/Resources/config/config.xml @@ -18,7 +18,7 @@ - + @@ -58,8 +58,8 @@ - - + + diff --git a/Resources/config/form.xml b/Resources/config/form.xml index 45524a66..ed532f0c 100644 --- a/Resources/config/form.xml +++ b/Resources/config/form.xml @@ -26,22 +26,22 @@ %fos_message.reply_form.model% - - + + - - + + - - + + diff --git a/Resources/config/routing.xml b/Resources/config/routing.xml index d4329c05..965840e0 100644 --- a/Resources/config/routing.xml +++ b/Resources/config/routing.xml @@ -4,37 +4,35 @@ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://symfony.com/schema/routing http://symfony.com/schema/routing/routing-1.0.xsd"> - + FOSMessageBundle:Message:inbox - + FOSMessageBundle:Message:sent - + FOSMessageBundle:Message:deleted - + FOSMessageBundle:Message:search - + FOSMessageBundle:Message:newThread - + FOSMessageBundle:Message:delete - POST|DELETE - + FOSMessageBundle:Message:undelete - POST - + FOSMessageBundle:Message:thread diff --git a/Resources/config/spam_detection.xml b/Resources/config/spam_detection.xml index 8e0e27d2..e1edd393 100644 --- a/Resources/config/spam_detection.xml +++ b/Resources/config/spam_detection.xml @@ -8,7 +8,7 @@ - + diff --git a/Resources/config/validator.xml b/Resources/config/validator.xml index a7f111fb..4126a42c 100644 --- a/Resources/config/validator.xml +++ b/Resources/config/validator.xml @@ -17,7 +17,7 @@ - + diff --git a/Resources/doc/99-config-reference.md b/Resources/doc/99-config-reference.md index 3b2dd2d4..d85a58dd 100644 --- a/Resources/doc/99-config-reference.md +++ b/Resources/doc/99-config-reference.md @@ -29,12 +29,12 @@ fos_message: query_parameter: 'q' # Request query parameter containing the term new_thread_form: factory: fos_message.new_thread_form.factory # See FormFactory\NewThreadMessageFormFactory - type: fos_message.new_thread_form.type # See FormType\NewThreadMessageFormType + type: FOS\MessageBundle\FormType\NewThreadMessageFormType handler: fos_message.new_thread_form.handler # See FormHandler\NewThreadMessageFormHandler name: message reply_form: factory: fos_message.reply_form.factory # See FormFactory\ReplyMessageFormFactory - type: fos_message.reply_form.type # See FormType\ReplyMessageFormType + type: FOS\MessageBundle\FormType\ReplyMessageFormType handler: fos_message.reply_form.handler # See FormHandler\ReplyMessageFormHandler name: message ``` diff --git a/Resources/doc/99-using-other-user-bundles.md b/Resources/doc/99-using-other-user-bundles.md index 157fb111..206dc925 100644 --- a/Resources/doc/99-using-other-user-bundles.md +++ b/Resources/doc/99-using-other-user-bundles.md @@ -150,8 +150,7 @@ You can copy and paste the bundle versions into your application and define them - + %fos_message.new_thread_form.name% diff --git a/Search/QueryFactory.php b/Search/QueryFactory.php index 70e801a3..a90b81b3 100644 --- a/Search/QueryFactory.php +++ b/Search/QueryFactory.php @@ -3,19 +3,17 @@ namespace FOS\MessageBundle\Search; use Symfony\Component\HttpFoundation\Request; +use Symfony\Component\HttpFoundation\RequestStack; /** * Gets the search term from the request and prepares it */ class QueryFactory implements QueryFactoryInterface { - /** - * @var Request - */ protected $request; /** - * the query parameter containing the search term + * The query parameter containing the search term * * @var string */ @@ -24,12 +22,12 @@ class QueryFactory implements QueryFactoryInterface /** * Instanciates a new TermGetter * - * @param Request $request + * @param RequestStack|Request $requestStack * @param string $queryParameter */ - public function __construct(Request $request, $queryParameter) + public function __construct($requestStack, $queryParameter) { - $this->request = $request; + $this->request = $requestStack; $this->queryParameter = $queryParameter; } @@ -38,7 +36,7 @@ public function __construct(Request $request, $queryParameter) */ public function createFromRequest() { - $original = $this->request->query->get($this->queryParameter); + $original = $this->getCurrentRequest()->query->get($this->queryParameter); $original = trim($original); $escaped = $this->escapeTerm($original); @@ -60,4 +58,17 @@ protected function escapeTerm($term) { return $term; } + + /** + * BC layer to retrieve the current request directly or from a stack. + * + * @return null|Request + */ + private function getCurrentRequest() { + if ($this->request instanceof Request) { + return $this->request; + } + + return $this->request->getCurrentRequest(); + } } diff --git a/Security/AuthorizerInterface.php b/Security/AuthorizerInterface.php index a922efd4..c8fc0052 100644 --- a/Security/AuthorizerInterface.php +++ b/Security/AuthorizerInterface.php @@ -17,7 +17,7 @@ interface AuthorizerInterface * to see this thread * * @param ThreadInterface $thread - * @return boolean + * @return bool */ public function canSeeThread(ThreadInterface $thread); @@ -26,7 +26,7 @@ public function canSeeThread(ThreadInterface $thread); * to delete this thread * * @param ThreadInterface $thread - * @return boolean + * @return bool */ public function canDeleteThread(ThreadInterface $thread); @@ -35,7 +35,7 @@ public function canDeleteThread(ThreadInterface $thread); * to send a message to this other participant * * @param ParticipantInterface $participant the one we want to send a message to - * @return boolean + * @return bool */ public function canMessageParticipant(ParticipantInterface $participant); } diff --git a/Security/ParticipantProvider.php b/Security/ParticipantProvider.php index 0fbc89d4..0c300fe0 100644 --- a/Security/ParticipantProvider.php +++ b/Security/ParticipantProvider.php @@ -3,6 +3,7 @@ namespace FOS\MessageBundle\Security; use Symfony\Component\Security\Core\SecurityContextInterface; +use Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorageInterface; use Symfony\Component\Security\Core\Exception\AccessDeniedException; use FOS\MessageBundle\Model\ParticipantInterface; @@ -14,12 +15,21 @@ class ParticipantProvider implements ParticipantProviderInterface { /** - * @var SecurityContextInterface + * @var SecurityContextInterface|TokenStorageInterface */ protected $securityContext; - public function __construct(SecurityContextInterface $securityContext) + public function __construct($securityContext) { + if (!$securityContext instanceof SecurityContextInterface && !$securityContext instanceof TokenStorageInterface) { + throw new \InvalidArgumentException(sprintf( + 'Argument 1 passed to ParticipantProvider::__construct is not valid (instance of %s or %s expected, %s given)', + 'Symfony\Component\Security\Core\SecurityContextInterface', + 'Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorageInterface', + is_object($securityContext) ? get_class($securityContext) : gettype($securityContext) + )); + } + $this->securityContext = $securityContext; } diff --git a/Sender/SenderInterface.php b/Sender/SenderInterface.php index c038ebdb..69e91e69 100644 --- a/Sender/SenderInterface.php +++ b/Sender/SenderInterface.php @@ -12,9 +12,7 @@ interface SenderInterface { /** - * Sends the message - * - * @param MessageInterface $message + * Sends the given message. */ public function send(MessageInterface $message); } diff --git a/SpamDetection/SpamDetectorInterface.php b/SpamDetection/SpamDetectorInterface.php index cfa38a14..72b2b9e3 100644 --- a/SpamDetection/SpamDetectorInterface.php +++ b/SpamDetection/SpamDetectorInterface.php @@ -15,7 +15,7 @@ interface SpamDetectorInterface * Tells whether or not a new message looks like spam * * @param NewThreadMessage $message - * @return boolean true if it is spam, false otherwise + * @return bool true if it is spam, false otherwise */ public function isSpam(NewThreadMessage $message); } diff --git a/Twig/Extension/MessageExtension.php b/Twig/Extension/MessageExtension.php index 84cdbc5e..4e197ce4 100644 --- a/Twig/Extension/MessageExtension.php +++ b/Twig/Extension/MessageExtension.php @@ -40,7 +40,7 @@ public function getFunctions() /** * Tells if this readable (thread or message) is read by the current user * - * @return boolean + * @return bool */ public function isRead(ReadableInterface $readable) { @@ -53,7 +53,7 @@ public function isRead(ReadableInterface $readable) * * @param ThreadInterface $thread * - * @return boolean true if participant can mark a thread as deleted, false otherwise + * @return bool true if participant can mark a thread as deleted, false otherwise */ public function canDeleteThread(ThreadInterface $thread) { @@ -65,7 +65,7 @@ public function canDeleteThread(ThreadInterface $thread) * * @param ThreadInterface $thread * - * @return boolean true if participant has marked the thread as deleted, false otherwise + * @return bool true if participant has marked the thread as deleted, false otherwise */ public function isThreadDeletedByParticipant(ThreadInterface $thread) { diff --git a/UPGRADING.md b/UPGRADING.md new file mode 100644 index 00000000..74a9257a --- /dev/null +++ b/UPGRADING.md @@ -0,0 +1,36 @@ +Upgrade from 1.2 to 1.3 +======================= + +The 1.3 version added the support for Symfony 3.0+. Several changes were made for the code to work with the new version. + + * **BC break**: `Controller\MessageController` now implements `Symfony\Component\DependencyInjection\ContainerAwareInterface` + instead of extending the abstract class `Symfony\Component\DependencyInjection\ContainerAware` (removed in Symfony 3.0). + If you relied on this (for instance by using `MessageController instanceof ContainerAware`), you may have to change + your code. + + * Form types are now classes names instead of service references (the usage of service references is therefore deprecated). + If you used your own form types for new threads and replies, you should update your configuration: + + Before: + + ```yaml + fos_message: + # ... + + new_thread_form: + type: app.custom_new_thread_form_service + reply_form: + type: app.custom_reply_form_service + ``` + + After: + + ```yaml + fos_message: + # ... + + new_thread_form: + type: AppBundle\Form\Type\NewThreadFormType + reply_form: + type: AppBundle\Form\Type\ReplyFormType + ``` diff --git a/Util/LegacyFormHelper.php b/Util/LegacyFormHelper.php new file mode 100644 index 00000000..a0ffc332 --- /dev/null +++ b/Util/LegacyFormHelper.php @@ -0,0 +1,47 @@ + + */ +final class LegacyFormHelper +{ + private static $map = array( + 'FOS\UserBundle\Form\Type\UsernameFormType' => 'fos_user_username', + 'FOS\MessageBundle\FormType\RecipientsType' => 'recipients_selector', + 'Symfony\Component\Form\Extension\Core\Type\EmailType' => 'email', + 'Symfony\Component\Form\Extension\Core\Type\PasswordType' => 'password', + 'Symfony\Component\Form\Extension\Core\Type\RepeatedType' => 'repeated', + 'Symfony\Component\Form\Extension\Core\Type\TextType' => 'text', + 'Symfony\Component\Form\Extension\Core\Type\TextareaType' => 'textarea', + ); + + public static function getType($class) + { + if (!self::isLegacy()) { + return $class; + } + + if (!isset(self::$map[$class])) { + throw new \InvalidArgumentException(sprintf('Form type with class "%s" can not be found. Please check for typos or add it to the map in LegacyFormHelper', $class)); + } + + return self::$map[$class]; + } + + public static function isLegacy() + { + return !method_exists('Symfony\Component\Form\AbstractType', 'getBlockPrefix'); + } + + private function __construct() + { + } + + private function __clone() + { + } +} diff --git a/composer.json b/composer.json index 2f088c19..5b172aeb 100644 --- a/composer.json +++ b/composer.json @@ -1,7 +1,7 @@ { "name": "friendsofsymfony/message-bundle", "type": "symfony-bundle", - "description": "Provides user-to-user messaging features for your Symfony2 application.", + "description": "Provides user-to-user messaging features for your Symfony application.", "keywords": ["symfony", "message", "messaging"], "homepage": "https://github.com/FriendsOfSymfony/FOSMessageBundle", "license": "MIT", @@ -18,10 +18,14 @@ ], "require": { "php": ">=5.3.2", - "symfony/form": "~2.1", - "symfony/framework-bundle": "~2.1", - "symfony/security": "~2.1", - "symfony/twig-bundle": "~2.1" + "doctrine/collections": "^1.3", + "symfony/form": "^2.7|^3.0", + "symfony/framework-bundle": "^2.7|^3.0", + "symfony/security": "^2.7|^3.0", + "symfony/twig-bundle": "^2.7|^3.0" + }, + "require-dev": { + "symfony/phpunit-bridge": "^3.0" }, "suggest": { "doctrine/doctrine-bundle": "dev-master",