- Notifications
You must be signed in to change notification settings - Fork40
Make StandaloneExtensionManagers configurable#55
Uh oh!
There was an error while loading.Please reload this page.
Conversation
Xerkus commentedNov 10, 2017
👎 from me. Standalone extension manager should not be extended and docs should be corrected not to suggest that. |
Synchro commentedNov 10, 2017
Rationale? |
weierophinney commentedNov 13, 2017
Xerkus commentedNov 13, 2017
I still oppose extending the class. It have numerous downsides.
I see only two valid options here and none of them is to extend:
finalclass MyExtensionManagerimplements ExtensionManagerInterface{private$decoratedManager;private$extensions = ['Media\Entry' =MyApp\RSS\Media\Entry::class, ];publicfunction__construct(ExtensionManagerInterface$em) {$this->decoratedManager =$em; }/** * Do we have the extension? * * @param string $extension * @return bool */publicfunctionhas($extension) {return (array_key_exists($extension,$this->extensions) ||$this->decoratedManager->has($extension)); }/** * Retrieve the extension * * @param string $extension * @return mixed */publicfunctionget($extension) {if (array_key_exists($extension,$this->extensions)) {$class =$this->extensions[$extension];returnnew$class(); }return$this->decoratedManager->get($extension); }} And of course there is always configurable container implementation for more complex needs. |
Synchro commentedNov 14, 2017
All this seems to be massive overkill - something that calls itself a plugin manager singularly fails to do anything matching that description - needing to write a convoluted decorator at all smells like a workaround for an inflexible base class. If a provided extension manager doesn't manage extensions, what is it for? A simpler alternative to extend/decorate would be to add an "addExtension" method, so I could say: I'm using a framework because it helps me do things with less effort; I want to add oneextension, but I have zero interest in writing anextension manager - that's a role I would expect the framework to fulfil. |
Xerkus commentedNov 14, 2017
Extension manager is a contract established by the interface. Responsibility of the contract is to manage extensions for zend-feed, ie create, configure and provide. If you need flexible configurable extension manager, that role is filled by As I said in previous comment, I will support expanding standalone responsibilities by making it configurable. Feel free to open PR for that. |
| namespaceZend\Feed\Reader; | ||
| class StandaloneExtensionManagerimplements ExtensionManagerInterface | ||
| finalclass StandaloneExtensionManagerimplements ExtensionManagerInterface |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others.Learn more.
We can't make it final, it will require a major version bump as someone is quite likely already extending it.
Xerkus commentedNov 14, 2017
Can you also provide same change for Writer? |
Synchro commentedNov 14, 2017
OK. I've removed |
| * Remove an extension. | ||
| * | ||
| * @param string $name | ||
| * @return bool |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others.Learn more.
It does not need to report the result. It is idempotent operation. void would be fine
Synchro commentedNov 14, 2017
I've noticed that the code style of the extension list is quite different in each. In Reader: in Writer: They are consistent within themselves, but not with each other. It makes writing tests easier using the string style as I don't have to provide a mocked extension class - I know that older versions used the literal style, so I assume there's some history to that. I noticed that the Writer doesn't have a test file for this, so I'm adding one. |
Xerkus commentedNov 14, 2017 • edited
Loading Uh oh!
There was an error while loading.Please reload this page.
edited
Uh oh!
There was an error while loading.Please reload this page.
|
Synchro commentedNov 14, 2017
Hm. Looks like it fails to find classes using pseudoconstants:
I will switch back to strings. |
Synchro commentedNov 14, 2017
Uh, I could always just un-break the fully namespaced names... |
| 'Syndication\Feed' =>'Zend\Feed\Reader\Extension\Syndication\Feed', | ||
| 'Thread\Entry' =>'Zend\Feed\Reader\Extension\Thread\Entry', | ||
| 'WellFormedWeb\Entry' =>'Zend\Feed\Reader\Extension\WellFormedWeb\Entry', | ||
| 'Atom\Entry' =>Zend\Feed\Reader\Extension\Atom\Entry::class, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others.Learn more.
It is resolved to FQCN using normal rules.Extension\Atom\Entry::class will resolve properly toZend\Feed\Reader\Extension\Atom\Entry
Xerkus commentedNov 14, 2017 • edited
Loading Uh oh!
There was an error while loading.Please reload this page.
edited
Uh oh!
There was an error while loading.Please reload this page.
Can you also update docs? For this change only |
Synchro commentedNov 14, 2017
Fixing test data provider... |
| namespaceZendTest\Feed\Writer; | ||
| usePHPUnit\Framework\TestCase; | ||
| useZend\Feed\Reader\StandaloneExtensionManager; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others.Learn more.
This is supposed to be Writer
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others.Learn more.
Ah, my IDE had collapsed the use statements so I didn't see them. Fixed.
| */ | ||
| publicfunctionremove($name) | ||
| { | ||
| if (array_key_exists($name,$this->extensions)) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others.Learn more.
Any reason, why this check is removed?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others.Learn more.
it is not needed. unset will work the same and there is no distinction between removing instance and noop.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others.Learn more.
@Xerkus
You are right, it throws no error.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others.Learn more.
It's becauseunset is a language construct, not a real function, and it doesn't care whether the thing you're unsetting exists or not. The check was only there before to set the return value.
| */ | ||
| publicfunctionadd($name,$class) | ||
| { | ||
| $this->extensions[$name] =$class; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others.Learn more.
No validation what is added to the manager?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others.Learn more.
good point.$class should be checked to be instance ofZend\Feed\Reader\Extension\AbstractEntry orZend\Feed\Reader\Extension\AbstractFeed
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others.Learn more.
I wondered about that - $class can be a string (it was in the components until I changed it), but it might be the name of something that doesn't exist yet, so I don't know that it can be validated at this point.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others.Learn more.
with check it will be autoloaded when extension is registered. Plugin manager validates on creation.
Xerkus commentedNov 14, 2017
This check for Writer extensions makes little sense zend-feed/src/Writer/ExtensionPluginManager.php Lines 135 to 158 in316e9b7
How should it be ported to standalone extension manager? |
Synchro commentedNov 14, 2017
All passing now. That OK? |
| namespaceZend\Feed\Writer; | ||
| useZend\ServiceManager\Exception\InvalidServiceException; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others.Learn more.
You cannot use ServiceManager exceptions in here. UseZend\Feed\Writer\Exception\InvalidArgumentException
| namespaceZend\Feed\Reader; | ||
| useZend\ServiceManager\Exception\InvalidServiceException; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others.Learn more.
You cannot use ServiceManager exceptions in here. UseZend\Feed\Reader\Exception\InvalidArgumentException
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others.Learn more.
But that's the type that is thrown?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others.Learn more.
throw that other type
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others.Learn more.
OK, I see why.
| $this->assertNotSame($extension,$test); | ||
| } | ||
| publicfunctiontestPluginAddRemove() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others.Learn more.
You need additional tests for expected exception in case of invalid extension class or object of valid extension.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others.Learn more.
You need additional tests to ensure extensions derived from both allowed classes are accepted
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others.Learn more.
I've added tests for the exceptions, but the check inadd is already checking for derived classes, because the class it checks for is abstract, so anything that is_aExtension\AbstractEntry is by definition derived from it, so passing a further derivation wouldn't be testing anything further.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others.Learn more.
Those should be separate tests with descriptive names for what you are testing for
testAddAcceptsValidExtensionClasses()
testAddRejectsInvalidExtensions()
testAddRejectsInstanceOfValidExtension()
That way we have intent of the test and its implementation details rather than just asserting that current code runs without errors. It makes sure that if code changes at a later stage no intent will be lost.
| $this->assertNotSame($extension,$test); | ||
| } | ||
| publicfunctiontestPluginAddRemove() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others.Learn more.
Same here, additional tests for expected exception in case of invalid extension class or object of valid extension.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others.Learn more.
additional tests to ensure extensions derived from allowed class or with classnames ending with 'Feed' or 'Entry' are accepted
Make StandaloneExtensionManagers configurable
weierophinney commentedDec 4, 2017
Thanks,@Synchro |
This is a simple PR that fixes my request in#54. If you're happy with this, I will add changes to the docs as well, also fixing#44.