Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

Merge branch 'develop' of git://github.com/zendframework/zf2 into fea…

…ture/cache-session-storage

Conflicts:
	CHANGELOG.md
  • Loading branch information...
commit a7bab8254432551a561f3461fa4fa9b1a1a38d3b 2 parents eb515e6 + 3c1f321
@marc-mabe authored
Showing with 4,346 additions and 1,394 deletions.
  1. +287 −18 CHANGELOG.md
  2. +1 −1  README-GIT.md
  3. +3 −48 README.md
  4. +16 −18 library/Zend/Barcode/Barcode.php
  5. +2 −2 library/Zend/Barcode/Object/Code128.php
  6. +137 −61 library/Zend/Cache/Storage/Adapter/Memcached.php
  7. +176 −152 library/Zend/Cache/Storage/Adapter/MemcachedOptions.php
  8. +554 −0 library/Zend/Cache/Storage/Adapter/MemcachedResourceManager.php
  9. +1 −1  library/Zend/Cache/composer.json
  10. +2 −2 library/Zend/Captcha/AbstractWord.php
  11. +1 −1  library/Zend/Code/Generator/FileGenerator.php
  12. +1 −1  library/Zend/Code/Generator/FileGeneratorRegistry.php
  13. +1 −1  library/Zend/Code/Generator/ParameterGenerator.php
  14. +5 −93 library/Zend/Code/Scanner/ClassScanner.php
  15. +3 −2 library/Zend/Code/composer.json
  16. +7 −7 library/Zend/Config/Factory.php
  17. +5 −5 library/Zend/Crypt/BlockCipher.php
  18. +2 −2 library/Zend/Crypt/Key/Derivation/SaltedS2k.php
  19. +3 −3 library/Zend/Crypt/PublicKey/DiffieHellman.php
  20. +5 −5 library/Zend/Crypt/Symmetric/Mcrypt.php
  21. +1 −1  library/Zend/Db/Adapter/Adapter.php
  22. +39 −0 library/Zend/Db/Adapter/AdapterAwareTrait.php
  23. +41 −0 library/Zend/Db/Adapter/AdapterInterface.php
  24. +0 −9 library/Zend/Db/Adapter/Driver/Pgsql/Feature/SequenceHelper.php
  25. +1 −1  library/Zend/Db/Adapter/Driver/Pgsql/Statement.php
  26. +1 −0  library/Zend/Db/Metadata/Source/AbstractSource.php
  27. +12 −12 library/Zend/Db/Sql/AbstractSql.php
  28. +5 −4 library/Zend/Db/Sql/Delete.php
  29. +0 −2  library/Zend/Db/Sql/Having.php
  30. +19 −16 library/Zend/Db/Sql/Insert.php
  31. +3 −3 library/Zend/Db/Sql/Platform/AbstractPlatform.php
  32. +9 −9 library/Zend/Db/Sql/Platform/Mysql/SelectDecorator.php
  33. +3 −3 library/Zend/Db/Sql/Platform/Platform.php
  34. +6 −5 library/Zend/Db/Sql/Platform/SqlServer/SelectDecorator.php
  35. +2 −2 library/Zend/Db/Sql/Predicate/Between.php
  36. +3 −3 library/Zend/Db/Sql/PreparableSqlInterface.php
  37. +25 −24 library/Zend/Db/Sql/Select.php
  38. +2 −2 library/Zend/Db/Sql/Sql.php
  39. +5 −5 library/Zend/Db/Sql/Update.php
  40. +0 −2  library/Zend/Db/Sql/Where.php
  41. +5 −5 library/Zend/Debug/Debug.php
  42. +4 −2 library/Zend/Di/Definition/Builder/InjectionMethod.php
  43. +6 −0 library/Zend/Di/Definition/BuilderDefinition.php
  44. +6 −2 library/Zend/Di/Definition/ClassDefinition.php
  45. +3 −4 library/Zend/Di/Definition/CompilerDefinition.php
  46. +1 −0  library/Zend/Di/Definition/DefinitionInterface.php
  47. +3 −2 library/Zend/Di/Definition/RuntimeDefinition.php
  48. +3 −7 library/Zend/Di/Di.php
  49. +1 −1  library/Zend/Dom/Css2Xpath.php
  50. +6 −14 library/Zend/EventManager/EventManager.php
  51. +10 −4 library/Zend/{Code/Scanner/VariableScanner.php → EventManager/EventManagerAwareTrait.php}
  52. +6 −6 library/Zend/Feed/PubSubHubbub/PubSubHubbub.php
  53. +42 −42 library/Zend/Feed/Reader/Reader.php
  54. +24 −24 library/Zend/Feed/Writer/Writer.php
  55. +3 −3 library/Zend/Filter/StaticFilter.php
  56. +1 −1  library/Zend/Form/Annotation/AnnotationBuilder.php
  57. +1 −1  library/Zend/Form/Element.php
  58. +10 −7 library/Zend/Form/Element/DateTime.php
  59. +13 −2 library/Zend/Form/Element/DateTimeLocal.php
  60. +314 −0 library/Zend/Form/Element/DateTimeSelect.php
  61. +1 −1  library/Zend/Form/Exception/InvalidElementException.php
  62. +1 −1  library/Zend/Form/Factory.php
  63. +1 −1  library/Zend/Form/Fieldset.php
  64. +4 −3 library/Zend/Form/Form.php
  65. +38 −0 library/Zend/Form/FormFactoryAwareTrait.php
  66. +1 −2  library/Zend/Form/View/Helper/Captcha/AbstractWord.php
  67. +1 −1  library/Zend/Form/View/Helper/FormDateSelect.php
  68. +301 −0 library/Zend/Form/View/Helper/FormDateTimeSelect.php
  69. +5 −0 library/Zend/Form/View/Helper/FormElement.php
  70. +1 −1  library/Zend/Form/View/Helper/FormMonthSelect.php
  71. +1 −0  library/Zend/Form/View/HelperConfig.php
  72. +4 −4 library/Zend/Http/Client.php
  73. +18 −0 library/Zend/Http/Client/Adapter/Proxy.php
  74. +2 −2 library/Zend/Http/Client/Adapter/Socket.php
  75. +4 −4 library/Zend/Http/Header/CacheControl.php
  76. +2 −4 library/Zend/Http/PhpEnvironment/Response.php
  77. +1 −1  library/Zend/Http/Request.php
  78. +10 −10 library/Zend/I18n/Translator/Plural/Rule.php
  79. +120 −0 library/Zend/I18n/Translator/TranslatorAwareTrait.php
  80. +4 −4 library/Zend/I18n/Validator/Alnum.php
  81. +5 −5 library/Zend/I18n/Validator/Alpha.php
  82. +2 −2 library/Zend/I18n/Validator/PostCode.php
  83. +48 −0 library/Zend/InputFilter/InputFilterAwareTrait.php
  84. +1 −1  library/Zend/Json/Encoder.php
  85. +14 −14 library/Zend/Json/Json.php
  86. +2 −2 library/Zend/Json/Server/Response.php
  87. +1 −1  library/Zend/Json/Server/Smd.php
  88. +12 −12 library/Zend/Ldap/Attribute.php
  89. +11 −11 library/Zend/Ldap/Converter/Converter.php
  90. +28 −28 library/Zend/Ldap/Dn.php
  91. +2 −2 library/Zend/Ldap/Filter.php
  92. +1 −1  library/Zend/Ldap/Filter/MaskFilter.php
  93. +2 −2 library/Zend/Ldap/Ldap.php
  94. +2 −2 library/Zend/Ldap/Node.php
  95. +1 −1  library/Zend/Ldap/Node/AbstractNode.php
  96. +1 −1  library/Zend/Loader/AutoloaderFactory.php
  97. +6 −6 library/Zend/Log/Logger.php
  98. +38 −0 library/Zend/Log/LoggerAwareTrait.php
  99. +4 −4 library/Zend/Log/Writer/Syslog.php
  100. +1 −1  library/Zend/Mail/Header/GenericHeader.php
  101. +3 −3 library/Zend/Mail/Storage/Imap.php
  102. +1 −1  library/Zend/Mail/Storage/Maildir.php
  103. +3 −3 library/Zend/Mime/Decode.php
  104. +7 −7 library/Zend/Mime/Mime.php
  105. +5 −4 library/Zend/Mime/Part.php
  106. +1 −1  library/Zend/ModuleManager/ModuleManager.php
  107. +2 −0  library/Zend/Mvc/Application.php
  108. +3 −2 library/Zend/Mvc/Controller/Plugin/FilePostRedirectGet.php
  109. +6 −2 library/Zend/Mvc/Controller/Plugin/Forward.php
  110. +2 −2 library/Zend/Mvc/Controller/Plugin/PostRedirectGet.php
  111. +2 −2 library/Zend/Mvc/Router/Http/Regex.php
  112. +7 −7 library/Zend/Mvc/Router/Http/Segment.php
  113. +26 −24 library/Zend/Mvc/Router/Http/TreeRouteStack.php
  114. +3 −3 library/Zend/Mvc/Router/Http/Wildcard.php
  115. +1 −1  library/Zend/Mvc/Router/RoutePluginManager.php
  116. +4 −4 library/Zend/Navigation/Page/AbstractPage.php
  117. +3 −3 library/Zend/Navigation/Page/Mvc.php
  118. +26 −26 library/Zend/Paginator/Paginator.php
  119. +3 −3 library/Zend/Serializer/Adapter/IgBinary.php
  120. +3 −3 library/Zend/Serializer/Adapter/PhpSerialize.php
  121. +18 −18 library/Zend/Serializer/Adapter/PythonPickle.php
  122. +1 −1  library/Zend/Server/Cache.php
  123. +48 −0 library/Zend/ServiceManager/ServiceLocatorAwareTrait.php
  124. +33 −17 library/Zend/ServiceManager/ServiceManager.php
  125. +18 −0 library/Zend/Session/Config/SessionConfig.php
  126. +6 −6 library/Zend/Session/Container.php
  127. +3 −3 library/Zend/Session/Validator/RemoteAddr.php
  128. +1 −1  library/Zend/Stdlib/ArrayUtils.php
  129. +10 −10 library/Zend/Stdlib/CallbackHandler.php
  130. +10 −10 library/Zend/Stdlib/Glob.php
  131. +3 −3 library/Zend/Stdlib/Hydrator/Reflection.php
  132. +5 −5 library/Zend/Text/Table/Table.php
  133. +2 −2 library/Zend/Uri/Http.php
  134. +7 −7 library/Zend/Validator/AbstractValidator.php
  135. +3 −3 library/Zend/Validator/Digits.php
  136. +4 −4 library/Zend/Validator/Iban.php
  137. +3 −3 library/Zend/Validator/StaticValidator.php
  138. +1 −1  library/Zend/Version/Version.php
  139. +6 −6 library/Zend/View/Helper/Navigation/AbstractHelper.php
  140. +2 −2 library/Zend/View/Helper/Navigation/Links.php
  141. +7 −7 library/Zend/View/Helper/PaginationControl.php
  142. +23 −43 library/Zend/View/Helper/Partial.php
  143. +29 −14 library/Zend/View/Helper/PartialLoop.php
  144. +11 −4 library/Zend/View/Renderer/PhpRenderer.php
  145. +15 −15 library/Zend/XmlRpc/AbstractValue.php
  146. +1 −1  library/Zend/XmlRpc/Server.php
  147. +10 −10 library/Zend/XmlRpc/Server/Fault.php
  148. +1 −1  library/Zend/XmlRpc/Value/AbstractCollection.php
  149. +144 −129 resources/languages/ja/Zend_Validate.php
  150. +3 −1 tests/ZendTest/Barcode/Renderer/TestCommon.php
  151. +48 −14 tests/ZendTest/Cache/Storage/Adapter/MemcachedTest.php
  152. +36 −0 tests/ZendTest/Db/Adapter/AdapterAwareTraitTest.php
  153. +4 −5 tests/ZendTest/Db/Sql/AbstractSqlTest.php
  154. +10 −0 tests/ZendTest/Db/Sql/InsertTest.php
  155. +4 −2 tests/ZendTest/Db/Sql/Platform/Mysql/SelectDecoratorTest.php
  156. +13 −2 tests/ZendTest/Db/Sql/Predicate/BetweenTest.php
  157. +2 −3 tests/ZendTest/Db/Sql/SelectTest.php
  158. +7 −7 tests/ZendTest/Di/Definition/BuilderDefinitionTest.php
  159. +5 −2 tests/ZendTest/Di/Definition/ClassDefinitionTest.php
  160. +13 −1 tests/ZendTest/Di/Definition/CompilerDefinitionTest.php
  161. +43 −2 tests/ZendTest/Di/Definition/RuntimeDefinitionTest.php
  162. +45 −0 tests/ZendTest/Di/DiTest.php
  163. +44 −0 tests/ZendTest/Di/TestAsset/ConstructorInjection/OptionalParameters.php
  164. +34 −0 tests/ZendTest/Di/TestAsset/SetterInjection/StaticSetter.php
  165. +46 −0 tests/ZendTest/EventManager/EventManagerAwareTraitTest.php
  166. +4 −4 tests/ZendTest/Form/Element/DateTimeLocalTest.php
  167. +75 −0 tests/ZendTest/Form/Element/DateTimeSelectTest.php
  168. +8 −8 tests/ZendTest/Form/Element/DateTimeTest.php
  169. +1 −1  tests/ZendTest/Form/FactoryTest.php
  170. +1 −1  tests/ZendTest/Form/FormElementManagerTest.php
  171. +33 −0 tests/ZendTest/Form/FormFactoryAwareTraitTest.php
  172. +28 −0 tests/ZendTest/Form/FormTest.php
  173. +9 −0 tests/ZendTest/Form/View/Helper/Captcha/DumbTest.php
  174. +89 −0 tests/ZendTest/Form/View/Helper/FormDateTimeSelectTest.php
  175. +23 −0 tests/ZendTest/Http/Client/ProxyAdapterTest.php
  176. +129 −0 tests/ZendTest/I18n/Translator/TranslatorAwareTraitTest.php
  177. +6 −6 tests/ZendTest/I18n/View/Helper/DateFormatTest.php
  178. +46 −0 tests/ZendTest/InputFilter/InputFilterAwareTraitTest.php
  179. +7 −0 tests/ZendTest/Json/Server/ResponseTest.php
  180. +33 −0 tests/ZendTest/Log/LoggerAwareTraitTest.php
  181. +0 −10 tests/ZendTest/Log/Writer/AbstractTest.php
  182. +0 −9 tests/ZendTest/Log/Writer/DbTest.php
  183. +19 −0 tests/ZendTest/ModuleManager/ModuleManagerTest.php
  184. +59 −3 tests/ZendTest/Mvc/ApplicationTest.php
  185. +7 −0 tests/ZendTest/Mvc/Controller/Plugin/FilePostRedirectGetTest.php
  186. +12 −6 tests/ZendTest/Mvc/Controller/Plugin/ForwardTest.php
  187. +31 −0 tests/ZendTest/Mvc/Controller/Plugin/PostRedirectGetTest.php
  188. +27 −1 tests/ZendTest/Mvc/Router/Http/RegexTest.php
  189. +29 −3 tests/ZendTest/Mvc/Router/Http/SegmentTest.php
  190. +27 −1 tests/ZendTest/Mvc/Router/Http/WildcardTest.php
  191. +46 −0 tests/ZendTest/ServiceManager/ServiceLocatorAwareTraitTest.php
  192. +57 −2 tests/ZendTest/ServiceManager/ServiceManagerTest.php
  193. +51 −0 tests/ZendTest/ServiceManager/TestAsset/FooCounterAbstractFactory.php
  194. +6 −0 tests/ZendTest/Session/Config/SessionConfigTest.php
  195. +7 −20 tests/ZendTest/View/Helper/PartialLoopTest.php
  196. +30 −65 tests/ZendTest/View/Helper/PartialTest.php
