Skip to content

Conversation

putzwasser
Copy link
Contributor

Q A
Bug fix? (use the a.b branch) 🟢 (more or less)
New feature/enhancement? (use the a.x branch) 🔴
Deprecations? 🔴
BC breaks? (use the c.x branch) 🔴
Automated tests included? 🟢
Related user documentation PR URL mautic/user-documentation#...
Related developer documentation PR URL mautic/developer-documentation-new#...
Issue(s) addressed Fixes #...

Description

This adds the missing return type hint for LeadEvent::getLead. This also adds a basic unit test for LeadEvent.


📋 Steps to test this PR:

  1. Open this PR on Gitpod or pull down for testing locally (see docs on testing PRs here)
  2. run composer run test app/bundles/LeadBundle/Tests/Event/LeadEventTest.php to run the new unit test.
  3. Besides that: Nothing changed or broke.

This adds the missing return type hint for `LeadEvent::getLead`. This also adds a simple unit test for `LeadEvent`
Copy link

codecov bot commented Jun 15, 2024

Codecov Report

All modified and coverable lines are covered by tests ✅

Project coverage is 64.54%. Comparing base (dadad05) to head (1d5855f).
Report is 1 commits behind head on 6.x.

Additional details and impacted files

Impacted file tree graph

@@            Coverage Diff            @@
##                6.x   #13842   +/-   ##
=========================================
  Coverage     64.54%   64.54%           
  Complexity    34613    34613           
=========================================
  Files          2271     2271           
  Lines        103440   103440           
=========================================
  Hits          66766    66766           
  Misses        36674    36674           
Files with missing lines Coverage Δ
app/bundles/LeadBundle/Event/LeadEvent.php 71.42% <100.00%> (ø)
...undles/LeadBundle/EventListener/LeadSubscriber.php 73.59% <ø> (ø)
...es/LeadBundle/Helper/LeadChangeEventDispatcher.php 100.00% <ø> (ø)

Copy link
Member

@escopecz escopecz left a comment

Choose a reason for hiding this comment

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

Unfortunately, changing method signature is considered a BC break so this would have to wait for Mautic 6.

But when we are in improving this class, is there any reason for &$lead? Can we drop it? How about to use Constructor Property Promotion? Do the comment add any value? Can the class be final?

@escopecz escopecz added this to the 6.0 milestone Jun 18, 2024
@escopecz escopecz added bc-break A BC break PR for major release milestones only refactoring The change does not change behavior but improves the code pending-feedback PR's and issues that are awaiting feedback from the author labels Jun 18, 2024
@putzwasser
Copy link
Contributor Author

putzwasser commented Jun 18, 2024

Unfortunately, changing method signature is considered a BC break so this would have to wait for Mautic 6.

I see the point you're making, but I don't really understand your conclusion for this particular case.

  1. The docstring already hinted the return type.
  2. There is no other way than using LeadEvent with Lead for $lead as you can only instantiate a new object with a Lead entity and use the setter with a Lead entity.

The way I see that is that all this does is making something explicit that was already there (and enforced in other parts). From my understanding nothing can break because of this change.

I don't want to argue—I'm genuinely interested.

But when we are in improving this class, is there any reason for &$lead? Can we drop it? […]

I have no idea. 😅

Edit: I guess, this was necessary as $lead might get changed outside the event and, thus, the event listeners? It probably is necessary to keep the object in sync?

Can the class be final?

Why would that be preferable? Couldn't have a plugin or custom integration have the need to extend LeadEvent to pass more/custom data to the lead events?

What's the benefit for the Mautic core if this gets restricted?

How about to use Constructor Property Promotion?

Wasn't sure whether to include this. Did M5 drop support for PHP<v7 completely?

@escopecz
Copy link
Member

The thing is that all classes should be final by default unless there is a reason not to. For DTO classes like events there is no good reason to extend them. Even in the tests it's easier to use the DTO class rather than mock it. If we'd keep this rule from the beginning, we wouldn't have this BC break to worry about.

Imagine that some plugin is extending this class because we allow it. Then can have their own implementation of the getLead() method in their class. If you add the return type, their plugin will be broken. It's a BC break.

It seems that in this case we cannot use Constructor Property Promotion because the properties are defined in the parent class as the failing tests suggest. Another reason why composition is better than inheritance.

