Skip to content
This repository

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse code

Guzzle 2.0

Adopting composer for dependency management
Updating LICENSE, travis build file, making better use of git ignores, and remove unused build target
Removing @author tags.  Use the commit history for a changelog.
Moving files from build folder to /
Adding min build target to product a Guzzle only phar with no autoloader
[Common] Accepting ZF1 or ZF2 cache in ZendCacheAdapter
[Common] Optimizing Stream wrapper and EntityBody abstractions.
[Common] [Http] Migrating from Guzzle event system to the Symfony2 event dispatcher
[Common] Moved Inflector and Inspector to Service namespace
[Http] Simplifying Guzzle\Guzzle curl detection
[Http] Removing Guzzle\Http\Pool and now using Guzzle\Http\Curl\CurlMulti
[Http] The helper methods from Guzzle\Http\Message\RequestFactory have been removed to prevent confusion and encourage developers to use Guzzle\Http\Client to create requests.
[Http] Clients can now send one or more requests in an array using the send() method, so the batch() method was removed.
[Http] Updating curl multi to allow blocking calls while sending other transfers
[Http] Making the Request::hasHeader method more intuitive.  Guzzle\Http\Message\AbstractMessage::hasHeader() now returns true if the header is found using exact matching.  If the header is found using a regex or case-insensitive match, then it will return the name of the found header.
[Http] Removing content-type guessing from EntityBody based on file extension and solely using finfo.
[Http] Adding basic auth plugin
[Http] Cleaning up CookieJar and CurlMulti
[Http] Removing custom rawurlencode from QueryString because PHP 5.3 now properly deals with tilde characters.
[Http] Minor optimization to parsing messages in RequestFactory
[Http] Adding Guzzle\Http\Client for developers that don't need commands or service descriptions
[Http] Making it easier to set a global User-Agent header for a Guzzle\Http\Client
[Http] Fixing the discrepancies between the ClientInterface and Guzzle\Http\Client
[Http] Adding the ability to set and retrieve tokenized headers from Requests and Responses
[Service] Ditching NIH filters and using the Symfony2 validator
[Service] Moving most service building logic to the ServiceBuilder::factory method so that it is easier to build custom config readers.
[Service] Allowing deep nested command inheritance.
[Service] Cleaning up Inflector caching.
[Service] Getting rid of concept of can_batch because everything is now sent in parallel.
[Service] Adding a JSON description builder.
[Service] Cleaning up ResourceIteratorApplyBatched.
[Service] Removing caching stuff from ServiceBuilder because the data being cached is extremely fast to generate.
[Service] Added a method to serialize the ServiceDescription in case a ServiceDescription needs to be cached in an application.
[Service] Making description builders use static methods.
[Service] Adding support to include other description files for XML and JSON description builders.
[Service] Adding support for filters to ApiCommands
[Service] Using {{}} instead of $. to reference other services as a dependency for another service
  • Loading branch information...
commit 4c46e7701530f45e7893d03537b05073a3ea639e 1 parent 85dae7d
Michael Dowling authored January 14, 2012