View
305 CHANGELOG.md
@@ -1,25 +1,294 @@
# CHANGELOG
+## 2.0.4
-## 2.1.0:
+- 2808: Add serializer better inheritance and extension
+ (https://github.com/zendframework/zf2/issues/2808)
+- 2813: Add test on canonical name with the ServiceManager
+ (https://github.com/zendframework/zf2/issues/2813)
+- 2832: bugfix: The helper DateFormat does not cache correctly when a pattern is
+ set. (https://github.com/zendframework/zf2/issues/2832)
+- 2837: Add empty option before empty check
+ (https://github.com/zendframework/zf2/issues/2837)
+- 2843: change self:: with static:: in call-ing static property/method
+ (https://github.com/zendframework/zf2/issues/2843)
+- 2857: Unnecessary path assembly on return in
+ Zend\Mvc\Router\Http\TreeRouteStack->assemble() line 236
+ (https://github.com/zendframework/zf2/issues/2857)
+- 2867: Enable view sub-directories when using ModuleRouteListener
+ (https://github.com/zendframework/zf2/issues/2867)
+- 2872: Resolve naming conflicts in foreach statements
+ (https://github.com/zendframework/zf2/issues/2872)
+- 2878: Fix : change self:: with static:: in call-ing static property/method()
+ in other components ( all ) (https://github.com/zendframework/zf2/issues/2878)
+- 2879: remove unused const in Zend\Barcode\Barcode.php
+ (https://github.com/zendframework/zf2/issues/2879)
+- 2896: Constraints in Zend\Db\Metadata\Source\AbstractSource::getTable not
+ initalised (https://github.com/zendframework/zf2/issues/2896)
+- 2907: Fixed proxy adapter keys being incorrectly set due Zend\Http\Client
+ (https://github.com/zendframework/zf2/issues/2907)
+- 2909: Change format of Form element DateTime and DateTimeLocal
+ (https://github.com/zendframework/zf2/issues/2909)
+- 2921: Added Chinese translations for zf2 validate/captcha resources
+ (https://github.com/zendframework/zf2/issues/2921)
+- 2924: small speed-up of Zend\EventManager\EventManager::triggerListeners()
+ (https://github.com/zendframework/zf2/issues/2924)
+- 2929: SetCookie::getFieldValue() always uses urlencode() for cookie values,
+ even in case they are already encoded
+ (https://github.com/zendframework/zf2/issues/2929)
+- 2930: Add minor test coverage to MvcEvent
+ (https://github.com/zendframework/zf2/issues/2930)
+- 2932: Sessions: SessionConfig does not allow setting non-directory save path
+ (https://github.com/zendframework/zf2/issues/2932)
+- 2937: preserve matched route name within route match instance while
+ forwarding... (https://github.com/zendframework/zf2/issues/2937)
+- 2940: change 'Cloud\Decorator\Tag' to 'Cloud\Decorator\AbstractTag'
+ (https://github.com/zendframework/zf2/issues/2940)
+- 2941: Logical operator fix : 'or' change to '||' and 'and' change to '&&'
+ (https://github.com/zendframework/zf2/issues/2941)
+- 2952: Various Zend\Mvc\Router\Http routers turn + into a space in path
+ segments (https://github.com/zendframework/zf2/issues/2952)
+- 2957: Make Partial proxy to view render function
+ (https://github.com/zendframework/zf2/issues/2957)
+- 2971: Zend\Http\Cookie undefined self::CONTEXT_REQUEST
+ (https://github.com/zendframework/zf2/issues/2971)
+- 2976: Fix for #2541 (https://github.com/zendframework/zf2/issues/2976)
+- 2981: Controller action HttpResponse is not used by SendResponseListener
+ (https://github.com/zendframework/zf2/issues/2981)
+- 2983: replaced all calls to $this->xpath with $this->getXpath() to always
+ have... (https://github.com/zendframework/zf2/issues/2983)
+- 2986: Add class to file missing a class (fixes #2789)
+ (https://github.com/zendframework/zf2/issues/2986)
+- 2987: fixed Zend\Session\Container::exchangeArray
+ (https://github.com/zendframework/zf2/issues/2987)
+- 2994: Fixes #2993 - Add missing asterisk to method docblock
+ (https://github.com/zendframework/zf2/issues/2994)
+- 2997: Fixing abstract factory instantiation time
+ (https://github.com/zendframework/zf2/issues/2997)
+- 2999: Fix for GitHub issue 2579
+ (https://github.com/zendframework/zf2/issues/2999)
+- 3002: update master's resources/ja Zend_Validate.php message
+ (https://github.com/zendframework/zf2/issues/3002)
+- 3003: Adding tests for zendframework/zf2#2593
+ (https://github.com/zendframework/zf2/issues/3003)
+- 3006: Hotfix for #2497 (https://github.com/zendframework/zf2/issues/3006)
+- 3007: Fix for issue 3001 Zend\Db\Sql\Predicate\Between fails with min and max
+ ... (https://github.com/zendframework/zf2/issues/3007)
+- 3008: Hotfix for #2482 (https://github.com/zendframework/zf2/issues/3008)
+- 3009: Hotfix for #2451 (https://github.com/zendframework/zf2/issues/3009)
+- 3013: Solved Issue 2857 (https://github.com/zendframework/zf2/issues/3013)
+- 3025: Removing the separator between the hidden and the visible inputs. As
+ the... (https://github.com/zendframework/zf2/issues/3025)
+- 3027: Reduced #calls of plugin() in PhpRenderer using a cache mechanism
+ (https://github.com/zendframework/zf2/issues/3027)
+- 3029: Fixed the pre-commit script, missed the fix command
+ (https://github.com/zendframework/zf2/issues/3029)
+- 3030: Mark module as loaded before trigginer EVENT_LOAD_MODULE
+ (https://github.com/zendframework/zf2/issues/3030)
+- 3031: Zend\Db\Sql Fix for Insert's Merge and Set capabilities with simlar keys
+ (https://github.com/zendframework/zf2/issues/3031)
-- The initializer for ServiceManagerAwareInterface was removed to prevent
- confusion between ServiceManagerAwareInterface and
- ServiceLocatorAwareInterface, and to promote using the latter interface.
-- File upload functionality has been rewritten and moved out of Zend\File
- into Zend\Form and Zend\InputFilter. File elements are now
- specified and handled with Zend\Form just like any other form element.
-- File upload progress functionality has been moved out of Zend\File into
- specific classes under Zend\ProgressBar\Upload based on the type of
- handler (APC, UploadProgress module, and Session progress in PHP 5.4).
-- New form elements under Zend\Form\Element\File for the various upload
- progress identifiers.
-- New Zend\Filter\File\RenameUpload filter for securely moving uploaded
- files.
-- New Zend\Mvc\Controller\Plugin\FilePostRedirectGet plugin for file
- upload forms.
-- New Zend\Cache\Storage\Adapter\Session to store items into a session
- container.
+
+## 2.0.3:
+
+- 2244: Fix for issue ZF2-503 (https://github.com/zendframework/zf2/issues/2244)
+- 2318: Allow to remove decimals in CurrencyFormat
+ (https://github.com/zendframework/zf2/issues/2318)
+- 2363: Hotfix db features with eventfeature
+ (https://github.com/zendframework/zf2/issues/2363)
+- 2380: ZF2-482 Attempt to fix the buffer. Also added extra unit tests.
+ (https://github.com/zendframework/zf2/issues/2380)
+- 2392: Update library/Zend/Db/Adapter/Platform/Mysql.php
+ (https://github.com/zendframework/zf2/issues/2392)
+- 2395: Fix for http://framework.zend.com/issues/browse/ZF2-571
+ (https://github.com/zendframework/zf2/issues/2395)
+- 2397: Memcached option merge issuse
+ (https://github.com/zendframework/zf2/issues/2397)
+- 2402: Adding missing dependencies
+ (https://github.com/zendframework/zf2/issues/2402)
+- 2404: Fix to comments (https://github.com/zendframework/zf2/issues/2404)
+- 2416: Fix expressionParamIndex for AbstractSql
+ (https://github.com/zendframework/zf2/issues/2416)
+- 2420: Zend\Db\Sql\Select: Fixed issue with join expression named parameters
+ overlapping. (https://github.com/zendframework/zf2/issues/2420)
+- 2421: Update library/Zend/Http/Header/SetCookie.php
+ (https://github.com/zendframework/zf2/issues/2421)
+- 2422: fix add 2 space after @param in Zend\Loader
+ (https://github.com/zendframework/zf2/issues/2422)
+- 2423: ManagerInterface must be interface, remove 'interface' description
+ (https://github.com/zendframework/zf2/issues/2423)
+- 2425: Use built-in Travis composer
+ (https://github.com/zendframework/zf2/issues/2425)
+- 2426: Remove need of setter in ClassMethods hydrator
+ (https://github.com/zendframework/zf2/issues/2426)
+- 2432: Prevent space before end of tag with HTML5 doctype
+ (https://github.com/zendframework/zf2/issues/2432)
+- 2433: fix for setJsonpCallback not called when recieved JsonModel + test
+ (https://github.com/zendframework/zf2/issues/2433)
+- 2434: added phpdoc in Zend\Db
+ (https://github.com/zendframework/zf2/issues/2434)
+- 2437: Hotfix/console 404 reporting
+ (https://github.com/zendframework/zf2/issues/2437)
+- 2438: Improved previous fix for ZF2-558.
+ (https://github.com/zendframework/zf2/issues/2438)
+- 2440: Turkish Translations for Captcha and Validate
+ (https://github.com/zendframework/zf2/issues/2440)
+- 2441: Allow form collection to have any helper
+ (https://github.com/zendframework/zf2/issues/2441)
+- 2516: limit(20) -> generates LIMIT '20' and throws an IllegalQueryException
+ (https://github.com/zendframework/zf2/issues/2516)
+- 2545: getSqlStringForSqlObject() returns an invalid SQL statement with LIMIT
+ and OFFSET clauses (https://github.com/zendframework/zf2/issues/2545)
+- 2595: Pgsql adapater has codes related to MySQL
+ (https://github.com/zendframework/zf2/issues/2595)
+- 2613: Prevent password to be rendered if form validation fails
+ (https://github.com/zendframework/zf2/issues/2613)
+- 2617: Fixed Zend\Validator\Iban class name
+ (https://github.com/zendframework/zf2/issues/2617)
+- 2619: Form enctype fix when File elements are within a collection
+ (https://github.com/zendframework/zf2/issues/2619)
+- 2620: InputFilter/Input when merging was not using raw value
+ (https://github.com/zendframework/zf2/issues/2620)
+- 2622: Added ability to specify port
+ (https://github.com/zendframework/zf2/issues/2622)
+- 2624: Form's default input filters added multiple times
+ (https://github.com/zendframework/zf2/issues/2624)
+- 2630: fix relative link ( remove the relative links ) in README.md
+ (https://github.com/zendframework/zf2/issues/2630)
+- 2631: Update library/Zend/Loader/AutoloaderFactory.php
+ (https://github.com/zendframework/zf2/issues/2631)
+- 2633: fix redundance errors "The input does not appear to be a valid date"
+ show twice (https://github.com/zendframework/zf2/issues/2633)
+- 2635: Fix potential issue with Sitemap test
+ (https://github.com/zendframework/zf2/issues/2635)
+- 2636: add isset checks around timeout and maxredirects
+ (https://github.com/zendframework/zf2/issues/2636)
+- 2641: hotfix : formRow() element error multi-checkbox and radio renderError
+ not shown (https://github.com/zendframework/zf2/issues/2641)
+- 2642: Fix Travis build for CS issue
+ (https://github.com/zendframework/zf2/issues/2642)
+- 2643: fix for setJsonpCallback not called when recieved JsonModel + test
+ (https://github.com/zendframework/zf2/issues/2643)
+- 2644: Add fluidity to the prepare() function for a form
+ (https://github.com/zendframework/zf2/issues/2644)
+- 2652: Zucchi/filter tweaks (https://github.com/zendframework/zf2/issues/2652)
+- 2665: pdftest fix (https://github.com/zendframework/zf2/issues/2665)
+- 2666: fixed url change (https://github.com/zendframework/zf2/issues/2666)
+- 2667: Possible fix for rartests
+ (https://github.com/zendframework/zf2/issues/2667)
+- 2669: skip whem gmp is loaded
+ (https://github.com/zendframework/zf2/issues/2669)
+- 2673: Input fallback value option
+ (https://github.com/zendframework/zf2/issues/2673)
+- 2676: mysqli::close() never called
+ (https://github.com/zendframework/zf2/issues/2676)
+- 2677: added phpdoc to Zend\Stdlib
+ (https://github.com/zendframework/zf2/issues/2677)
+- 2678: Zend\Db\Adapter\Sqlsrv\Sqlsrv never calls Statement\initialize() (fix
+ within) (https://github.com/zendframework/zf2/issues/2678)
+- 2679: Zend/Log/Logger.php using incorrect php errorLevel
+ (https://github.com/zendframework/zf2/issues/2679)
+- 2680: Cache: fixed bug on getTotalSpace of filesystem and dba adapter
+ (https://github.com/zendframework/zf2/issues/2680)
+- 2681: Cache/Dba: fixed notices on tearDown db4 tests
+ (https://github.com/zendframework/zf2/issues/2681)
+- 2682: Replace 'Configuration' with 'Config' when retrieving configuration
+ (https://github.com/zendframework/zf2/issues/2682)
+- 2683: Hotfix: Allow items from Abstract Factories to have setShared() called
+ (https://github.com/zendframework/zf2/issues/2683)
+- 2685: Remove unused Uses (https://github.com/zendframework/zf2/issues/2685)
+- 2686: Adding code to allow EventManager trigger listeners using wildcard
+ identifier (https://github.com/zendframework/zf2/issues/2686)
+- 2687: Hotfix/db sql nested expressions
+ (https://github.com/zendframework/zf2/issues/2687)
+- 2688: Hotfix/tablegateway event feature
+ (https://github.com/zendframework/zf2/issues/2688)
+- 2689: Hotfix/composer phpunit
+ (https://github.com/zendframework/zf2/issues/2689)
+- 2690: Use RFC-3339 full-date format (Y-m-d) in Date element
+ (https://github.com/zendframework/zf2/issues/2690)
+- 2691: join on conditions don't accept alternatives to columns
+ (https://github.com/zendframework/zf2/issues/2691)
+- 2693: Update library/Zend/Db/Adapter/Driver/Mysqli/Connection.php
+ (https://github.com/zendframework/zf2/issues/2693)
+- 2694: Bring fluid interface to Feed Writer
+ (https://github.com/zendframework/zf2/issues/2694)
+- 2698: fix typo in # should be :: in exception
+ (https://github.com/zendframework/zf2/issues/2698)
+- 2699: fix elseif in javascript Upload Demo
+ (https://github.com/zendframework/zf2/issues/2699)
+- 2700: fix cs in casting variable
+ (https://github.com/zendframework/zf2/issues/2700)
+- 2705: Fix french translation
+ (https://github.com/zendframework/zf2/issues/2705)
+- 2707: Improved error message when ServiceManager does not find an invokable
+ class (https://github.com/zendframework/zf2/issues/2707)
+- 2710: #2461 - correcting the url encoding of path segments
+ (https://github.com/zendframework/zf2/issues/2710)
+- 2711: Fix/demos ProgressBar/ZendForm.php : Object of class Zend\Form\Form
+ could not be converted to string
+ (https://github.com/zendframework/zf2/issues/2711)
+- 2712: fix cs casting variable for (array)
+ (https://github.com/zendframework/zf2/issues/2712)
+- 2713: Update library/Zend/Mvc/Service/ViewHelperManagerFactory.php
+ (https://github.com/zendframework/zf2/issues/2713)
+- 2714: Don't add separator if not prefixing columns
+ (https://github.com/zendframework/zf2/issues/2714)
+- 2717: Extends when it can : Validator\DateStep extends Validator\Date to
+ reduce code redundancy (https://github.com/zendframework/zf2/issues/2717)
+- 2719: Fixing the Cache Storage Factory Adapter Factory
+ (https://github.com/zendframework/zf2/issues/2719)
+- 2728: Bad Regex for Content Type header
+ (https://github.com/zendframework/zf2/issues/2728)
+- 2731: Reset the Order part when resetting Select
+ (https://github.com/zendframework/zf2/issues/2731)
+- 2732: Removed references to Mysqli in Zend\Db\Adapter\Driver\Pgsql
+ (https://github.com/zendframework/zf2/issues/2732)
+- 2733: fix @package Zend_Validate should be Zend_Validator
+ (https://github.com/zendframework/zf2/issues/2733)
+- 2734: fix i18n @package and @subpackage value
+ (https://github.com/zendframework/zf2/issues/2734)
+- 2736: fix captcha helper test.
+ (https://github.com/zendframework/zf2/issues/2736)
+- 2737: Issue #2728 - Bad Regex for Content Type header
+ (https://github.com/zendframework/zf2/issues/2737)
+- 2738: fix link 'quickstart' to version 2.0
+ (https://github.com/zendframework/zf2/issues/2738)
+- 2739: remove '@subpackage' because Zend\Math is not in subpackage
+ (https://github.com/zendframework/zf2/issues/2739)
+- 2742: remove () in echo-ing (https://github.com/zendframework/zf2/issues/2742)
+- 2749: Fix for #2678 (Zend\Db's Sqlsrv Driver)
+ (https://github.com/zendframework/zf2/issues/2749)
+- 2750: Adds the ability to instanciate by factory to AbstractPluginManager
+ (https://github.com/zendframework/zf2/issues/2750)
+- 2754: add the support to register module paths over namespace
+ (https://github.com/zendframework/zf2/issues/2754)
+- 2755: remove Zend\Mvc\Controller\PluginBroker from aliases in
+ "$defaultServiceConfig" (https://github.com/zendframework/zf2/issues/2755)
+- 2759: Fix Zend\Code\Scanner\TokenArrayScanner
+ (https://github.com/zendframework/zf2/issues/2759)
+- 2764: Fixed Zend\Math\Rand::getString() to pass the parameter $strong to
+ ::getBytes() (https://github.com/zendframework/zf2/issues/2764)
+- 2765: Csrf: always use dedicated setter
+ (https://github.com/zendframework/zf2/issues/2765)
+- 2766: Session\Storage: always preserve REQUEST_ACCESS_TIME
+ (https://github.com/zendframework/zf2/issues/2766)
+- 2768: Zend\Validator dependency is missed in Zend\Cache composer.json
+ (https://github.com/zendframework/zf2/issues/2768)
+- 2769: change valueToLDAP to valueToLdap and valueFromLDAP to valueFromLdap
+ (https://github.com/zendframework/zf2/issues/2769)
+- 2770: Memcached (https://github.com/zendframework/zf2/issues/2770)
+- 2775: Zend\Db\Sql: Fix for Mysql quoting during limit and offset
+ (https://github.com/zendframework/zf2/issues/2775)
+- 2776: Allow whitespace in Iban
+ (https://github.com/zendframework/zf2/issues/2776)
+- 2777: Fix issue when PREG_BAD_UTF8_OFFSET_ERROR is defined but Unicode support
+ is not enabled on PCRE (https://github.com/zendframework/zf2/issues/2777)
+- 2778: Undefined Index fix in ViewHelperManagerFactory
+ (https://github.com/zendframework/zf2/issues/2778)
+- 2779: Allow forms that have been added as fieldsets to bind values to bound
+ ob... (https://github.com/zendframework/zf2/issues/2779)
+- 2782: Issue 2781 (https://github.com/zendframework/zf2/issues/2782)
## 2.0.2:
View
2  README-GIT.md
@@ -140,7 +140,7 @@ foreach ($output as $file) {
*/
$output = array();
$return = null;
- exec("php-cs-fixer --dry-run --level=psr2 " . escapeshellarg($fileName), $output, $return);
+ exec("php-cs-fixer fix --dry-run --level=psr2 " . escapeshellarg($fileName), $output, $return);
if ($return != 0 || !empty($output)) {
echo "PHP file fails contains CS issues: " . $fileName . ":" . PHP_EOL;
echo implode(PHP_EOL, $output) . PHP_EOL;
View
51 README.md
@@ -9,57 +9,12 @@ Develop: [![Build Status](https://secure.travis-ci.org/zendframework/zf2.png?bra
This is the first minor (feature) release for the 2.0 series.
-XX YYY 2012
+20 Nov 2012
### UPDATES IN 2.1.0
-*Security Changes*
-
-By default, the JsonStrategy and FeedStrategy were selecting their
-associated renderers based on two criteria: if a ViewModel of
-appropriate type was present, *OR* if the Accept header matched certain
-criteria. It was pointed out that this latter is undesirable when the
-strategies are enabled globally, as any matching route could be forced
-to return JSON or a feed -- and potentially expose information not meant
-for that particular format, or raise exceptions due to containing
-content not compatible with the format.
-
-In this release, we removed the Accept header detection. To mitigate
-this, however, a new controller plugin, AcceptableViewModelSelector, was
-added. This plugin may be invoked from a controller, and based on
-criteria passed to it, return an appropriate view model type based on
-matching the Accept header. As an example:
-
-```php
-class SomeController extends AbstractActionController
-{
- protected $acceptCriteria = array(
- 'Zend\View\Model\JsonModel' => array(
- 'application/json',
- ),
- 'Zend\View\Model\FeedModel' => array(
- 'application/rss+xml',
- ),
- );
-
- public function apiAction()
- {
- $viewModel = $this->acceptableViewModelSelector($this->acceptCriteria);
-
- // Potentially vary execution based on model returned
- if ($viewModel instanceof JsonModel) {
- // ...
- }
- }
-}
-```
-
-You will still enable the JsonStrategy or FeedStrategy at the global
-level, but they will only be selected now if an appropriate view model
-is returned by the controller; the above plugin can help you select the
-appropriate view model based on Accept header on an as-needed basis.
-
-For more changes, please see CHANGELOG.md.
+
+Please see CHANGELOG.md.
### SYSTEM REQUIREMENTS
View
34 library/Zend/Barcode/Barcode.php
@@ -22,8 +22,6 @@
*/
abstract class Barcode
{
- const OBJECT = 'OBJECT';
- const RENDERER = 'RENDERER';
/**
* Default barcode TTF font name
*
@@ -56,11 +54,11 @@
*/
public static function getObjectPluginManager()
{
- if (!self::$objectPlugins instanceof ObjectPluginManager) {
- self::$objectPlugins = new ObjectPluginManager();
+ if (!static::$objectPlugins instanceof ObjectPluginManager) {
+ static::$objectPlugins = new ObjectPluginManager();
}
- return self::$objectPlugins;
+ return static::$objectPlugins;
}
/**
@@ -70,11 +68,11 @@ public static function getObjectPluginManager()
*/
public static function getRendererPluginManager()
{
- if (!self::$rendererPlugins instanceof RendererPluginManager) {
- self::$rendererPlugins = new RendererPluginManager();
+ if (!static::$rendererPlugins instanceof RendererPluginManager) {
+ static::$rendererPlugins = new RendererPluginManager();
}
- return self::$rendererPlugins;
+ return static::$rendererPlugins;
}
/**
@@ -131,12 +129,12 @@ public static function factory($barcode,
}
try {
- $barcode = self::makeBarcode($barcode, $barcodeConfig);
- $renderer = self::makeRenderer($renderer, $rendererConfig);
+ $barcode = static::makeBarcode($barcode, $barcodeConfig);
+ $renderer = static::makeRenderer($renderer, $rendererConfig);
} catch (Exception\ExceptionInterface $e) {
if ($automaticRenderError && !($e instanceof Exception\RendererCreationException)) {
- $barcode = self::makeBarcode('error', array( 'text' => $e->getMessage() ));
- $renderer = self::makeRenderer($renderer, array());
+ $barcode = static::makeBarcode('error', array( 'text' => $e->getMessage() ));
+ $renderer = static::makeRenderer($renderer, array());
} else {
throw $e;
}
@@ -197,7 +195,7 @@ public static function makeBarcode($barcode, $barcodeConfig = array())
);
}
- return self::getObjectPluginManager()->get($barcode, $barcodeConfig);
+ return static::getObjectPluginManager()->get($barcode, $barcodeConfig);
}
/**
@@ -249,7 +247,7 @@ public static function makeRenderer($renderer = 'image', $rendererConfig = array
);
}
- return self::getRendererPluginManager()->get($renderer, $rendererConfig);
+ return static::getRendererPluginManager()->get($renderer, $rendererConfig);
}
/**
@@ -265,7 +263,7 @@ public static function render($barcode,
$barcodeConfig = array(),
$rendererConfig = array())
{
- self::factory($barcode, $renderer, $barcodeConfig, $rendererConfig)->render();
+ static::factory($barcode, $renderer, $barcodeConfig, $rendererConfig)->render();
}
/**
@@ -282,7 +280,7 @@ public static function draw($barcode,
$barcodeConfig = array(),
$rendererConfig = array())
{
- return self::factory($barcode, $renderer, $barcodeConfig, $rendererConfig)->draw();
+ return static::factory($barcode, $renderer, $barcodeConfig, $rendererConfig)->draw();
}
/**
@@ -293,7 +291,7 @@ public static function draw($barcode,
*/
public static function setBarcodeFont($font)
{
- self::$staticFont = $font;
+ static::$staticFont = $font;
}
/**
@@ -303,6 +301,6 @@ public static function setBarcodeFont($font)
*/
public static function getBarcodeFont()
{
- return self::$staticFont;
+ return static::$staticFont;
}
}
View
4 library/Zend/Barcode/Object/Code128.php
@@ -218,8 +218,8 @@ protected function convertToBarcodeChars($string)
$char = $string[$pos];
$code = null;
- if (self::_isDigit($string, $pos, 4) && $currentCharset != 'C'
- || self::_isDigit($string, $pos, 2) && $currentCharset == 'C') {
+ if (static::_isDigit($string, $pos, 4) && $currentCharset != 'C'
+ || static::_isDigit($string, $pos, 2) && $currentCharset == 'C') {
/**
* Switch to C if the next 4 chars are numeric or stay C if the next 2
* chars are numeric
View
198 library/Zend/Cache/Storage/Adapter/Memcached.php
@@ -37,11 +37,32 @@ class Memcached extends AbstractAdapter implements
protected static $extMemcachedMajorVersion;
/**
- * The memcached resource
+ * Has this instance be initialized
*
- * @var MemcachedResource
+ * @var boolean
*/
- protected $memcachedResource;
+ protected $initialized = false;
+
+ /**
+ * The memcached resource manager
+ *
+ * @var null|MemcachedResourceManager
+ */
+ protected $resourceManager;
+
+ /**
+ * The memcached resource id
+ *
+ * @var null|string
+ */
+ protected $resourceId;
+
+ /**
+ * The namespace prefix
+ *
+ * @var string
+ */
+ protected $namespacePrefix = '';
/**
* Constructor
@@ -61,6 +82,12 @@ public function __construct($options = null)
}
parent::__construct($options);
+
+ // reset initialized flag on update option(s)
+ $initialized = & $this->initialized;
+ $this->getEventManager()->attach('option', function ($event) use (& $initialized) {
+ $initialized = false;
+ });
}
/**
@@ -70,45 +97,26 @@ public function __construct($options = null)
*/
protected function getMemcachedResource()
{
- if ($this->memcachedResource) {
- return $this->memcachedResource;
- }
+ if (!$this->initialized) {
+ $options = $this->getOptions();
- $options = $this->getOptions();
+ // get resource manager and resource id
+ $this->resourceManager = $options->getResourceManager();
+ $this->resourceId = $options->getResourceId();
- // use a configured resource or a new one
- $memcached = $options->getMemcachedResource() ?: new MemcachedResource();
-
- // init lib options
- if (static::$extMemcachedMajorVersion > 1) {
- $memcached->setOptions($options->getLibOptions());
- } else {
- foreach ($options->getLibOptions() as $k => $v) {
- $memcached->setOption($k, $v);
- }
- }
- $memcached->setOption(MemcachedResource::OPT_PREFIX_KEY, $options->getNamespace());
-
- // Allow updating namespace
- $this->getEventManager()->attach('option', function ($event) use ($memcached) {
- $params = $event->getParams();
- if (!isset($params['namespace'])) {
- // Cannot set lib options after initialization
- return;
+ // init namespace prefix
+ $namespace = $options->getNamespace();
+ if ($namespace !== '') {
+ $this->namespacePrefix = $namespace . $options->getNamespaceSeparator();
+ } else {
+ $this->namespacePrefix = '';
}
- $memcached->setOption(MemcachedResource::OPT_PREFIX_KEY, $params['namespace']);
- });
- // init servers
- $servers = $options->getServers();
- if ($servers) {
- $memcached->addServers($servers);
+ // update initialized flag
+ $this->initialized = true;
}
- // use the initialized resource
- $this->memcachedResource = $memcached;
-
- return $this->memcachedResource;
+ return $this->resourceManager->getResource($this->resourceId);
}
/* options */
@@ -210,12 +218,13 @@ public function getAvailableSpace()
*/
protected function internalGetItem(& $normalizedKey, & $success = null, & $casToken = null)
{
- $memc = $this->getMemcachedResource();
+ $memc = $this->getMemcachedResource();
+ $internalKey = $this->namespacePrefix . $normalizedKey;
if (func_num_args() > 2) {
- $result = $memc->get($normalizedKey, null, $casToken);
+ $result = $memc->get($internalKey, null, $casToken);
} else {
- $result = $memc->get($normalizedKey);
+ $result = $memc->get($internalKey);
}
$success = true;
@@ -242,12 +251,27 @@ protected function internalGetItem(& $normalizedKey, & $success = null, & $casTo
*/
protected function internalGetItems(array & $normalizedKeys)
{
- $memc = $this->getMemcachedResource();
+ $memc = $this->getMemcachedResource();
+
+ foreach ($normalizedKeys as & $normalizedKey) {
+ $normalizedKey = $this->namespacePrefix . $normalizedKey;
+ }
+
$result = $memc->getMulti($normalizedKeys);
if ($result === false) {
throw $this->getExceptionByResultCode($memc->getResultCode());
}
+ // remove namespace prefix from result
+ if ($result && $this->namespacePrefix !== '') {
+ $tmp = array();
+ $nsPrefixLength = strlen($this->namespacePrefix);
+ foreach ($result as $internalKey => & $value) {
+ $tmp[ substr($internalKey, $nsPrefixLength) ] = & $value;
+ }
+ $result = $tmp;
+ }
+
return $result;
}
@@ -261,7 +285,7 @@ protected function internalGetItems(array & $normalizedKeys)
protected function internalHasItem(& $normalizedKey)
{
$memc = $this->getMemcachedResource();
- $value = $memc->get($normalizedKey);
+ $value = $memc->get($this->namespacePrefix . $normalizedKey);
if ($value === false || $value === null) {
$rsCode = $memc->getResultCode();
if ($rsCode == MemcachedResource::RES_SUCCESS) {
@@ -285,13 +309,29 @@ protected function internalHasItem(& $normalizedKey)
*/
protected function internalHasItems(array & $normalizedKeys)
{
- $memc = $this->getMemcachedResource();
+ $memc = $this->getMemcachedResource();
+
+ foreach ($normalizedKeys as & $normalizedKey) {
+ $normalizedKey = $this->namespacePrefix . $normalizedKey;
+ }
+
$result = $memc->getMulti($normalizedKeys);
if ($result === false) {
throw $this->getExceptionByResultCode($memc->getResultCode());
}
- return array_keys($result);
+ // Convert to a simgle list
+ $result = array_keys($result);
+
+ // remove namespace prefix
+ if ($result && $this->namespacePrefix !== '') {
+ $nsPrefixLength = strlen($this->namespacePrefix);
+ foreach ($result as & $internalKey) {
+ $internalKey = substr($internalKey, $nsPrefixLength);
+ }
+ }
+
+ return $result;
}
/**
@@ -303,14 +343,29 @@ protected function internalHasItems(array & $normalizedKeys)
*/
protected function internalGetMetadatas(array & $normalizedKeys)
{
- $memc = $this->getMemcachedResource();
+ $memc = $this->getMemcachedResource();
+
+ foreach ($normalizedKeys as & $normalizedKey) {
+ $normalizedKey = $this->namespacePrefix . $normalizedKey;
+ }
+
$result = $memc->getMulti($normalizedKeys);
if ($result === false) {
throw $this->getExceptionByResultCode($memc->getResultCode());
}
- foreach ($result as & $value) {
- $value = array();
+ // remove namespace prefix and use an empty array as metadata
+ if ($this->namespacePrefix !== '') {
+ $tmp = array();
+ $nsPrefixLength = strlen($this->namespacePrefix);
+ foreach (array_keys($result) as $internalKey) {
+ $tmp[ substr($internalKey, $nsPrefixLength) ] = array();
+ }
+ $result = $tmp;
+ } else {
+ foreach ($result as & $value) {
+ $value = array();
+ }
}
return $result;
@@ -330,7 +385,7 @@ protected function internalSetItem(& $normalizedKey, & $value)
{
$memc = $this->getMemcachedResource();
$expiration = $this->expirationTime();
- if (!$memc->set($normalizedKey, $value, $expiration)) {
+ if (!$memc->set($this->namespacePrefix . $normalizedKey, $value, $expiration)) {
throw $this->getExceptionByResultCode($memc->getResultCode());
}
@@ -348,7 +403,13 @@ protected function internalSetItems(array & $normalizedKeyValuePairs)
{
$memc = $this->getMemcachedResource();
$expiration = $this->expirationTime();
- if (!$memc->setMulti($normalizedKeyValuePairs, $expiration)) {
+
+ $namespacedKeyValuePairs = array();
+ foreach ($normalizedKeyValuePairs as $normalizedKey => & $value) {
+ $namespacedKeyValuePairs[ $this->namespacePrefix . $normalizedKey ] = & $value;
+ }
+
+ if (!$memc->setMulti($namespacedKeyValuePairs, $expiration)) {
throw $this->getExceptionByResultCode($memc->getResultCode());
}
@@ -367,7 +428,7 @@ protected function internalAddItem(& $normalizedKey, & $value)
{
$memc = $this->getMemcachedResource();
$expiration = $this->expirationTime();
- if (!$memc->add($normalizedKey, $value, $expiration)) {
+ if (!$memc->add($this->namespacePrefix . $normalizedKey, $value, $expiration)) {
if ($memc->getResultCode() == MemcachedResource::RES_NOTSTORED) {
return false;
}
@@ -389,7 +450,7 @@ protected function internalReplaceItem(& $normalizedKey, & $value)
{
$memc = $this->getMemcachedResource();
$expiration = $this->expirationTime();
- if (!$memc->replace($normalizedKey, $value, $expiration)) {
+ if (!$memc->replace($this->namespacePrefix . $normalizedKey, $value, $expiration)) {
$rsCode = $memc->getResultCode();
if ($rsCode == MemcachedResource::RES_NOTSTORED) {
return false;
@@ -415,7 +476,7 @@ protected function internalCheckAndSetItem(& $token, & $normalizedKey, & $value)
{
$memc = $this->getMemcachedResource();
$expiration = $this->expirationTime();
- $result = $memc->cas($token, $normalizedKey, $value, $expiration);
+ $result = $memc->cas($token, $this->namespacePrefix . $normalizedKey, $value, $expiration);
if ($result === false) {
$rsCode = $memc->getResultCode();
@@ -438,7 +499,7 @@ protected function internalCheckAndSetItem(& $token, & $normalizedKey, & $value)
protected function internalRemoveItem(& $normalizedKey)
{
$memc = $this->getMemcachedResource();
- $result = $memc->delete($normalizedKey);
+ $result = $memc->delete($this->namespacePrefix . $normalizedKey);
if ($result === false) {
$rsCode = $memc->getResultCode();
@@ -466,7 +527,12 @@ protected function internalRemoveItems(array & $normalizedKeys)
return parent::internalRemoveItems($normalizedKeys);
}
- $memc = $this->getMemcachedResource();
+ $memc = $this->getMemcachedResource();
+
+ foreach ($normalizedKeys as & $normalizedKey) {
+ $normalizedKey = $this->namespacePrefix . $normalizedKey;
+ }
+
$rsCodes = $memc->deleteMulti($normalizedKeys);
$missingKeys = array();
@@ -479,6 +545,14 @@ protected function internalRemoveItems(array & $normalizedKeys)
}
}
+ // remove namespace prefix
+ if ($missingKeys && $this->namespacePrefix !== '') {
+ $nsPrefixLength = strlen($this->namespacePrefix);
+ foreach ($missingKeys as & $missingKey) {
+ $missingKey = substr($missingKey, $nsPrefixLength);
+ }
+ }
+
return $missingKeys;
}
@@ -492,9 +566,10 @@ protected function internalRemoveItems(array & $normalizedKeys)
*/
protected function internalIncrementItem(& $normalizedKey, & $value)
{
- $memc = $this->getMemcachedResource();
- $value = (int) $value;
- $newValue = $memc->increment($normalizedKey, $value);
+ $memc = $this->getMemcachedResource();
+ $internalKey = $this->namespacePrefix . $normalizedKey;
+ $value = (int) $value;
+ $newValue = $memc->increment($internalKey, $value);
if ($newValue === false) {
$rsCode = $memc->getResultCode();
@@ -502,7 +577,7 @@ protected function internalIncrementItem(& $normalizedKey, & $value)
// initial value
if ($rsCode == MemcachedResource::RES_NOTFOUND) {
$newValue = $value;
- $memc->add($normalizedKey, $newValue, $this->expirationTime());
+ $memc->add($internalKey, $newValue, $this->expirationTime());
$rsCode = $memc->getResultCode();
}
@@ -524,9 +599,10 @@ protected function internalIncrementItem(& $normalizedKey, & $value)
*/
protected function internalDecrementItem(& $normalizedKey, & $value)
{
- $memc = $this->getMemcachedResource();
- $value = (int)$value;
- $newValue = $memc->decrement($normalizedKey, $value);
+ $memc = $this->getMemcachedResource();
+ $internalKey = $this->namespacePrefix . $normalizedKey;
+ $value = (int)$value;
+ $newValue = $memc->decrement($internalKey, $value);
if ($newValue === false) {
$rsCode = $memc->getResultCode();
@@ -534,7 +610,7 @@ protected function internalDecrementItem(& $normalizedKey, & $value)
// initial value
if ($rsCode == MemcachedResource::RES_NOTFOUND) {
$newValue = -$value;
- $memc->add($normalizedKey, $newValue, $this->expirationTime());
+ $memc->add($internalKey, $newValue, $this->expirationTime());
$rsCode = $memc->getResultCode();
}
View
328 library/Zend/Cache/Storage/Adapter/MemcachedOptions.php
@@ -23,31 +23,24 @@
class MemcachedOptions extends AdapterOptions
{
/**
- * A memcached resource to share
- *
- * @var null|MemcachedResource
+ * The namespace separator
+ * @var string
*/
- protected $memcachedResource;
+ protected $namespaceSeparator = ':';
/**
- * List of memcached servers to add on initialize
+ * The memcached resource manager
*
- * @var string
+ * @var null|MemcachedResourceManager
*/
- protected $servers = array(
- array(
- 'host' => '127.0.0.1',
- 'port' => 11211,
- 'weight' => 0,
- ),
- );
+ protected $resourceManager;
/**
- * List of Libmemcached options to set on initialize
+ * The resource id of the resource manager
*
- * @var array
+ * @var string
*/
- protected $libOptions = array();
+ protected $resourceId = 'default';
/**
* Set namespace.
@@ -73,16 +66,51 @@ public function setNamespace($namespace)
}
/**
+ * Set namespace separator
+ *
+ * @param string $namespaceSeparator
+ * @return MemcachedOptions
+ */
+ public function setNamespaceSeparator($namespaceSeparator)
+ {
+ $namespaceSeparator = (string) $namespaceSeparator;
+ if ($this->namespaceSeparator !== $namespaceSeparator) {
+ $this->triggerOptionEvent('namespace_separator', $namespaceSeparator);
+ $this->namespaceSeparator = $namespaceSeparator;
+ }
+ return $this;
+ }
+
+ /**
+ * Get namespace separator
+ *
+ * @return string
+ */
+ public function getNamespaceSeparator()
+ {
+ return $this->namespaceSeparator;
+ }
+
+ /**
* A memcached resource to share
*
* @param null|MemcachedResource $memcachedResource
* @return MemcachedOptions
+ * @deprecated Please use the resource manager instead
*/
public function setMemcachedResource(MemcachedResource $memcachedResource = null)
{
- if ($this->memcachedResource !== $memcachedResource) {
+ trigger_error(
+ 'This method is deprecated and will be removed in the feature'
+ . ', please use the resource manager instead',
+ E_USER_DEPRECATED
+ );
+
+ if ($memcachedResource !== null) {
$this->triggerOptionEvent('memcached_resource', $memcachedResource);
- $this->memcachedResource = $memcachedResource;
+ $resourceManager = $this->getResourceManager();
+ $resourceId = $this->getResourceId();
+ $resourceManager->setResource($resourceId, $memcachedResource);
}
return $this;
}
@@ -90,117 +118,133 @@ public function setMemcachedResource(MemcachedResource $memcachedResource = null
/**
* Get memcached resource to share
*
- * @return null|MemcachedResource
+ * @return MemcachedResource
+ * @deprecated Please use the resource manager instead
*/
public function getMemcachedResource()
{
- return $this->memcachedResource;
+ trigger_error(
+ 'This method is deprecated and will be removed in the feature'
+ . ', please use the resource manager instead',
+ E_USER_DEPRECATED
+ );
+
+ return $this->resourceManager->getResource($this->getResourceId());
}
/**
- * Add a server to the list
+ * Set the memcached resource manager to use
*
- * @param string $host
- * @param int $port
- * @param int $weight
+ * @param null|MemcachedResourceManager $resourceManager
* @return MemcachedOptions
*/
- public function addServer($host, $port = 11211, $weight = 0)
+ public function setResourceManager(MemcachedResourceManager $resourceManager = null)
{
- $new = array(
- 'host' => $host,
- 'port' => $port,
- 'weight' => $weight
- );
-
- foreach ($this->servers as $server) {
- $diff = array_diff($new, $server);
- if (empty($diff)) {
- // Done -- server is already present
- return $this;
- }
+ if ($this->resourceManager !== $resourceManager) {
+ $this->triggerOptionEvent('resource_manager', $resourceManager);
+ $this->resourceManager = $resourceManager;
}
-
- $this->servers[] = $new;
return $this;
}
/**
- * Set a list of memcached servers to add on initialize
+ * Get the memcached resource manager
*
- * @param string|array $servers list of servers
- * @return MemcachedOptions
- * @throws Exception\InvalidArgumentException
+ * @return MemcachedResourceManager
*/
- public function setServers($servers)
+ public function getResourceManager()
{
- if (!is_array($servers)) {
- return $this->setServers(explode(',', $servers));
+ if (!$this->resourceManager) {
+ $this->resourceManager = new MemcachedResourceManager();
}
+ return $this->resourceManager;
+ }
- $this->servers = array();
- foreach ($servers as $server) {
- // default values
- $host = null;
- $port = 11211;
- $weight = 1;
-
- if (!is_array($server) && !is_string($server)) {
- throw new Exception\InvalidArgumentException('Invalid server specification provided; must be an array or string');
- }
-
- // parse a single server from an array
- if (is_array($server)) {
- if (!isset($server[0]) && !isset($server['host'])) {
- throw new Exception\InvalidArgumentException("Invalid list of servers given");
- }
-
- // array(array(<host>[, <port>[, <weight>]])[, ...])
- if (isset($server[0])) {
- $host = (string) $server[0];
- $port = isset($server[1]) ? (int) $server[1] : $port;
- $weight = isset($server[2]) ? (int) $server[2] : $weight;
- }
-
- // array(array('host' => <host>[, 'port' => <port>[, 'weight' => <weight>]])[, ...])
- if (!isset($server[0]) && isset($server['host'])) {
- $host = (string)$server['host'];
- $port = isset($server['port']) ? (int) $server['port'] : $port;
- $weight = isset($server['weight']) ? (int) $server['weight'] : $weight;
- }
- }
+ /**
+ * Get the memcached resource id
+ *
+ * @return string
+ */
+ public function getResourceId()
+ {
+ return $this->resourceId;
+ }
- // parse a single server from a string
- if (!is_array($server)) {
- $server = trim($server);
- if (strpos($server, '://') === false) {
- $server = 'tcp://' . $server;
- }
+ /**
+ * Set the memcached resource id
+ *
+ * @param string $resourceId
+ * @return MemcachedOptions
+ */
+ public function setResourceId($resourceId)
+ {
+ $resourceId = (string) $resourceId;
+ if ($this->resourceId !== $resourceId) {
+ $this->triggerOptionEvent('resource_id', $resourceId);
+ $this->resourceId = $resourceId;
+ }
+ return $this;
+ }
- $server = parse_url($server);
- if (!$server) {
- throw new Exception\InvalidArgumentException("Invalid list of servers given");
- }
+ /**
+ * Get the persistent id
+ *
+ * @return string
+ */
+ public function getPersistentId()
+ {
+ return $this->getResourceManager()->getPersistentId($this->getResourceId());
+ }
- $host = $server['host'];
- $port = isset($server['port']) ? (int)$server['port'] : $port;
+ /**
+ * Set the persistent id
+ *
+ * @param string $persistentId
+ * @return MemcachedOptions
+ */
+ public function setPersistentId($persistentId)
+ {
+ $this->triggerOptionEvent('persistent_id', $persistentId);
+ $this->getResourceManager()->setPersistentId($this->getPersistentId(), $persistentId);
+ return $this;
+ }
- if (isset($server['query'])) {
- $query = null;
- parse_str($server['query'], $query);
- if (isset($query['weight'])) {
- $weight = (int)$query['weight'];
- }
- }
- }
+ /**
+ * Add a server to the list
+ *
+ * @param string $host
+ * @param int $port
+ * @param int $weight
+ * @return MemcachedOptions
+ * @deprecated Please use the resource manager instead
+ */
+ public function addServer($host, $port = 11211, $weight = 0)
+ {
+ trigger_error(
+ 'This method is deprecated and will be removed in the feature'
+ . ', please use the resource manager instead',
+ E_USER_DEPRECATED
+ );
- if (!$host) {
- throw new Exception\InvalidArgumentException('The list of servers must contain a host value.');
- }
+ $this->getResourceManager()->addServer($this->getResourceId(), array(
+ 'host' => $host,
+ 'port' => $port,
+ 'weight' => $weight
+ ));
- $this->addServer($host, $port, $weight);
- }
+ return $this;
+ }
+ /**
+ * Set a list of memcached servers to add on initialize
+ *
+ * @param string|array $servers list of servers
+ * @return MemcachedOptions
+ * @throws Exception\InvalidArgumentException
+ */
+ public function setServers($servers)
+ {
+ $this->getResourceManager()->setServers($this->getResourceId(), $servers);
return $this;
}
@@ -211,27 +255,19 @@ public function setServers($servers)
*/
public function getServers()
{
- return $this->servers;
+ return $this->getResourceManager()->getServers($this->getResourceId());
}
/**
- * Set libmemcached options
- *
- * @param array $libOptions
- * @return MemcachedOptions
- * @link http://php.net/manual/memcached.constants.php
- */
+ * Set libmemcached options
+ *
+ * @param array $libOptions
+ * @return MemcachedOptions
+ * @link http://php.net/manual/memcached.constants.php
+ */
public function setLibOptions(array $libOptions)
{
- $normalizedOptions = array();
- foreach ($libOptions as $key => $value) {
- $this->normalizeLibOptionKey($key);
- $normalizedOptions[$key] = $value;
- }
-
- $this->triggerOptionEvent('lib_options', $normalizedOptions);
- $this->libOptions = array_diff_key($this->libOptions, $normalizedOptions) + $normalizedOptions;
-
+ $this->getResourceManager()->setLibOptions($this->getResourceId(), $libOptions);
return $this;
}
@@ -239,16 +275,20 @@ public function setLibOptions(array $libOptions)
* Set libmemcached option
*
* @param string|int $key
- * @param mixed $value
+ * @param mixed $value
* @return MemcachedOptions
* @link http://php.net/manual/memcached.constants.php
+ * @deprecated Please use lib_options or the resource manager instead
*/
public function setLibOption($key, $value)
{
- $this->normalizeLibOptionKey($key);
- $this->triggerOptionEvent('lib_options', array($key, $value));
- $this->libOptions[$key] = $value;
+ trigger_error(
+ 'This method is deprecated and will be removed in the feature'
+ . ', please use "lib_options" or the resource manager instead',
+ E_USER_DEPRECATED
+ );
+ $this->getResourceManager()->setLibOption($this->getResourceId(), $key, $value);
return $this;
}
@@ -260,41 +300,25 @@ public function setLibOption($key, $value)
*/
public function getLibOptions()
{
- return $this->libOptions;
+ return $this->getResourceManager()->getLibOptions($this->getResourceId());
}
/**
- * Get libmemcached option
- *
- * @param string|int $key
- * @return mixed
- * @link http://php.net/manual/memcached.constants.php
- */
+ * Get libmemcached option
+ *
+ * @param string|int $key
+ * @return mixed
+ * @link http://php.net/manual/memcached.constants.php
+ * @deprecated Please use lib_options or the resource manager instead
+ */
public function getLibOption($key)
{
- $this->normalizeLibOptionKey($key);
- if (isset($this->libOptions[$key])) {
- return $this->libOptions[$key];
- }
- return null;
- }
+ trigger_error(
+ 'This method is deprecated and will be removed in the feature'
+ . ', please use "lib_options" or the resource manager instead',
+ E_USER_DEPRECATED
+ );
- /**
- * Normalize libmemcached option name into it's constant value
- *
- * @param string|int $key
- * @throws Exception\InvalidArgumentException
- */
- protected function normalizeLibOptionKey(& $key)
- {
- if (is_string($key)) {
- $const = 'Memcached::OPT_' . str_replace(array(' ', '-'), '_', strtoupper($key));
- if (!defined($const)) {
- throw new Exception\InvalidArgumentException("Unknown libmemcached option '{$key}' ({$const})");
- }
- $key = constant($const);
- } else {
- $key = (int) $key;
- }
+ return $this->getResourceManager()->getLibOption($this->getResourceId(), $key);
}
}
View
554 library/Zend/Cache/Storage/Adapter/MemcachedResourceManager.php
@@ -0,0 +1,554 @@
+<?php
+/**
+ * Zend Framework (http://framework.zend.com/)
+ *
+ * @link http://github.com/zendframework/zf2 for the canonical source repository
+ * @copyright Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license http://framework.zend.com/license/new-bsd New BSD License
+ * @package Zend_Cache
+ */
+
+namespace Zend\Cache\Storage\Adapter;
+
+use Memcached as MemcachedResource;
+use ReflectionClass;
+use Traversable;
+use Zend\Cache\Exception;
+use Zend\Stdlib\ArrayUtils;
+
+/**
+ * This is a resource manager for memcached
+ *
+ * @category Zend
+ * @package Zend_Cache
+ * @subpackage Storage
+ */
+class MemcachedResourceManager
+{
+
+ /**
+ * Registered resources
+ *
+ * @var array
+ */
+ protected $resources = array();
+
+ /**
+ * Check if a resource exists
+ *
+ * @param string $id
+ * @return boolean
+ */
+ public function hasResource($id)
+ {
+ return isset($this->resources[$id]);
+ }
+
+ /**
+ * Gets a memcached resource
+ *
+ * @param string $id
+ * @return MemcachedResource
+ * @throws Exception\RuntimeException
+ */
+ public function getResource($id)
+ {
+ if (!$this->hasResource($id)) {
+ throw new Exception\RuntimeException("No resource with id '{$id}'");
+ }
+
+ $resource = $this->resources[$id];
+ if ($resource instanceof MemcachedResource) {
+ return $resource;
+ }
+
+ if ($resource['persistent_id'] !== '') {
+ $memc = new MemcachedResource($resource['persistent_id']);
+ } else {
+ $memc = new MemcachedResource();
+ }
+
+ if (method_exists($memc, 'setOptions')) {
+ $memc->setOptions($resource['lib_options']);
+ } else {
+ foreach ($resource['lib_options'] as $k => $v) {
+ $memc->setOption($k, $v);
+ }
+ }
+
+ // merge and add servers (with persistence id servers could be added already)
+ $servers = array_udiff($resource['servers'], $memc->getServerList(), array($this, 'compareServers'));
+ if ($servers) {
+ $memc->addServers($servers);
+ }
+
+ // buffer and return
+ $this->resources[$id] = $memc;
+ return $memc;
+ }
+
+ /**
+ * Set a resource
+ *
+ * @param string $id
+ * @param array|Traversable|MemcachedResource $resource
+ * @return MemcachedResourceManager Fluent interface
+ */
+ public function setResource($id, $resource)
+ {
+ $id = (string) $id;
+
+ if ( !($resource instanceof MemcachedResource) ) {
+ if ($resource instanceof Traversable) {
+ $resource = ArrayUtils::iteratorToArray($resource);
+ } elseif (!is_array($resource)) {
+ throw new Exception\InvalidArgumentException(
+ 'Resource must be an instance of Memcached or an array or Traversable'
+ );
+ }
+
+ $resource = array_merge(array(
+ 'persistent_id' => '',
+ 'lib_options' => array(),
+ 'servers' => array(),
+ ), $resource);
+
+ // normalize and validate params
+ $this->normalizePersistentId($resource['persistent_id']);
+ $this->normalizeLibOptions($resource['lib_options']);
+ $this->normalizeServers($resource['servers']);
+ }
+
+ $this->resources[$id] = $resource;
+ return $this;
+ }
+
+ /**
+ * Remove a resource
+ *
+ * @param string $id
+ * @return MemcachedResourceManager Fluent interface
+ */
+ public function removeResource($id)
+ {
+ unset($this->resources[$id]);
+ return $this;
+ }
+
+ /**
+ * Set the persistent id
+ *
+ * @param string $id
+ * @param string $persistentId
+ * @return MemcachedResourceManager Fluent interface
+ * @throws Exception\RuntimeException
+ */
+ public function setPersistentId($id, $persistentId)
+ {
+ if (!$this->hasResource($id)) {
+ return $this->setResource($id, array(
+ 'persistent_id' => $persistentId
+ ));
+ }
+
+ $resource = & $this->resources[$id];
+ if ($resource instanceof MemcachedResource) {
+ throw new Exception\RuntimeException(
+ "Can't change persistent id of resource {$id} after instanziation"
+ );
+ }
+
+ $this->normalizePersistentId($persistentId);
+ $resource['persistent_id'] = $persistentId;
+
+ return $this;
+ }
+
+ /**
+ * Get the persistent id
+ *
+ * @param string $id
+ * @return string
+ * @throws Exception\RuntimeException
+ */
+ public function getPersistentId($id)
+ {
+ if (!$this->hasResource($id)) {
+ throw new Exception\RuntimeException("No resource with id '{$id}'");
+ }
+
+ $resource = & $this->resources[$id];
+
+ if ($resource instanceof MemcachedResource) {
+ throw new Exception\RuntimeException(
+ "Can't get persistent id of an instantiated memcached resource"
+ );
+ }
+
+ return $resource['persistent_id'];
+ }
+
+ /**
+ * Normalize the persistent id
+ *
+ * @param string $persistentId
+ */
+ protected function normalizePersistentId(& $persistentId)
+ {
+ $persistentId = (string) $persistentId;
+ }
+
+ /**
+ * Set Libmemcached options
+ *
+ * @param string $id
+ * @param array $libOptions
+ * @return MemcachedResourceManager Fluent interface
+ */
+ public function setLibOptions($id, array $libOptions)
+ {
+ if (!$this->hasResource($id)) {
+ return $this->setResource($id, array(
+ 'lib_options' => $libOptions
+ ));
+ }
+
+ $this->normalizeLibOptions($libOptions);
+
+ $resource = & $this->resources[$id];
+ if ($resource instanceof MemcachedResource) {
+ if (method_exists($resource, 'setOptions')) {
+ $resource->setOptions($resource);
+ } else {
+ foreach ($libOptions as $key => $value) {
+ $resource->setOption($key, $value);
+ }
+ }
+ } else {
+ $resource['lib_options'] = $libOptions;
+ }
+
+ return $this;
+ }
+
+ /**
+ * Get Libmemcached options
+ *
+ * @param string $id
+ * @return array
+ * @throws Exception\RuntimeException
+ */
+ public function getLibOptions($id)
+ {
+ if (!$this->hasResource($id)) {
+ throw new Exception\RuntimeException("No resource with id '{$id}'");
+ }
+
+ $resource = & $this->resources[$id];
+
+ if ($resource instanceof MemcachedResource) {
+ $libOptions = array();
+ $reflection = new ReflectionClass('Memcached');
+ $constants = $reflection->getConstants();
+ foreach ($constants as $constName => $constValue) {
+ if (substr($constName, 0, 4) == 'OPT_') {
+ $libOptions[ $constValue ] = $resource->getOption($constValue);
+ }
+ }
+ return $libOptions;
+ }
+ return $resource['lib_options'];
+ }
+
+ /**
+ * Set one Libmemcached option
+ *
+ * @param string $id
+ * @param string|int $key
+ * @param mixed $value
+ * @return MemcachedResourceManager Fluent interface
+ */
+ public function setLibOption($id, $key, $value)
+ {
+ return $this->setLibOptions($id, array($key => $value));
+ }
+
+ /**
+ * Get one Libmemcached option
+ *
+ * @param string $id
+ * @param string|int $key
+ * @return mixed
+ * @throws Exception\RuntimeException
+ */
+ public function getLibOption($id, $key)
+ {
+ if (!$this->hasResource($id)) {
+ throw new Exception\RuntimeException("No resource with id '{$id}'");
+ }
+
+ $constValue = $this->normalizeLibOptionKey($key);
+ $resource = & $this->resources[$id];
+
+ if ($resource instanceof MemcachedResource) {
+ return $resource->getOption($constValue);
+ }
+
+ return isset($resource['lib_options'][$constValue]) ? $resource['lib_options'][$constValue] : null;
+ }
+
+ /**
+ * Normalize libmemcached options
+ *
+ * @param array|Traversable $libOptions
+ * @throws Exception\InvalidArgumentException
+ */
+ protected function normalizeLibOptions(& $libOptions)
+ {
+ if (!is_array($libOptions) && !($libOptions instanceof Traversable)) {
+ throw new Exception\InvalidArgumentException(
+ "Lib-Options must be an array or an instance of Traversable"
+ );
+ }
+
+ $result = array();
+ foreach ($libOptions as $key => $value) {
+ $this->normalizeLibOptionKey($key);
+ $result[$key] = $value;
+ }
+
+ $libOptions = $result;
+ }
+
+ /**
+ * Convert option name into it's constant value
+ *
+ * @param string|int $key
+ * @throws Exception\InvalidArgumentException
+ */
+ protected function normalizeLibOptionKey(& $key)
+ {
+ // convert option name into it's constant value
+ if (is_string($key)) {
+ $const = 'Memcached::OPT_' . str_replace(array(' ', '-'), '_', strtoupper($key));
+ if (!defined($const)) {
+ throw new Exception\InvalidArgumentException("Unknown libmemcached option '{$key}' ({$const})");
+ }
+ $key = constant($const);
+ } else {
+ $key = (int) $key;
+ }
+ }
+
+ /**
+ * Set servers
+ *
+ * $servers can be an array list or a comma separated list of servers.
+ * One server in the list can be descripted as follows:
+ * - URI: [tcp://]<host>[:<port>][?weight=<weight>]
+ * - Assoc: array('host' => <host>[, 'port' => <port>][, 'weight' => <weight>])
+ * - List: array(<host>[, <port>][, <weight>])
+ *
+ * @param string $id
+ * @param string|array $servers
+ * @return MemcachedResourceManager
+ */
+ public function setServers($id, $servers)
+ {
+ if (!$this->hasResource($id)) {
+ return $this->setResource($id, array(
+ 'servers' => $servers
+ ));
+ }
+
+ $this->normalizeServers($servers);
+
+ $resource = & $this->resources[$id];
+ if ($resource instanceof MemcachedResource) {
+ // don't add servers twice
+ $servers = array_udiff($servers, $resource->getServerList(), array($this, 'compareServers'));
+ if ($servers) {
+ $resource->addServers($servers);
+ }
+ } else {
+ $resource['servers'] = $servers;
+ }
+
+ return $this;
+ }
+
+ /**
+ * Get servers
+ * @param string $id
+ * @throws Exception\RuntimeException
+ * @return array array('host' => <host>, 'port' => <port>, 'weight' => <weight>)
+ */
+ public function getServers($id)
+ {
+ if (!$this->hasResource($id)) {
+ throw new Exception\RuntimeException("No resource with id '{$id}'");
+ }
+
+ $resource = & $this->resources[$id];
+
+ if ($resource instanceof MemcachedResource) {
+ return $resource->getServerList();
+ }
+ return $resource['servers'];
+ }
+
+ /**
+ * Add servers
+ *
+ * @param string $id
+ * @param string|array $servers
+ * @return MemcachedResourceManager
+ */
+ public function addServers($id, $servers)
+ {
+ if (!$this->hasResource($id)) {
+ return $this->setResource($id, array(
+ 'servers' => $servers
+ ));
+ }
+
+ $this->normalizeServers($servers);
+
+ $resource = & $this->resources[$id];
+ if ($resource instanceof MemcachedResource) {
+ // don't add servers twice
+ $servers = array_udiff($servers, $resource->getServerList(), array($this, 'compareServers'));
+ if ($servers) {
+ $resource->addServers($servers);
+ }
+ } else {
+ // don't add servers twice
+ $resource['servers'] = array_merge(
+ $resource['servers'],
+ array_udiff($servers, $resource['servers'], array($this, 'compareServers'))
+ );
+ }
+
+ return $this;
+ }
+
+ /**
+ * Add one server
+ *
+ * @param string $id
+ * @param string|array $server
+ * @return MemcachedResourceManager
+ */
+ public function addServer($id, $server)
+ {
+ return $this->addServers($id, array($server));
+ }
+
+ /**
+ * Normalize a list of servers into the following format:
+ * array(array('host' => <host>, 'port' => <port>, 'weight' => <weight>)[, ...])
+ *
+ * @param string|array $servers
+ */
+ protected function normalizeServers(& $servers)
+ {
+ if (!is_array($servers) && !$servers instanceof Traversable) {
+ // Convert string into a list of servers
+ $servers = explode(',', $servers);
+ }
+
+ $result = array();
+ foreach ($servers as $server) {
+ $this->normalizeServer($server);
+ $result[ $server['host'] . ':' . $server['port'] ] = $server;
+ }
+
+ $servers = array_values($result);
+ }
+
+ /**
+ * Normalize one server into the following format:
+ * array('host' => <host>, 'port' => <port>, 'weight' => <weight>)
+ *
+ * @param string|array $server
+ * @throws Exception\InvalidArgumentException
+ */
+ protected function normalizeServer(& $server)
+ {
+ $host = null;
+ $port = 11211;
+ $weight = 0;
+
+ // convert a single server into an array
+ if ($server instanceof Traversable) {
+ $server = ArrayUtils::iteratorToArray($server);
+ }
+
+ if (is_array($server)) {
+ // array(<host>[, <port>[, <weight>]])
+ if (isset($server[0])) {
+ $host = (string) $server[0];
+ $port = isset($server[1]) ? (int) $server[1] : $port;
+ $weight = isset($server[2]) ? (int) $server[2] : $weight;
+ }
+
+ // array('host' => <host>[, 'port' => <port>[, 'weight' => <weight>]])
+ if (!isset($server[0]) && isset($server['host'])) {
+ $host = (string)$server['host'];
+ $port = isset($server['port']) ? (int) $server['port'] : $port;
+ $weight = isset($server['weight']) ? (int) $server['weight'] : $weight;
+ }
+
+ } else {
+ // parse server from URI host{:?port}{?weight}
+ $server = trim($server);
+ if (strpos($server, '://') === false) {
+ $server = 'tcp://' . $server;
+ }