I guess, this was necessary as $lead might get changed outside the event and, thus, the event listeners? It probably is necessary to keep the object in sync?

Objects are always passed as a reference. This would make sense if it would be an array for example, but I don't see any reason for it as an object. The setLead() method doesn't seem to be called anywhere so even overwriting one Lead object with another isn't a suitable use case here. But it's another possible BC break.

Let me know if you have more questions

@putzwasser
Copy link
Contributor Author

Thanks for your explanations.

Imagine that some plugin is extending this class because we allow it. Then can have their own implementation of the getLead() method in their class. If you add the return type, their plugin will be broken. It's a BC break.

The code documents that the return type should be a Lead object. If someone deviates from the core I'd say it's their fault if they get hit by a change like this. For anyone using/extending the class like it is intended this isn't a BC1.

Am I mistaken, here?

What I mean by extending the class is that a plugin might add another method to use this event to transport additional data. This wouldn't be possible if the class is final. This could make it harder to leverage the LeadEvents for a plugin.

So, by extending I don't mean to override existing methods in a way that one completely deviates from the core (even though this is possible).

Footnotes

  1. I probably have a different (and more lax?) understanding of a BC. Everything in the code shouts that you're working with a Lead object here. This change makes it even more obvious/enforces it. I guess, this is a I use a hammer when I should use screwdriver type of situation.

@escopecz
Copy link
Member

The code documents that the return type should be a Lead object. If someone deviates from the core I'd say it's their fault if they get hit by a change like this. For anyone using/extending the class like it is intended this isn't a BC

Well, try to do that. If the method in the parent class has a return type and the method in the child class does not then you get an error. That's what this BC change is about. Not that some plugin could expect some other object than Lead.

What I mean by extending the class is that a plugin might add another method to use this event to transport additional data. This wouldn't be possible if the class is final. This could make it harder to leverage the LeadEvents for a plugin.

Why would anyone extend the event class? When the event is dispatched in the core then a new instance of the event class is created. If you extend it, how would you enforce your event class being dispatched instead of the original?

Ideally, the event class should be unique to each event being dispatched. This way we could throw away the event keys and dispatch just the event objects. That is how it's recommended in the newer Symfony versions.

So I still don't see any good use case why the event classes should not be final.

@andersonjeccel andersonjeccel added the T2 Medium difficulty to fix (issue) or test (PR) label Jun 21, 2024
@RCheesley
Copy link
Member

Hi folks, do you think we could wrap this up over the next weeks so we can merge it in 6.0 alpha?

@RCheesley RCheesley modified the milestones: 6.0.0-alpha, 6.0.0-beta Jan 27, 2025
@RCheesley
Copy link
Member

Hi @putzwasser another one here which is currently tagged for 6.0 - if we can't get it ready by then it'll have to be pushed back to 7.0 (alpha this quarter, but the General Availability release isn't until Q4).

@RCheesley
Copy link
Member

Bumping to Release Candidate due to need for rebase.

@RCheesley RCheesley modified the milestones: 6.0.0-beta, 6.0.0-RC Feb 21, 2025
@escopecz escopecz changed the base branch from 5.1 to 6.x February 26, 2025 14:06
@escopecz escopecz self-requested a review February 26, 2025 14:09
@escopecz escopecz removed this from the 6.0.0-RC milestone Feb 26, 2025
@escopecz escopecz added this to the 6.0.0-beta milestone Feb 26, 2025
@escopecz escopecz added ready-to-commit PR's with 2 successful tests, 1 approval, automated tests and docs and is ready to be merged and removed pending-feedback PR's and issues that are awaiting feedback from the author labels Feb 26, 2025
Copy link
Member

@escopecz escopecz left a comment

Choose a reason for hiding this comment

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

Rebased and improved 👍

Copy link
Member

@patrykgruszka patrykgruszka left a comment

Choose a reason for hiding this comment

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

Code changes look fine 👍

@RCheesley RCheesley merged commit 5a4e860 into mautic:6.x Feb 26, 2025
17 checks passed
@RCheesley RCheesley modified the milestones: 6.0.0-beta, 6.0.0-beta2 Mar 5, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bc-break A BC break PR for major release milestones only ready-to-commit PR's with 2 successful tests, 1 approval, automated tests and docs and is ready to be merged refactoring The change does not change behavior but improves the code T2 Medium difficulty to fix (issue) or test (PR)
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants