Skip to content

[Notifier] Inject Mailer instead of service locator for FakeSms and FakeChat #40739

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Apr 12, 2021

Conversation

OskarStark
Copy link
Contributor

@OskarStark OskarStark commented Apr 8, 2021

Q A
Branch? 5.x
Bug fix? yes
New feature? no
Deprecations? no
Tickets Fixes #40731
License MIT
Doc PR symfony/symfony-docs#15206
Recipe PR symfony/recipes#930

Until now the locator was not injected and therefore not working.

We decided to make the transport name configurable instead of the service_id.

How is it working?

Todos

  • add tests
  • test in a real project

@@ -2417,6 +2417,16 @@ private function registerNotifierConfiguration(array $config, ContainerBuilder $
$container->removeDefinition($classToServices[MercureTransportFactory::class]);
}

if (ContainerBuilder::willBeAvailable('symfony/fake-chat-notifier', FakeChatTransportFactory::class, array_merge($parentPackages, ['symfony/mailer']))) {
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not sure this line is correct 🤔

I only want to run this code if fake-chat-notifier with FakeChatTransportFactory::class and symfony/mailer is installed. Am I using willBeAvailable method correct?

Friendly ping @stof

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The part I'm not sure is the array_merge. I don't remember whether passing multiple parent packages requires all of them or at least one of them. /cc @nicolas-grekas

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Regarding this code:

/**
* Checks whether a class is available and will remain available in the "no-dev" mode of Composer.
*
* When parent packages are provided and if any of them is in dev-only mode,
* the class will be considered available even if it is also in dev-only mode.
*/
final public static function willBeAvailable(string $package, string $class, array $parentPackages): bool
{
if (!class_exists($class) && !interface_exists($class, false) && !trait_exists($class, false)) {
return false;
}
if (!class_exists(InstalledVersions::class) || !InstalledVersions::isInstalled($package) || InstalledVersions::isInstalled($package, false)) {
return true;
}
// the package is installed but in dev-mode only, check if this applies to one of the parent packages too
$rootPackage = InstalledVersions::getRootPackage()['name'] ?? '';
foreach ($parentPackages as $parentPackage) {
if ($rootPackage === $parentPackage || (InstalledVersions::isInstalled($parentPackage) && !InstalledVersions::isInstalled($parentPackage, false))) {
return true;
}
}
return false;
}

I would say it just checks if at least one of them is available 🤔

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

meaning that if you want to ensure that several parent packages are all installed, you should do that as ContainerBuilder::willBeAvailable(..., $parent1) && ContainerBuilder::willBeAvailable(..., $parent2) 😄

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, but in this case I am wondering if the previous used one by mercure is working as expected and needs to do the call twice too 🤔

cc @mtarld

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes indeed, the call is done twice for mercure

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes but you are using $parentPackages, but I think you need to achieve, that both, notifier and framework-bundle need to be available, right? But this would not work.

To be more clear, I think we need to change your code to:

diff --git a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php
index 4d4749a2f1..f36702d254 100644
--- a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php
+++ b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php
@@ -2410,10 +2410,16 @@ class FrameworkExtension extends Extension
             }
         }

-        if (ContainerBuilder::willBeAvailable('symfony/mercure-notifier', MercureTransportFactory::class, $parentPackages) && ContainerBuilder::willBeAvailable('symfony/mercure-bundle', MercureBundle::class, $parentPackages)) {
+        if (ContainerBuilder::willBeAvailable('symfony/mercure-notifier', MercureTransportFactory::class, ['symfony/framework-bundle'])
+            && ContainerBuilder::willBeAvailable('symfony/mercure-notifier', MercureTransportFactory::class, ['symfony/notifier'])
+            && ContainerBuilder::willBeAvailable('symfony/mercure-bundle', MercureBundle::class, ['symfony/framework-bundle'])
+            && ContainerBuilder::willBeAvailable('symfony/mercure-bundle', MercureBundle::class, ['symfony/notifier'])
+        ) {
             $container->getDefinition($classToServices[MercureTransportFactory::class])
                 ->replaceArgument('$registry', new Reference(HubRegistry::class));
-        } elseif (ContainerBuilder::willBeAvailable('symfony/mercure-notifier', MercureTransportFactory::class, $parentPackages)) {
+        } elseif (ContainerBuilder::willBeAvailable('symfony/mercure-notifier', MercureTransportFactory::class, ['symfony/framework-bundle'])
+            && ContainerBuilder::willBeAvailable('symfony/mercure-notifier', MercureTransportFactory::class, ['symfony/notifier'])
+        ) {
             $container->removeDefinition($classToServices[MercureTransportFactory::class]);
:

if yes maybe it makes sense to either extend the willBeAvailable method to a 4th parameter bool $all = false or create a allWillBeAvailable and deprecated $parentPackages to be an array in willBeAvailable method.

cc @nicolas-grekas

PS: I am unsure because I use this method the first time 😸

@OskarStark
Copy link
Contributor Author

@Nyholm any idea what's wrong here?
CleanShot 2021-04-09 at 09 47 24

@OskarStark OskarStark force-pushed the fix/service-id branch 2 times, most recently from 035a59e to 3c6a2ef Compare April 9, 2021 10:58
@OskarStark
Copy link
Contributor Author

I tested this in my project with the following command:

<?php

declare(strict_types=1);

namespace App\Command;

use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;
use Symfony\Component\Notifier\ChatterInterface;
use Symfony\Component\Notifier\Message\ChatMessage;
use Symfony\Component\Notifier\Message\SmsMessage;
use Symfony\Component\Notifier\Tests\Fixtures\TestOptions;
use Symfony\Component\Notifier\TexterInterface;

final class TestFakeBridgesCommand extends Command
{
    protected static $defaultName = 'test:fake-bridges';

    public function __construct(
        private ChatterInterface $chatter,
        private TexterInterface $texter,
    ) {
        parent::__construct();
    }

    protected function configure(): void
    {
        $this
            ->setDescription('Test FakeSms and FakeChat bridge');
    }

    protected function execute(InputInterface $input, OutputInterface $output): int
    {
        // SMS
        $message = new SmsMessage('1234567', 'Hi Symfony');
        $this->texter->send($message);

        // ChatMessage without recipient
        $message = new ChatMessage('Hi Symfony!');
        $this->chatter->send($message);

        // Chat Message with recipient
        $message = new ChatMessage('Hi Symfony!', new TestOptions(['recipient_id' => 'Oskar']));
        $this->chatter->send($message);

        return Command::SUCCESS;
    }
}

Results 👍

CleanShot 2021-04-09 at 13 11 27
CleanShot 2021-04-09 at 13 11 54
CleanShot 2021-04-09 at 13 12 23

@OskarStark OskarStark force-pushed the fix/service-id branch 2 times, most recently from 3fb8a3f to 7fcaed7 Compare April 9, 2021 11:15
@OskarStark OskarStark changed the title [Notifier] Fix service locator for fake-chat/sms [Notifier] Inject Mailer instead of service locator for FakeSms and FakeCha Apr 9, 2021
@OskarStark OskarStark requested review from chalasr and Nyholm April 9, 2021 11:16
* file that was distributed with this source code.
*/

namespace Symfony\Component\Notifier\Tests\Fixtures;
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Namespace correct?

/**
* @author Oskar Stark <oskarstark@googlemail.com>
*/
class DummyMailer implements MailerInterface
Copy link
Contributor Author

@OskarStark OskarStark Apr 9, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Or is there sth similar available? 🤔

Do you have a proposal for a better name?

@Nyholm
Copy link
Member

Nyholm commented Apr 9, 2021

Yes, you are missing .gitignore

Screenshot 2021-04-09 at 13 24 32

@OskarStark
Copy link
Contributor Author

Oh I overlooked this, thanks .gitignore added

@OskarStark OskarStark changed the title [Notifier] Inject Mailer instead of service locator for FakeSms and FakeCha [Notifier] Inject Mailer instead of service locator for FakeSms and FakeChat Apr 9, 2021
Copy link
Member

@chalasr chalasr left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks

@OskarStark OskarStark merged commit 9092d5b into symfony:5.x Apr 12, 2021
OskarStark added a commit to symfony/symfony-docs that referenced this pull request Apr 12, 2021
This PR was merged into the 5.3-dev branch.

Discussion
----------

[Notifier] [FakeSms] [FakeChat] Update DSN

Follows symfony/symfony#40739

Commits
-------

3833bba [Notifier] [FakeSms] [FakeChat] Update DSN
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Broken FakeSmsTransportFactory
6 participants