-
Notifications
You must be signed in to change notification settings - Fork 2.5k
Better polyfill support for Stdlib and Session #3966
Better polyfill support for Stdlib and Session #3966
Conversation
* are unable to unset multi-dimensional arrays because you | ||
* need to fetch the properties / lists as references. | ||
* If the version is less than 5.3.4, we'll use Zend\Stdlib\ArrayObject\PhpLegacyCompatibility | ||
* which extend sthe native PHP ArrayObject implementation. For versions greater than or equal |
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.
Move the space between "extend sthe" :)
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.
Done.
If this is not fixed any issue in the wild then may be better merge this against devel |
@Maks3w - It actually does fix issues reported in the wild:
The solution presented in here fixes both of those, and makes usage as easy as |
- Instead of using an autoload file, instead created two separate classes, named after the type of support they provide. The file Zend\Stdlib\ArrayObject now simply has a conditional in it; based on the condition met, a class_alias() is created -- and from then on, that alias will be used for Zend\Stdlib\ArrayObject. - Removed autoload.files entries from composer.json files; no longer necessary. - One test failure currently in doing a comparison of merged array objects; will investigate in a later commit.
- Created Zend\Session\Container and Zend\Session\Storage\SessionArrayStorage namespaces. Each contains PhpLegacyCompatibility and PhpReferenceCompatibility classes. The classes with the same name as the new namespaces each use conditionals to execute class_alias() commands in order to perform version-specific polyfills. - Removed compatibility/autoload.php from composer.json autoload.files; no longer necessary. - All tests are running!
- changed a typehint from "ArrayObject" to "self"
- bad import
- BC measure, so that code referencing these files doesn't break
- typehint on AbstractContainer - when instantiating a Container instance, use fully qualified class name in order to trigger alias
- Imports will work against class_alias - Typehinting works, *except* when using mocks, as mocks do not take into account class aliasing.
} | ||
$storage = $this->getStorage(); | ||
$name = $this->getName(); | ||
$ret =& $storage[$name][$key]; |
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.
Indentation
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.
What's the change needed? (This is the original formatting from @mwillbanks -- just moved to a new file.)
- moved autoload.php files into compatibility subdirs where they belong - marked each with @deprecated annotation
} | ||
} | ||
if (version_compare(PHP_VERSION, '5.3.4', 'lt') | ||
&& !class_exists('Zend\Stdlib\ArrayObject', false) |
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.
Why do you check if that class was already defined?
- If you want to ensure you only load it once, shouldn't you also use 'elseif' (checking for the same condition) instead of 'else'?
- If we want to keep php's behavior as regular as possible, we shouldn't perform this check at all I think. Including the same file twice will usually generate a 'cannot redeclare class at...'
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.
bad cut-and-paste -- I've removed it in a separate commit now.
- bad cut-and-paste
Review complete. |
- Use __halt_compiler(), and then define stub class, in order to trick classmap compilers into thinking a class exists.
- Allows finding class definitions following halt_compiler directives, effectively allowing polyfill support in classmap generation.
@Freeaqingme and @DASPRiD I've done the following in the last few commits:
Ready to merge, if tests pass. |
I'm still wondering about one little thing before merging. I did a small test, and this also seems to work, not requiring any classmap generator changes or the like. @weierophinney, can you verify if this is a valid solution? I'm not sure if you considered this already, and/or if it also messes with opcode caching, but else it's probably worth taking a look at: <?php
namespace Zend\Stdlib\ArrayObject;
if (version_compare(PHP_VERSION, '5.4.0', 'lt')) {
class_alias('Zend\Stdlib\ArrayObject\PhpLegacyCompatibility', 'Zend\Stdlib\ArrayObjectBase');
} else {
class_alias('Zend\Stdlib\ArrayObject\PhpReferenceCompatibility', 'Zend\Stdlib\ArrayObjectBase');
}
class ArrayObject extends ArrayObjectBase
{
} |
- Have a base class that extends a polyfill class - makes classmap generation simpler - makes typehinting and mock objects simpler
- No longer necessary to do the halt_compiler hack
- No longer necessary
- To allow running ant build without prompting for missing files
- Changes are simpler, so simpler explanation is in order.
- they are not intended to be instantiated directly; they are intended as bases for the typehinted class that uses the polyfills.
@DASPRiD Your comment is exactly the reason I was looking for review! The solution you outline both simplifies the support, and solves the typehinting problems. I've implemented that now, and rolled back the changes to the CSRF validator and to the ClassFileLocator. |
- since the "legacy" class simply extended AbstractContainer, can use that as the polyfill
- It was an empty extension of AbstractSessionArrayStorage; simply use that class as the polyfill
I was able to simplify even further, as two of the Session polyfills were simply empty extensions of existing abstract classes. @DASPRiD @Freeaqingme @Maks3w Ready for final review. @mwillbanks -- check out the solution -- it's basically the conditional use statements we wanted originally. :) |
Looks very good to me now. Preferring a second review though before merging :) |
@weierophinney this looks good 👍 I like the conditionals TBH, much more explicit and easier to determine. Also far happier with this in the end as it basically does what we intend it to do. |
@@ -13,6 +13,26 @@ DD MMM YYYY | |||
|
|||
### UPDATES IN 2.1.4 | |||
|
|||
Better polyfill support in `Zend\Session` and `Zend\Stdlib`. Polyfills |
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.
Shouldn't this paragraph have some kind of caption or title? If we add more to this readme, it would ease on legibility. Although I'm not entirely sure this is merely hypothetical.
Also, this is part of the changelog for 2.1.4. Shouldn't we also add it to the change log for 2.2, so that people who upgrade from minor to minor release get to see the list of changes? (I'm not sure discussing this on this PR is the right place to do so though).
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 will go into CHANGELOG.md when we release 2.1.4, and that always gets merged back to develop as well.
IF we have more updates we want to call out, we can add additional subheaders; with only one, there's no need yet.
@weierophinney Looks good! There is one mini remark about indentation that it would seem you missed. Remarks on the changelog may have to be discussed elsewhere, independent from putting this PR forward. |
This PR aims to provide more robust, simpler-to-use polyfill support for Zend\Stdlib and Zend\Session.
The current support requires that uses call on a
compatibility/autoload.php
file in order for the polyfill replacements to be made. This creates problems:classmap_generator.php
fails, as the incorrect variant may be used.The proposed solution uses PHP's
class_alias
. This function allows you to globally alias one class name to another. I have putclass_alias
statements inside conditionals, achieving conditional imports:This approach means we no longer need to introduce autoloading hacks, and makes it possible for classmap generation to work properly again.