Showing 231 changed files with 6,036 additions and 18,599 deletions. Show diff stats Hide diff stats

  1. 22  .gitignore
  2. 9  .gitmodules
  3. 8  .travis.yml
  4. 2  LICENSE
  5. 34  README.md
  6. 24  autoload.php
  7. 42  build.xml
  8. 22  build/autoload.php
  9. 53  build/build.xml
  10. 65  composer.json
  11. 2  phpunit.xml.dist
  12. 55  src/Guzzle/Common/AbstractHasDispatcher.php
  13. 10  src/Guzzle/Common/Cache/AbstractCacheAdapter.php
  14. 2  src/Guzzle/Common/Cache/CacheAdapterInterface.php
  15. 36  src/Guzzle/Common/Cache/DoctrineCacheAdapter.php
  16. 47  src/Guzzle/Common/Cache/ZendCacheAdapter.php
  17. 15  src/Guzzle/Common/Collection.php
  18. 66  src/Guzzle/Common/Event.php
  19. 30  src/Guzzle/Common/Event/AbstractSubject.php
  20. 234  src/Guzzle/Common/Event/EventManager.php
  21. 22  src/Guzzle/Common/Event/Observer.php
  22. 18  src/Guzzle/Common/Event/Subject.php
  23. 58  src/Guzzle/Common/ExceptionCollection.php
  24. 77  src/Guzzle/Common/Filter/AbstractFilter.php
  25. 24  src/Guzzle/Common/Filter/ArrayFilter.php
  26. 33  src/Guzzle/Common/Filter/BooleanFilter.php
  27. 40  src/Guzzle/Common/Filter/ClassFilter.php
  28. 34  src/Guzzle/Common/Filter/ClosureFilter.php
  29. 36  src/Guzzle/Common/Filter/DateFilter.php
  30. 39  src/Guzzle/Common/Filter/EnumFilter.php
  31. 22  src/Guzzle/Common/Filter/FilterInterface.php
  32. 25  src/Guzzle/Common/Filter/FloatFilter.php
  33. 25  src/Guzzle/Common/Filter/IntegerFilter.php
  34. 36  src/Guzzle/Common/Filter/RegexFilter.php
  35. 25  src/Guzzle/Common/Filter/StringFilter.php
  36. 31  src/Guzzle/Common/Filter/TimestampFilter.php
  37. 12  src/Guzzle/Common/GuzzleException.php
  38. 10  src/Guzzle/Common/GuzzleExceptionInterface.php
  39. 42  src/Guzzle/Common/HasDispatcherInterface.php
  40. 102  src/Guzzle/Common/Inflector.php
  41. 9  src/Guzzle/Common/Log/AbstractLogAdapter.php
  42. 9  src/Guzzle/Common/Log/ClosureLogAdapter.php
  43. 6  src/Guzzle/Common/Log/LogAdapterInterface.php
  44. 8  src/Guzzle/Common/Log/MonologLogAdapter.php
  45. 19  src/Guzzle/Common/Log/ZendLogAdapter.php
  46. 91  src/Guzzle/Common/NullObject.php
  47. 188  src/Guzzle/Common/Stream.php
  48. 3  src/Guzzle/Common/XmlElement.php
  49. 60  src/Guzzle/Guzzle.php
  50. 391  src/Guzzle/Http/Client.php
  51. 200  src/Guzzle/Http/ClientInterface.php
  52. 10  src/Guzzle/Http/Cookie.php
  53. 23  src/Guzzle/Http/CookieJar/ArrayCookieJar.php
  54. 2  src/Guzzle/Http/CookieJar/CookieJarInterface.php
  55. 8  src/Guzzle/Http/CookieJar/FileCookieJar.php
  56. 22  src/Guzzle/Http/Curl/CurlException.php
  57. 474  src/Guzzle/Http/Curl/CurlFactory.php
  58. 32  src/Guzzle/Http/Curl/CurlFactoryInterface.php
  59. 416  src/Guzzle/Http/Curl/CurlHandle.php
  60. 485  src/Guzzle/Http/Curl/CurlMulti.php
  61. 37  src/Guzzle/Http/{Pool/PoolInterface.php → Curl/CurlMultiInterface.php}
  62. 130  src/Guzzle/Http/EntityBody.php
  63. 6  src/Guzzle/Http/HttpException.php
  64. 144  src/Guzzle/Http/Message/AbstractMessage.php
  65. 2  src/Guzzle/Http/Message/BadResponseException.php
  66. 226  src/Guzzle/Http/Message/EntityEnclosingRequest.php
  67. 48  src/Guzzle/Http/Message/EntityEnclosingRequestInterface.php
  68. 76  src/Guzzle/Http/Message/MessageInterface.php
  69. 461  src/Guzzle/Http/Message/Request.php
  70. 6  src/Guzzle/Http/Message/RequestException.php
  71. 113  src/Guzzle/Http/Message/RequestFactory.php
  72. 66  src/Guzzle/Http/Message/RequestInterface.php
  73. 38  src/Guzzle/Http/Message/Response.php
  74. 46  src/Guzzle/Http/Plugin/BasicAuthPlugin.php
  75. 174  src/Guzzle/Http/Plugin/CachePlugin.php
  76. 126  src/Guzzle/Http/Plugin/CookiePlugin.php
  77. 118  src/Guzzle/Http/Plugin/ExponentialBackoffPlugin.php
  78. 22  src/Guzzle/Http/Plugin/HistoryPlugin.php
  79. 167  src/Guzzle/Http/Plugin/LogPlugin.php
  80. 45  src/Guzzle/Http/Plugin/Md5ValidatorPlugin.php
  81. 54  src/Guzzle/{Service → Http}/Plugin/MockPlugin.php
  82. 268  src/Guzzle/Http/Pool/Pool.php
  83. 63  src/Guzzle/Http/Pool/PoolRequestException.php
  84. 63  src/Guzzle/Http/QueryString.php
  85. 27  src/Guzzle/Http/Url.php
  86. 399  src/Guzzle/Service/Client.php
  87. 199  src/Guzzle/Service/ClientInterface.php
  88. 46  src/Guzzle/Service/Command/AbstractCommand.php
  89. 16  src/Guzzle/Service/Command/ClosureCommand.php
  90. 9  src/Guzzle/Service/Command/CommandInterface.php
  91. 109  src/Guzzle/Service/Command/CommandSet.php
  92. 2  src/Guzzle/Service/Command/CommandSetException.php
  93. 121  src/Guzzle/Service/Description/ApiCommand.php
  94. 2  src/Guzzle/Service/Description/CommandFactoryInterface.php
  95. 6  src/Guzzle/Service/Description/DescriptionBuilderInterface.php
  96. 23  src/Guzzle/Service/Description/DynamicCommandFactory.php
  97. 38  src/Guzzle/Service/Description/JsonDescriptionBuilder.php
  98. 74  src/Guzzle/Service/Description/ServiceDescription.php
  99. 169  src/Guzzle/Service/Description/XmlDescriptionBuilder.php
  100. 75  src/Guzzle/Service/Inflector.php
  101. 190  src/Guzzle/{Common → Service}/Inspector.php
  102. 58  src/Guzzle/Service/ResourceIterator.php
  103. 42  src/Guzzle/Service/ResourceIteratorApplyBatched.php
  104. 108  src/Guzzle/Service/ServiceBuilder.php
  105. 57  tests/Guzzle/Tests/Common/AbstractHasDispatcherTest.php
  106. 3  tests/Guzzle/Tests/Common/Cache/CacheAdapterTest.php
  107. 19  tests/Guzzle/Tests/Common/Cache/ZendCacheAdapterTest.php
  108. 3  tests/Guzzle/Tests/Common/CollectionTest.php
  109. 23  tests/Guzzle/Tests/Common/Event/AbstractSubjectTest.php
  110. 236  tests/Guzzle/Tests/Common/Event/EventManagerTest.php
  111. 62  tests/Guzzle/Tests/Common/EventTest.php
  112. 46  tests/Guzzle/Tests/Common/ExceptionCollectionTest.php
  113. 151  tests/Guzzle/Tests/Common/Filter/FilterImpTest.php
  114. 87  tests/Guzzle/Tests/Common/Filter/FilterTest.php
  115. 5  tests/Guzzle/Tests/Common/Log/ClosureLogAdapterTest.php
  116. 3  tests/Guzzle/Tests/Common/Log/MonologLogAdapterTest.php
  117. 9  tests/Guzzle/Tests/Common/Log/ZendLogAdapterTest.php
  118. 45  tests/Guzzle/Tests/Common/Mock/MockFilter.php
  119. 14  tests/Guzzle/Tests/Common/Mock/MockFilterCommand.php
  120. 37  tests/Guzzle/Tests/Common/Mock/MockObserver.php
  121. 10  tests/Guzzle/Tests/Common/Mock/MockSubject.php
  122. 3  tests/Guzzle/Tests/Common/NullObjectTest.php
  123. 63  tests/Guzzle/Tests/Common/StreamTest.php
  124. 4  tests/Guzzle/Tests/Common/XmlElementTest.php
  125. 3  tests/Guzzle/Tests/GuzzleTest.php
  126. 62  tests/Guzzle/Tests/GuzzleTestCase.php
  127. 432  tests/Guzzle/Tests/Http/ClientTest.php
  128. 6  tests/Guzzle/Tests/Http/CookieJar/ArrayCookieJarTest.php
  129. 3  tests/Guzzle/Tests/Http/CookieJar/FileCookieJarTest.php
  130. 3  tests/Guzzle/Tests/Http/CookieTest.php
  131. 13  tests/Guzzle/Tests/Http/Curl/CurlExceptionTest.php
  132. 737  tests/Guzzle/Tests/Http/Curl/CurlFactoryTest.php
  133. 496  tests/Guzzle/Tests/Http/Curl/CurlHandleTest.php
  134. 490  tests/Guzzle/Tests/Http/Curl/CurlMultiTest.php
  135. 3  tests/Guzzle/Tests/Http/EntityBodyTest.php
  136. 98  tests/Guzzle/Tests/Http/Message/AbstractMessageTest.php
  137. 250  tests/Guzzle/Tests/Http/Message/EntityEnclosingRequestTest.php
  138. 3  tests/Guzzle/Tests/Http/Message/ExceptionTest.php
  139. 44  tests/Guzzle/Tests/Http/Message/RequestFactoryTest.php
  140. 188  tests/Guzzle/Tests/Http/Message/RequestTest.php
  141. 10  tests/Guzzle/Tests/Http/Message/ResponseTest.php
  142. 22  tests/Guzzle/Tests/Http/Plugin/BasicAuthPluginTest.php
  143. 137  tests/Guzzle/Tests/Http/Plugin/CachePluginTest.php
  144. 53  tests/Guzzle/Tests/Http/Plugin/CookiePluginTest.php
  145. 35  tests/Guzzle/Tests/Http/Plugin/ExponentialBackoffTest.php
  146. 26  tests/Guzzle/Tests/Http/Plugin/HistoryPluginTest.php
  147. 70  tests/Guzzle/Tests/Http/Plugin/LogPluginTest.php
  148. 59  tests/Guzzle/Tests/Http/Plugin/Md5ValidatorPluginTest.php
  149. 82  tests/Guzzle/Tests/{Service → Http}/Plugin/MockPluginTest.php
  150. 14  tests/Guzzle/Tests/Http/Pool/MockPool.php
  151. 252  tests/Guzzle/Tests/Http/Pool/PoolTest.php
  152. 7  tests/Guzzle/Tests/Http/QueryStringTest.php
  153. 21  tests/Guzzle/Tests/Http/Server.php
  154. 3  tests/Guzzle/Tests/Http/UrlTest.php
  155. 7  tests/Guzzle/Tests/Http/server.js
  156. 11  tests/Guzzle/Tests/Mock/MockMulti.php
  157. 70  tests/Guzzle/Tests/Mock/MockObserver.php
  158. 7  tests/Guzzle/Tests/Mock/MockSubject.php
  159. 363  tests/Guzzle/Tests/Service/ClientTest.php
  160. 6  tests/Guzzle/Tests/Service/Command/AbstractCommandTest.php
  161. 20  tests/Guzzle/Tests/Service/Command/ClosureCommandTest.php
  162. 45  tests/Guzzle/Tests/Service/Command/CommandSetTest.php
  163. 15  tests/Guzzle/Tests/Service/Command/CommandTest.php
  164. 44  tests/Guzzle/Tests/Service/Description/ApiCommandTest.php
  165. 45  tests/Guzzle/Tests/Service/Description/DynamicCommandFactoryTest.php
  166. 29  tests/Guzzle/Tests/Service/Description/JsonDescriptionBuilderTest.php
  167. 105  tests/Guzzle/Tests/Service/Description/ServiceDescriptionTest.php
  168. 90  tests/Guzzle/Tests/Service/Description/XmlDescriptionBuilderTest.php
  169. 17  tests/Guzzle/Tests/{Common → Service}/InflectorTest.php
  170. 164  tests/Guzzle/Tests/{Common → Service}/InspectorTest.php
  171. 16  tests/Guzzle/Tests/Service/Mock/Command/MockCommand.php
  172. 2  tests/Guzzle/Tests/Service/Mock/Command/OtherCommand.php
  173. 2  tests/Guzzle/Tests/Service/Mock/Command/Sub/Sub.php
  174. 4  tests/Guzzle/Tests/Service/Mock/MockClient.php
  175. 17  tests/Guzzle/Tests/Service/Mock/MockInflector.php
  176. 3  tests/Guzzle/Tests/Service/Mock/MockResourceIterator.php
  177. 9  tests/Guzzle/Tests/Service/ResourceIteratorApplyBatchedTest.php
  178. 9  tests/Guzzle/Tests/Service/ResourceIteratorTest.php
  179. 87  tests/Guzzle/Tests/Service/ServiceBuilderTest.php
  180. 12  tests/Guzzle/Tests/TestData/test_service.json
  181. 23  tests/Guzzle/Tests/TestData/test_service.xml
  182. 7  tests/Guzzle/Tests/TestData/test_service2.json
  183. 6  tests/Guzzle/Tests/TestData/test_service2.xml
  184. 27  tests/bootstrap.php
  185. 1  vendor/Doctrine
  186. 1  vendor/Monolog
  187. 1  vendor/Symfony/Component/ClassLoader
  188. 250  vendor/Zend/Cache.php
  189. 266  vendor/Zend/Cache/Backend.php
  190. 355  vendor/Zend/Cache/Backend/Apc.php
  191. 250  vendor/Zend/Cache/Backend/BlackHole.php
  192. 126  vendor/Zend/Cache/Backend/ExtendedInterface.php
  193. 1,006  vendor/Zend/Cache/Backend/File.php
  194. 99  vendor/Zend/Cache/Backend/Interface.php
  195. 484  vendor/Zend/Cache/Backend/Libmemcached.php
  196. 504  vendor/Zend/Cache/Backend/Memcached.php
  197. 679  vendor/Zend/Cache/Backend/Sqlite.php
  198. 559  vendor/Zend/Cache/Backend/Static.php
  199. 413  vendor/Zend/Cache/Backend/Test.php
  200. 536  vendor/Zend/Cache/Backend/TwoLevels.php
  201. 221  vendor/Zend/Cache/Backend/Xcache.php
  202. 317  vendor/Zend/Cache/Backend/ZendPlatform.php
  203. 207  vendor/Zend/Cache/Backend/ZendServer.php
  204. 100  vendor/Zend/Cache/Backend/ZendServer/Disk.php
  205. 100  vendor/Zend/Cache/Backend/ZendServer/ShMem.php
  206. 757  vendor/Zend/Cache/Core.php
  207. 32  vendor/Zend/Cache/Exception.php
  208. 88  vendor/Zend/Cache/Frontend/Capture.php
  209. 259  vendor/Zend/Cache/Frontend/Class.php
  210. 218  vendor/Zend/Cache/Frontend/File.php
  211. 180  vendor/Zend/Cache/Frontend/Function.php
  212. 106  vendor/Zend/Cache/Frontend/Output.php
  213. 402  vendor/Zend/Cache/Frontend/Page.php
  214. 298  vendor/Zend/Cache/Manager.php
  215. 96  vendor/Zend/Exception.php
  216. 583  vendor/Zend/Log.php
  217. 33  vendor/Zend/Log/Exception.php
  218. 38  vendor/Zend/Log/FactoryInterface.php
  219. 60  vendor/Zend/Log/Filter/Abstract.php
  220. 40  vendor/Zend/Log/Filter/Interface.php
  221. 85  vendor/Zend/Log/Filter/Message.php
  222. 101  vendor/Zend/Log/Filter/Priority.php
  223. 77  vendor/Zend/Log/Filter/Suppress.php
  224. 50  vendor/Zend/Log/Formatter/Firebug.php
  225. 41  vendor/Zend/Log/Formatter/Interface.php
  226. 86  vendor/Zend/Log/Formatter/Simple.php
  227. 122  vendor/Zend/Log/Formatter/Xml.php
  228. 138  vendor/Zend/Log/Writer/Abstract.php
  229. 145  vendor/Zend/Log/Writer/Db.php
  230. 204  vendor/Zend/Log/Writer/Firebug.php
22  .gitignore
... ...
@@ -1,10 +1,20 @@
  1
+# Ingore common cruft
1 2
 .DS_STORE
2 3
 coverage
  4
+
  5
+# Ignore binary files
  6
+guzzle.phar
  7
+
  8
+# Ignore potentially sensitive phpunit file
3 9
 phpunit.xml
4  
-build/guzzle.phar
5  
-build/guzzle-na.phar
6  
-src/Guzzle/Aws/
7  
-src/Guzzle/CardinalCommerce/
8  
-src/Guzzle/Unfuddle/
  10
+
  11
+# Helps to ignore services being tested
  12
+src/Guzzle/
  13
+!src/Guzzle/Guzzle.php
  14
+!src/Guzzle/Common
  15
+!src/Guzzle/Http
  16
+!src/Guzzle/Service
  17
+
  18
+# Ignore composer generated files
9 19
 composer.lock
10  
-vendor/.composer
  20
+vendor/
9  .gitmodules
... ...
@@ -1,9 +0,0 @@
1  
-[submodule "vendor/Symfony/Component/ClassLoader"]
2  
-	path = vendor/Symfony/Component/ClassLoader
3  
-	url = https://github.com/symfony/ClassLoader
4  
-[submodule "vendor/Doctrine"]
5  
-	path = vendor/Doctrine
6  
-	url = https://github.com/doctrine/common
7  
-[submodule "vendor/Monolog"]
8  
-	path = vendor/Monolog
9  
-	url = https://github.com/Seldaek/monolog.git
8  .travis.yml
@@ -3,10 +3,8 @@ php:
3 3
   - 5.3
4 4
   - 5.4
5 5
 before_script:
6  
-  - git submodule update --init
  6
+  - wget --quiet http://getcomposer.org/composer.phar
  7
+  - php composer.phar install --install-suggests 
7 8
   - cp phpunit.xml.dist phpunit.xml
8  
-  - ~/.nvm/v0.6.1/bin/node tests/Guzzle/Tests/Http/server.js &
  9
+  - ~/.nvm/nvm.sh run default tests/Guzzle/Tests/Http/server.js &
9 10
 script: sudo phpunit
10  
-notifications:
11  
-  email:
12  
-    - michael@guzzlephp.org
2  LICENSE
... ...
@@ -1,4 +1,4 @@
1  
-Copyright (c) 2011 Michael Dowling <michael@guzzlephp.org>
  1
+Copyright (c) 2011 Michael Dowling, https://github.com/mtdowling <mtdowling@gmail.com>
2 2
 
3 3
 Permission is hereby granted, free of charge, to any person obtaining a copy
4 4
 of this software and associated documentation files (the "Software"), to deal
34  README.md
Source Rendered
... ...
@@ -1,7 +1,7 @@
1 1
 Guzzle, PHP HTTP client and webservice framework
2  
-===============================================
  2
+================================================
3 3
 
4  
-Guzzle is a game changer in the world of PHP HTTP clients. Guzzle allows you to truly reap the benefits of the HTTP/1.1 spec. No other library provides persistent connection management or makes it easier to send requests in parallel.</p>
  4
+Guzzle is a game changer in the world of PHP HTTP clients. Guzzle allows you to truly reap the benefits of the HTTP/1.1 spec. No other library makes it easier to manage persistent connections or send requests in parallel.</p>
5 5
 
6 6
 In addition to taking the pain out of HTTP, Guzzle provides a lightweight framework for creating web service clients.  Most web service clients follow a specific pattern: create a client class, create methods for each action, create and execute a cURL handle, parse the response, implement error handling, and return the result. Guzzle takes the redundancy out of this process and gives you the tools you need to quickly build a web service client.
7 7
 
@@ -37,7 +37,7 @@ HTTP basics
37 37
 ```php
38 38
 <?php
39 39
 
40  
-use Guzzle\Service\Client;
  40
+use Guzzle\Http\Client;
41 41
 
42 42
 $client = new Client('http://www.example.com/api/v1/key/{{key}}', array(
43 43
     'key' => '***'
@@ -102,18 +102,30 @@ Send requests in parallel
102 102
 ```php
103 103
 <?php
104 104
 
105  
-use Guzzle\Service\Client;
106  
-
107 105
 try {
108  
-    $responses = $client->batch(array(
109  
-        $client->get('http://www.google.com/'),
110  
-        $client->head('http://www.google.com/'),
111  
-        $client->get('https://www.github.com/')
  106
+    $client = new Guzzle\Http\Client('http://www.myapi.com/api/v1');
  107
+    $responses = $client->send(array(
  108
+        $client->get('users'),
  109
+        $client->head('messages/123'),
  110
+        $client->delete('orders/123')
112 111
     ));
113  
-} catch (PoolRequestException $e) {
  112
+} catch (Guzzle\Common\ExceptionCollection $e) {
114 113
     echo "The following requests encountered an exception: \n";
115 114
     foreach ($e as $exception) {
116 115
         echo $exception->getRequest() . "\n" . $exception->getMessage() . "\n";
117 116
     }
118 117
 }
119  
-```
  118
+```
  119
+
  120
+Testing Guzzle
  121
+--------------
  122
+
  123
+Here's how to install Guzzle from source to run the unit tests:
  124
+
  125
+```
  126
+git clone git@github.com:guzzle/guzzle.git
  127
+cd guzzle
  128
+composer.phar install --install-suggests
  129
+cp phpunit.xml.dist phpunit.xml
  130
+phpunit
  131
+```
24  autoload.php
... ...
@@ -0,0 +1,24 @@
  1
+<?php
  2
+
  3
+$namespaces = array(
  4
+    'Guzzle' => 'phar://' . __FILE__ . '/src',
  5
+    'Symfony\\Component\\Validator' => 'phar://' . __FILE__ . '/vendor/symfony/validator',
  6
+    'Symfony\\Component\\EventDispatcher' => 'phar://' . __FILE__ . '/vendor/symfony/event-dispatcher',
  7
+    'Doctrine' => 'phar://' . __FILE__ . '/vendor/doctrine/common/lib',
  8
+    'Monolog' => 'phar://' . __FILE__ . '/vendor/monolog/monolog/src'
  9
+);
  10
+
  11
+if (DIRECTORY_SEPARATOR == '/') {
  12
+    require_once 'phar://' . __FILE__ . '/vendor/symfony/class-loader/Symfony/Component/ClassLoader/UniversalClassLoader.php';
  13
+} else {
  14
+    require_once 'phar://' . __FILE__ . '\\vendor\\symfony\\class-loader\\Symfony\\Component\\ClassLoader\\UniversalClassLoader.php';
  15
+    $namespaces = array_filter($namespaces, function($namespace) {
  16
+        return str_replace('phar:\\\\', 'phar://', str_replace('/', '\\', $namespace));
  17
+    });
  18
+}
  19
+
  20
+$classLoader = new Symfony\Component\ClassLoader\UniversalClassLoader();
  21
+$classLoader->registerNamespaces($namespaces);
  22
+$classLoader->register();
  23
+
  24
+__HALT_COMPILER();
42  build.xml
... ...
@@ -0,0 +1,42 @@
  1
+<?xml version="1.0" encoding="UTF-8"?>
  2
+<project name="guzzle" default="phar">
  3
+    <target name="phar" description="Create a phar with an autoloader">
  4
+        <if>
  5
+            <equals arg1="${min}" arg2="true" />
  6
+            <then>
  7
+                <pharpackage
  8
+                    destfile="./guzzle-min.phar"
  9
+                    basedir="."
  10
+                    alias="Guzzle"
  11
+                    signature="md5">
  12
+                    <fileset dir=".">
  13
+                        <include name="src/**/*.php" />
  14
+                    </fileset>
  15
+                    <metadata>
  16
+                        <element name="version" value="2.0.0" />
  17
+                    </metadata>
  18
+                </pharpackage>
  19
+            </then>
  20
+            <else>
  21
+                <pharpackage
  22
+                    destfile="./guzzle.phar"
  23
+                    basedir="."
  24
+                    stub="autoload.php"
  25
+                    alias="Guzzle"
  26
+                    signature="md5">
  27
+                    <fileset dir=".">
  28
+                        <include name="src/**/*.php" />
  29
+                        <include name="vendor/symfony/class-loader/Symfony/Component/ClassLoader/UniversalClassLoader.php" />
  30
+                        <include name="vendor/symfony/event-dispatcher/**/*.php" />
  31
+                        <include name="vendor/symfony/validator/**/*.php" />
  32
+                        <include name="vendor/doctrine/common/lib/Doctrine/Common/Cache/*.php" />
  33
+                        <include name="vendor/monolog/monolog/src/**/*.php" />
  34
+                    </fileset>
  35
+                    <metadata>
  36
+                        <element name="version" value="2.0.0" />
  37
+                    </metadata>
  38
+                </pharpackage>
  39
+            </else>
  40
+        </if>
  41
+    </target>
  42
+</project>
22  build/autoload.php
... ...
@@ -1,22 +0,0 @@
1  
-<?php
2  
-/**
3  
- * Autoloader stub for guzzle.phar to autoload Guzzle\* classes.
4  
- *
5  
- * Note: this autoloader does not load other PSR-0 libraries.  If you need to
6  
- * autoload other libraries, we recommend the Symfony ClassLoader component.
7  
- */
8  
-
9  
-spl_autoload_register(function($class) {
10  
-    if (0 === strpos($class, 'Guzzle\\')) {
11  
-        if ('\\' != DIRECTORY_SEPARATOR) {
12  
-            $class = 'phar://' . __FILE__ . DIRECTORY_SEPARATOR . str_replace('\\', DIRECTORY_SEPARATOR, $class) . '.php';
13  
-        } else {
14  
-            $class = 'phar://' . __FILE__ . DIRECTORY_SEPARATOR . $class . '.php';
15  
-        }
16  
-        if (file_exists($class)) {
17  
-            require $class;
18  
-        }
19  
-    }
20  
-});
21  
-
22  
-__HALT_COMPILER();
53  build/build.xml
... ...
@@ -1,53 +0,0 @@
1  
-<?xml version="1.0" encoding="UTF-8"?>
2  
-
3  
-<project name="guzzle" default="init">
4  
-
5  
-    <target name="init-git" description="Initialize git submodules">
6  
-        <echo msg="Initializing git submodules" />
7  
-        <exec command="git submodule update --init" dir="./.." />
8  
-    </target>
9  
-
10  
-    <target name="init-test" description="Initialize for unit testing">
11  
-        <echo msg="Copying ./phpunit.xml.dist to ./phpunit.xml" />
12  
-        <copy file="../phpunit.xml.dist" tofile="../phpunit.xml" />
13  
-    </target>
14  
-
15  
-    <target name="init" depends="init-git,init-test" />
16  
-
17  
-    <target name="phar" description="Create a phar with an autoloader">
18  
-        <if>
19  
-            <equals arg1="${autoload}" arg2="false" />
20  
-            <then>
21  
-                <pharpackage
22  
-                    destfile="./guzzle-na.phar"
23  
-                    basedir="../src"
24  
-                    alias="Guzzle"
25  
-                    signature="sha1">
26  
-                    <fileset dir="../src">
27  
-                        <include name="**/*.php" />
28  
-                        <exclude name="**/Tests/**" />
29  
-                    </fileset>
30  
-                    <metadata>
31  
-                        <element name="version" value="1.0.1" />
32  
-                    </metadata>
33  
-                </pharpackage>
34  
-            </then>
35  
-            <else>
36  
-                <pharpackage
37  
-                    destfile="./guzzle.phar"
38  
-                    basedir="../src"
39  
-                    stub="./autoload.php"
40  
-                    alias="Guzzle"
41  
-                    signature="sha1">
42  
-                    <fileset dir="../src">
43  
-                        <include name="**/*.php" />
44  
-                        <exclude name="**/Tests/**" />
45  
-                    </fileset>
46  
-                    <metadata>
47  
-                        <element name="version" value="1.0.1" />
48  
-                    </metadata>
49  
-                </pharpackage>
50  
-            </else>
51  
-        </if>
52  
-    </target>
53  
-</project>
65  composer.json
@@ -2,21 +2,66 @@
2 2
     "name": "guzzle/guzzle",
3 3
     "type": "library",
4 4
     "description": "Guzzle is a PHP HTTP client library and framework for building RESTful web service clients",
5  
-    "keywords": ["framework", "http", "rest"],
  5
+    "keywords": ["framework", "http", "rest", "web service"],
6 6
     "homepage": "http://www.guzzlephp.org/",
7 7
     "license": "MIT",
8  
-    "authors": [
9  
-        {
10  
-            "name": "Michael Dowling",
11  
-            "email": "michael@guzzlephp.org"
  8
+    "authors": [{
  9
+        "name": "Michael Dowling",
  10
+        "email": "mtdowling@gmail.com",
  11
+        "homepage": "https://github.com/mtdowling"
  12
+    },
  13
+    {
  14
+        "name": "Guzzle Community",
  15
+        "homepage": "https://github.com/guzzle/guzzle/contributors"
  16
+    }],
  17
+    "repositories": {
  18
+        "zend-log": {
  19
+            "package": {
  20
+                "name": "zend/zend-log",
  21
+                "version": "2.0.0",
  22
+                "autoload": { "psr-0": { "Zend\\Log": "" } },
  23
+                "target-dir": "Zend/Log",
  24
+                "dist": {
  25
+                    "url": "https://github.com/KnpLabs/zend-log/zipball/master",
  26
+                    "type": "zip"
  27
+                },
  28
+                "source": {
  29
+                    "url": "https://github.com/KnpLabs/zend-log.git",
  30
+                    "type": "git",
  31
+                    "reference": "master"
  32
+                }
  33
+            }
12 34
         },
13  
-        {
14  
-            "name": "Guzzle Community",
15  
-            "homepage": "https://github.com/guzzle/guzzle/contributors"
  35
+        "zend-cache": {
  36
+            "package": {
  37
+                "name": "zend/zend-cache",
  38
+                "version": "2.0.0",
  39
+                "autoload": { "psr-0": { "Zend\\Cache": "" } },
  40
+                "target-dir": "Zend/Cache",
  41
+                "dist": {
  42
+                    "url": "https://github.com/KnpLabs/zend-cache/zipball/master",
  43
+                    "type": "zip"
  44
+                },
  45
+                "source": {
  46
+                    "url": "https://github.com/KnpLabs/zend-cache.git",
  47
+                    "type": "git",
  48
+                    "reference": "master"
  49
+                }
  50
+            }
16 51
         }
17  
-    ],
  52
+    },
18 53
     "require": {
19  
-        "php": ">=5.3.2"
  54
+        "php": ">=5.3.2",
  55
+        "ext-curl": "*",
  56
+        "symfony/event-dispatcher": "*",
  57
+        "symfony/validator": "*"
  58
+    },
  59
+    "suggest": {
  60
+        "symfony/class-loader": "*",
  61
+        "doctrine/common": "*",
  62
+        "monolog/monolog": "*",
  63
+        "zend/zend-cache": "*",
  64
+        "zend/zend-log": "*"
20 65
     },
21 66
     "autoload": {
22 67
         "psr-0": { "Guzzle": "src/" }
2  phpunit.xml.dist
@@ -20,8 +20,6 @@
20 20
             <directory suffix=".php">./src/Guzzle</directory>
21 21
             <exclude>
22 22
                 <directory suffix="Interface.php">./src/Guzzle</directory>
23  
-                <file>./src/Guzzle/Common/Event/Subject.php</file>
24  
-                <file>./src/Guzzle/Common/GuzzleException.php</file>
25 23
                 <file>./src/Guzzle/Http/HttpException.php</file>
26 24
             </exclude>
27 25
         </whitelist>
55  src/Guzzle/Common/AbstractHasDispatcher.php
... ...
@@ -0,0 +1,55 @@
  1
+<?php
  2
+
  3
+namespace Guzzle\Common;
  4
+
  5
+use Symfony\Component\EventDispatcher\EventDispatcher;
  6
+use Symfony\Component\EventDispatcher\EventDispatcherInterface;
  7
+
  8
+/**
  9
+ * Class that holds an event dispatcher
  10
+ */
  11
+class AbstractHasDispatcher implements HasDispatcherInterface
  12
+{
  13
+    /**
  14
+     * @var EventDispatcherInterface
  15
+     */
  16
+    protected $eventDispatcher;
  17
+
  18
+    /**
  19
+     * {@inheritdoc}
  20
+     */
  21
+    public static function getAllEvents()
  22
+    {
  23
+        return array();
  24
+    }
  25
+
  26
+    /**
  27
+     * {@inheritdoc}
  28
+     */
  29
+    public function setEventDispatcher(EventDispatcherInterface $eventDispatcher)
  30
+    {
  31
+        $this->eventDispatcher = $eventDispatcher;
  32
+
  33
+        return $this;
  34
+    }
  35
+
  36
+    /**
  37
+     * {@inheritdoc}
  38
+     */
  39
+    public function getEventDispatcher()
  40
+    {
  41
+        if (!$this->eventDispatcher) {
  42
+            $this->eventDispatcher = new EventDispatcher();
  43
+        }
  44
+
  45
+        return $this->eventDispatcher;
  46
+    }
  47
+
  48
+    /**
  49
+     * {@inheritdoc}
  50
+     */
  51
+    public function dispatch($eventName, array $context = array())
  52
+    {
  53
+        $this->getEventDispatcher()->dispatch($eventName, new Event($context));
  54
+    }
  55
+}
10  src/Guzzle/Common/Cache/AbstractCacheAdapter.php
@@ -4,21 +4,13 @@
4 4
 
5 5
 /**
6 6
  * Abstract cache adapter
7  
- *
8  
- * @link http://www.doctrine-project.org/
9  
- * @author Michael Dowling <michael@guzzlephp.org>
10 7
  */
11 8
 abstract class AbstractCacheAdapter implements CacheAdapterInterface
12 9
 {
13  
-    /**
14  
-     * @var mixed Cache object that is wrapped by the adapter
15  
-     */
16 10
     protected $cache;
17 11
 
18 12
     /**
19  
-     * Get the cache object
20  
-     *
21  
-     * @return mixed
  13
+     * {@inheritdoc}
22 14
      */
23 15
     public function getCacheObject()
24 16
     {
2  src/Guzzle/Common/Cache/CacheAdapterInterface.php
@@ -10,8 +10,6 @@
10 10
  *
11 11
  * The CacheAdapter interface was inspired by the Doctrine 2 ORM:
12 12
  * @link http://www.doctrine-project.org/
13  
- *
14  
- * @author Michael Dowling <michael@guzzlephp.org>
15 13
  */
16 14
 interface CacheAdapterInterface
17 15
 {
36  src/Guzzle/Common/Cache/DoctrineCacheAdapter.php
@@ -7,15 +7,12 @@
7 7
 /**
8 8
  * Doctrine 2 cache adapter
9 9
  *
10  
- * @link   http://www.doctrine-project.org/ 
11  
- * @author Michael Dowling <michael@guzzlephp.org>
  10
+ * @link   http://www.doctrine-project.org/
12 11
  */
13 12
 class DoctrineCacheAdapter extends AbstractCacheAdapter
14 13
 {
15 14
     /**
16  
-     * Constructor
17  
-     *
18  
-     * @param Cache $cacheObject Object to wrap and adapt
  15
+     * {@inheritdoc}
19 16
      */
20 17
     public function __construct(Cache $cache)
21 18
     {
@@ -23,12 +20,7 @@ public function __construct(Cache $cache)
23 20
     }
24 21
 
25 22
     /**
26  
-     * Test if an entry exists in the cache.
27  
-     *
28  
-     * @param string $id cache id The cache id of the entry to check for.
29  
-     *
30  
-     * @return bool TRUE if a cache entry exists for the given cache id,
31  
-     *      FALSE otherwise.
  23
+     * {@inheritdoc}
32 24
      */
33 25
     public function contains($id)
34 26
     {
@@ -36,11 +28,7 @@ public function contains($id)
36 28
     }
37 29
 
38 30
     /**
39  
-     * Deletes a cache entry.
40  
-     *
41  
-     * @param string $id cache id
42  
-     *
43  
-     * @return bool TRUE on success, FALSE on failure
  31
+     * {@inheritdoc}
44 32
      */
45 33
     public function delete($id)
46 34
     {
@@ -48,12 +36,7 @@ public function delete($id)
48 36
     }
49 37
 
50 38
     /**
51  
-     * Fetches an entry from the cache.
52  
-     *
53  
-     * @param string $id cache id The id of the cache entry to fetch.
54  
-     *
55  
-     * @return string The cached data or FALSE, if no cache entry exists for
56  
-     *      the given id.
  39
+     * {@inheritdoc}
57 40
      */
58 41
     public function fetch($id)
59 42
     {
@@ -61,14 +44,7 @@ public function fetch($id)
61 44
     }
62 45
 
63 46
     /**
64  
-     * Puts data into the cache.
65  
-     *
66  
-     * @param string $id The cache id.
67  
-     * @param string $data The cache entry/data.
68  
-     * @param int $lifeTime The lifetime. If != false, sets a specific lifetime
69  
-     *      for this cache entry (null => infinite lifeTime).
70  
-     *
71  
-     * @return bool TRUE on success, FALSE on failure
  47
+     * {@inheritdoc}
72 48
      */
73 49
     public function save($id, $data, $lifeTime = false)
74 50
     {
47  src/Guzzle/Common/Cache/ZendCacheAdapter.php
@@ -2,31 +2,27 @@
2 2
 
3 3
 namespace Guzzle\Common\Cache;
4 4
 
  5
+use Zend\Cache\Backend;
  6
+
5 7
 /**
6  
- * Zend Framework 1.x cache adapter
7  
- *
8  
- * @link   http://www.doctrine-project.org/
9  
- * @author Michael Dowling <michael@guzzlephp.org>
  8
+ * ZF1 / ZF2 cache adapter
10 9
  */
11 10
 class ZendCacheAdapter extends AbstractCacheAdapter
12 11
 {
13 12
     /**
14  
-     * Constructor
15  
-     *
16  
-     * @param Zend_Cache_Backend $cacheObject Object to wrap and adapt
  13
+     * {@inheritdoc}
17 14
      */
18  
-    public function __construct(\Zend_Cache_Backend $cache)
  15
+    public function __construct($cache)
19 16
     {
  17
+        if (!($cache instanceof Backend) && !($cache instanceof \Zend_Cache_Backend)) {
  18
+            throw new \InvalidArgumentException('$cache must be an instance of '
  19
+                . 'Zend\\Log\\Backend or Zend_Cache_Backend');
  20
+        }
20 21
         $this->cache = $cache;
21 22
     }
22 23
 
23 24
     /**
24  
-     * Test if an entry exists in the cache.
25  
-     *
26  
-     * @param string $id cache id The cache id of the entry to check for.
27  
-     *
28  
-     * @return bool TRUE if a cache entry exists for the given cache id,
29  
-     *      FALSE otherwise.
  25
+     * {@inheritdoc}
30 26
      */
31 27
     public function contains($id)
32 28
     {
@@ -34,11 +30,7 @@ public function contains($id)
34 30
     }
35 31
 
36 32
     /**
37  
-     * Deletes a cache entry.
38  
-     *
39  
-     * @param string $id cache id
40  
-     *
41  
-     * @return bool TRUE on success, FALSE on failure
  33
+     * {@inheritdoc}
42 34
      */
43 35
     public function delete($id)
44 36
     {
@@ -46,12 +38,7 @@ public function delete($id)
46 38
     }
47 39
 
48 40
     /**
49  
-     * Fetches an entry from the cache.
50  
-     *
51  
-     * @param string $id cache id The id of the cache entry to fetch.
52  
-     *
53  
-     * @return string The cached data or FALSE, if no cache entry exists for
54  
-     *      the given id.
  41
+     * {@inheritdoc}
55 42
      */
56 43
     public function fetch($id)
57 44
     {
@@ -59,15 +46,7 @@ public function fetch($id)
59 46
     }
60 47
 
61 48
     /**
62  
-     * Puts data into the cache.
63  
-     *
64  
-     * @param string $id The cache id.
65  
-     * @param string $data The cache entry/data.
66  
-     * @param int $lifeTime The lifetime. If != false, sets a specific lifetime
67  
-     *      for this cache entry (null => infinite lifeTime).
68  
-     *
69  
-     * @return bool TRUE if the entry was successfully stored in the cache,
70  
-     *      FALSE otherwise.
  49
+     * {@inheritdoc}
71 50
      */
72 51
     public function save($id, $data, $lifeTime = false)
73 52
     {
15  src/Guzzle/Common/Collection.php
@@ -4,8 +4,6 @@
4 4
 
5 5
 /**
6 6
  * Key value pair collection object
7  
- *
8  
- * @author Michael Dowling <michael@guzzlephp.org>
9 7
  */
10 8
 class Collection implements \ArrayAccess, \IteratorAggregate, \Countable
11 9
 {
@@ -16,7 +14,7 @@ class Collection implements \ArrayAccess, \IteratorAggregate, \Countable
16 14
     /**
17 15
      * @var array Data associated with the object.
18 16
      */
19  
-    protected $data = array();
  17
+    protected $data;
20 18
 
21 19
     /**
22 20
      * Constructor
@@ -25,9 +23,7 @@ class Collection implements \ArrayAccess, \IteratorAggregate, \Countable
25 23
      */
26 24
     public function __construct(array $data = null)
27 25
     {
28  
-        if ($data) {
29  
-            $this->data = $data;
30  
-        }
  26
+        $this->data = $data ?: array();
31 27
     }
32 28
 
33 29
     /**
@@ -291,8 +287,8 @@ public function hasValue($value)
291 287
      */
292 288
     public function map(\Closure $closure, array $context = array(), $static = true)
293 289
     {
294  
-        $collection = ($static) ? new static() : new self();
295  
-        foreach ($this->getIterator() as $key => $value) {
  290
+        $collection = $static ? new static() : new self();
  291
+        foreach ($this as $key => $value) {
296 292
             $collection->add($key, $closure($key, $value, $context));
297 293
         }
298 294
 
@@ -383,8 +379,7 @@ public function offsetUnset($offset)
383 379
     public function remove($key, $match = self::MATCH_EXACT)
384 380
     {
385 381
         foreach ((array) $key as $k) {
386  
-            $matched = $this->hasKey($k, $match);
387  
-            if ($matched !== false) {
  382
+            if (false !== $matched = $this->hasKey($k, $match)) {
388 383
                 unset($this->data[$matched]);
389 384
             }
390 385
         }
66  src/Guzzle/Common/Event.php
... ...
@@ -0,0 +1,66 @@
  1
+<?php
  2
+
  3
+namespace Guzzle\Common;
  4
+
  5
+use Symfony\Component\EventDispatcher\Event as SymfonyEvent;
  6
+
  7
+/**
  8
+ * Default event for Guzzle notifications
  9
+ */
  10
+class Event extends SymfonyEvent implements \ArrayAccess, \IteratorAggregate
  11
+{
  12
+    /**
  13
+     * @var array
  14
+     */
  15
+    private $context;
  16
+
  17
+    /**
  18
+     * Constructor
  19
+     *
  20
+     * @param array $context Contextual information
  21
+     */
  22
+    public function __construct(array $context = array())
  23
+    {
  24
+        $this->context = $context;
  25
+    }
  26
+
  27
+    /**
  28
+     * {@inheritdoc}
  29
+     */
  30
+    public function getIterator()
  31
+    {
  32
+        return new \ArrayIterator($this->context);
  33
+    }
  34
+
  35
+    /**
  36
+     * {@inheritdoc}
  37
+     */
  38
+    public function offsetGet($offset)
  39
+    {
  40
+        return array_key_exists($offset, $this->context) ? $this->context[$offset] : null;
  41
+    }
  42
+
  43
+    /**
  44
+     * {@inheritdoc}
  45
+     */
  46
+    public function offsetSet($offset, $value)
  47
+    {
  48
+        $this->context[$offset] = $value;
  49
+    }
  50
+
  51
+    /**
  52
+     * {@inheritdoc}
  53
+     */
  54
+    public function offsetExists($offset)
  55
+    {
  56
+        return array_key_exists($offset, $this->context);
  57
+    }
  58
+
  59
+    /**
  60
+     * {@inheritdoc}
  61
+     */
  62
+    public function offsetUnset($offset)
  63
+    {
  64
+        unset($this->context[$offset]);
  65
+    }
  66
+}
30  src/Guzzle/Common/Event/AbstractSubject.php
... ...
@@ -1,30 +0,0 @@
1  
-<?php
2  
-
3  
-namespace Guzzle\Common\Event;
4  
-
5  
-/**
6  
- * Abstract subject class
7  
- *
8  
- * @author Michael Dowling <michael@guzzlephp.org>
9  
- */
10  
-abstract class AbstractSubject implements Subject
11  
-{
12  
-    /**
13  
-     * @var EventManager
14  
-     */
15  
-    protected $eventManager;
16  
-
17  
-    /**
18  
-     * Get the subject mediator associated with the subject
19  
-     *
20  
-     * @return EventManager
21  
-     */
22  
-    public function getEventManager()
23  
-    {
24  
-        if (!$this->eventManager) {
25  
-            $this->eventManager = new EventManager($this);
26  
-        }
27  
-
28  
-        return $this->eventManager;
29  
-    }
30  
-}
234  src/Guzzle/Common/Event/EventManager.php
... ...
@@ -1,234 +0,0 @@
1  
-<?php
2  
-
3  
-namespace Guzzle\Common\Event;
4  
-
5  
-/**
6  
- * Connects {@see Subject} objects and {@see Observer} objects by emitting
7  
- * signals from the subject to the observer.  Contextual information can be
8  
- * sent to observers to give more context on how to react to a signal.
9  
- *
10  
- * @author Michael Dowling <michael@guzzlephp.org>
11  
- */
12  
-class EventManager
13  
-{
14  
-    /**
15  
-     * @var Subject Mediated {@see Subject} to connect with {@see Observer}s
16  
-     */
17  
-    protected $subject;
18  
-
19  
-    /**
20  
-     * @var array Array of {@see Observer} objects.
21  
-     */
22  
-    protected $observers = array();
23  
-
24  
-    /**
25  
-     * @var array Array of observer priorities
26  
-     */
27  
-    protected $priorities = array();
28  
-
29  
-    /**
30  
-     * Construct a new EventManager
31  
-     *
32  
-     * @param Subject Subject colleague object
33  
-     */
34  
-    public function __construct(Subject $subject)
35  
-    {
36  
-        $this->subject = $subject;
37  
-    }
38  
-
39  
-    /**
40  
-     * Attach a new observer.
41  
-     *
42  
-     * @param Observer|Closure $observer Object that observes the subject.
43  
-     * @param int $priority (optional) Priority to attach to the subject.  The
44  
-     *      higher the priority, the sooner it will be notified
45  
-     *
46  
-     * @return Observer|Closure Returns the $observer that was attached
47  
-     * @throws InvalidArgumentException if the observer is not a Closure or Observer
48  
-     */
49  
-    public function attach($observer, $priority = 0)
50  
-    {
51  
-        if (!($observer instanceof \Closure) && !($observer instanceof Observer)) {
52  
-            throw new \InvalidArgumentException(
53  
-                'Observer must be a Closure or Observer object'
54  
-            );
55  
-        }
56  
-
57  
-        if (!$this->hasObserver($observer)) {
58  
-            $hash = spl_object_hash($observer);
59  
-            $this->observers[$hash] = $observer;
60  
-            $this->priorities[$hash] = $priority;
61  
-            $priorities = $this->priorities;
62  
-            // Sort the events by priority
63  
-            uasort($this->observers, function($a, $b) use ($priorities) {
64  
-                $priority1 = $priorities[spl_object_hash($a)];
65  
-                $priority2 = $priorities[spl_object_hash($b)];
66  
-                if ($priority1 === $priority2) {
67  
-                    return 0;
68  
-                } else if ($priority1 > $priority2) {
69  
-                    return -1;
70  
-                } else {
71  
-                    return 1;
72  
-                }
73  
-            });
74  
-            // Notify the observer that it is being attached to the subject
75  
-            $this->notifyObserver($observer, 'event.attach');
76  
-        }
77  
-
78  
-        return $observer;
79  
-    }
80  
-
81  
-    /**
82  
-     * Detach an observer.
83  
-     *
84  
-     * @param Observer|Closure $observer Observer to detach.
85  
-     *
86  
-     * @return Observer Returns the $observer that was detached.
87  
-     */
88  
-    public function detach($observer)
89  
-    {
90  
-        if (is_object($observer)) {
91  
-            $hash = spl_object_hash($observer);
92  
-            if (isset($this->observers[$hash])) {
93  
-                // Notify the observer that it is being detached
94  
-                $this->notifyObserver($observer, 'event.detach');
95  
-                unset($this->priorities[$hash]);
96  
-                unset($this->observers[$hash]);
97  
-            }
98  
-        }
99  
-
100  
-        return $observer;
101  
-    }
102  
-
103  
-    /**
104  
-     * Detach all observers.
105  
-     *
106  
-     * @return array Returns an array of the detached observers
107  
-     */
108  
-    public function detachAll()
109  
-    {
110  
-        $detached = array_values($this->observers);
111  
-        foreach ($detached as $o) {
112  
-            $this->detach($o);
113  
-        }
114  
-
115  
-        return $detached;
116  
-    }
117  
-
118  
-    /**
119  
-     * Notify all observers of an event
120  
-     *
121  
-     * @param string $event (optional) Event signal to emit
122  
-     * @param mixed $context (optional) Context of the event
123  
-     * @param bool $until (optional) Set to TRUE to stop event propagation when
124  
-     *      one of the observers returns TRUE
125  
-     *
126  
-     * @return array Returns an array containing the response of each observer
127  
-     */
128  
-    public function notify($event, $context = null, $until = false)
129  
-    {
130  
-        $responses = array();
131  
-
132  
-        foreach ($this->observers as $observer) {
133  
-            $result = $this->notifyObserver($observer, $event, $context);
134  
-            if ($result) {
135  
-                $responses[] = $result;
136  
-                if ($until == true) {
137  
-                    break;
138  
-                }
139  
-            }
140  
-        }
141  
-        
142  
-        return $responses;
143  
-    }
144  
-
145  
-    /**
146  
-     * Get all attached observers.
147  
-     *
148  
-     * @param string $byName (optional) Pass the name of a class to retrieve
149  
-     *      only observers that are an instance of a particular class.
150  
-     *
151  
-     * @return array Returns an array containing the matching observers.  The
152  
-     *      returned array may or may not be empty.
153  
-     */
154  
-    public function getAttached($byName = null)
155  
-    {
156  
-        if (!$byName) {
157  
-            return array_values($this->observers);
158  
-        }
159  
-
160  
-        return array_values(array_filter($this->observers, function($o) use ($byName) {
161  
-            return $o instanceof $byName;
162  
-        }));
163  
-    }
164  
-
165  
-    /**
166  
-     * Get the mediated {@see Subject} or NULL if no Subject has been associated
167  
-     *
168  
-     * @return Subject|null
169  
-     */
170  
-    public function getSubject()
171  
-    {
172  
-        return $this->subject;
173  
-    }
174  
-
175  
-    /**
176  
-     * Check if a certain observer or type of observer is attached
177  
-     *
178  
-     * @param string|Observer|Closure $observer Observer to check for.  Pass the
179  
-     *      name of an observer, a concrete {@see Observer}, or Closure
180  
-     *
181  
-     * @return bool
182  
-     */
183  
-    public function hasObserver($observer)
184  
-    {
185  
-        if (is_object($observer)) {
186  
-            return isset($this->observers[spl_object_hash($observer)]);
187  
-        } else if (is_string($observer)) {
188  
-            foreach ($this->observers as $item) {
189  
-                if ($item instanceOf $observer) {
190  
-                    return true;
191  
-                }
192  
-            }
193  
-        }
194  
-
195  
-        return false;
196  
-    }
197  
-
198  
-    /**
199  
-     * Get the priority level that an observer was attached at
200  
-     *
201  
-     * @param object $observer Observer to get the priority level of
202  
-     *
203  
-     * @return int|null Returns the priortity level or NULl if not attached
204  
-     */
205  
-    public function getPriority($observer)
206  
-    {
207  
-        if (is_object($observer)) {
208  
-            $hash = spl_object_hash($observer);
209  
-            if (array_key_exists($hash, $this->priorities)) {
210  
-                return $this->priorities[$hash];
211  
-            }
212  
-        }
213  
-
214  
-        return null;
215  
-    }
216  
-
217  
-    /**
218  
-     * Notify a single observer of an event