├── .gitignore
├── .scrutinizer.yml
├── .travis.yml
├── CHANGELOG.md
├── LICENSE
├── README.md
├── composer.json
├── example
├── make_a_delete_request
├── make_a_get_request
├── make_a_patch_request
├── make_a_post_request
└── make_a_put_request
├── phpunit.xml.dist
├── source
├── Builder
│ ├── Builder.php
│ └── BuilderFactory.php
├── Dispatcher
│ ├── Dispatcher.php
│ ├── DispatcherInterface.php
│ └── LoggingDispatcher.php
├── FactoryInterface.php
├── HeaderLine
│ ├── AbstractContentType.php
│ ├── AbstractHeaderLine.php
│ ├── AcceptEncoding.php
│ ├── AcceptLanguage.php
│ ├── ContentTypeIsUtf8Form.php
│ ├── ContentTypeIsUtf8Html.php
│ ├── ContentTypeIsUtf8Json.php
│ ├── Custom.php
│ └── HeaderLineInterface.php
├── Option
│ ├── AbstractAuthentication.php
│ ├── AbstractSetOptionArrayValue.php
│ ├── AbstractSetOptionClosureValue.php
│ ├── AbstractSetOptionIntValue.php
│ ├── AbstractSetOptionMixedValue.php
│ ├── AbstractSetOptionStreamValue.php
│ ├── AbstractSetOptionStringValue.php
│ ├── AbstractSetOptionToFalse.php
│ ├── AbstractSetOptionToTrue.php
│ ├── Authentication
│ │ ├── EnableUnrestrictedAuth.php
│ │ ├── SetBasicAuthentication.php
│ │ ├── SetKeyPassword.php
│ │ └── SetUsernameAndPassword.php
│ ├── Authorization
│ │ └── EnableNetrc.php
│ ├── Behaviour
│ │ ├── DisableBody.php
│ │ ├── DisableProgress.php
│ │ ├── DisableSignal.php
│ │ ├── EnableAutoReferer.php
│ │ ├── EnableFailOnError.php
│ │ ├── EnableFollowAllocation.php
│ │ ├── EnableForbidReuse.php
│ │ ├── EnableFreshConnect.php
│ │ ├── EnableMute.php
│ │ ├── EnableVerbose.php
│ │ ├── SetConnectTimeOutInMilliSeconds.php
│ │ ├── SetConnectTimeOutInSeconds.php
│ │ ├── SetDnsCacheTimeout.php
│ │ ├── SetHttp200Aliases.php
│ │ ├── SetLowSpeedLimit.php
│ │ ├── SetMaxConnects.php
│ │ ├── SetMaxRedirs.php
│ │ ├── SetRange.php
│ │ ├── SetRedirProtocols.php
│ │ ├── SetResumeFrom.php
│ │ ├── SetStderr.php
│ │ ├── SetTcpNoDelay.php
│ │ ├── SetTimeCondition.php
│ │ ├── SetTimeOutInMilliSeconds.php
│ │ └── SetTimeOutInSeconds.php
│ ├── Callback
│ │ ├── SetCallbackForPassWordFunction.php
│ │ ├── SetCallbackForProgressFunction.php
│ │ ├── SetCallbackForReadFunction.php
│ │ └── SetCallbackForWriteFunction.php
│ ├── Cookie
│ │ ├── EnableCookieSession.php
│ │ ├── SetCookie.php
│ │ ├── SetCookieFile.php
│ │ └── SetCookieJar.php
│ ├── Ftp
│ │ ├── EnableFtpAppend.php
│ │ ├── EnableFtpAscii.php
│ │ ├── EnableFtpCreateMissingDirs.php
│ │ ├── EnableFtpListOnly.php
│ │ ├── EnableFtpUseEprt.php
│ │ ├── EnableFtpUseEpsv.php
│ │ ├── SetFtpPort.php
│ │ ├── SetFtpSslAuth.php
│ │ ├── SetPostQuote.php
│ │ └── SetQuote.php
│ ├── OptionInterface.php
│ ├── Security
│ │ ├── DisableSslVerifyHost.php
│ │ ├── DisableSslVerifyPeer.php
│ │ ├── EnableCertInfo.php
│ │ ├── SetCaInfo.php
│ │ ├── SetCaPath.php
│ │ ├── SetSslCert.php
│ │ ├── SetSslCertPasswd.php
│ │ ├── SetSslCertType.php
│ │ ├── SetSslCipherList.php
│ │ ├── SetSslEngine.php
│ │ ├── SetSslEngineDefault.php
│ │ ├── SetSslKey.php
│ │ ├── SetSslKeyPasswd.php
│ │ ├── SetSslKeyType.php
│ │ └── SetSslVersion.php
│ ├── SetOption.php
│ └── Transfer
│ │ ├── DisableDnsUseGlobalCache.php
│ │ ├── EnableBinaryTransfer.php
│ │ ├── EnableCrlf.php
│ │ ├── EnableFileTime.php
│ │ ├── EnableHeader.php
│ │ ├── EnableHttpProxyTunnel.php
│ │ ├── EnableSafeUpload.php
│ │ ├── EnableTransferText.php
│ │ ├── EnableUpload.php
│ │ ├── SetBufferSize.php
│ │ ├── SetEgdSocket.php
│ │ ├── SetEncoding.php
│ │ ├── SetFile.php
│ │ ├── SetHttpVersion.php
│ │ ├── SetInFile.php
│ │ ├── SetInFileSize.php
│ │ ├── SetInterface.php
│ │ ├── SetPort.php
│ │ ├── SetProxy.php
│ │ ├── SetProxyAuth.php
│ │ ├── SetProxyPort.php
│ │ ├── SetProxyType.php
│ │ ├── SetProxyUserPwd.php
│ │ ├── SetRandomFile.php
│ │ ├── SetReferer.php
│ │ ├── SetTimeValue.php
│ │ ├── SetUserAgent.php
│ │ └── SetWriteHeader.php
├── Request
│ ├── Request.php
│ └── RequestFactory.php
├── Response
│ └── Response.php
└── ResponseBehaviour
│ ├── ConvertJsonToArrayBehaviour.php
│ ├── ResponseBehaviourInterface.php
│ └── ThrowRuntimeExceptionIfStatusCodeIsAboveTheLimitBehaviour.php
└── test
├── AbstractTestCase.php
├── Builder
└── BuilderTest.php
├── Request
└── RequestTest.php
├── Response
└── ResponseTest.php
├── ResponseBehaviour
├── ConvertJsonToArrayBehaviourTest.php
└── ThrowRuntimeExceptionIfStatusCodeIsAboveTheLimitBehaviourTest.php
└── bootstrap.php
/.gitignore:
--------------------------------------------------------------------------------
1 | .idea
2 | *.iml
3 | composer.lock
4 | vendor
5 |
--------------------------------------------------------------------------------
/.scrutinizer.yml:
--------------------------------------------------------------------------------
1 | filter:
2 | paths:
3 | - source/*
4 | excluded_paths:
5 | - vendor/*
6 |
7 | checks:
8 | php:
9 | code_rating: true
10 | duplication: true
11 |
--------------------------------------------------------------------------------
/.travis.yml:
--------------------------------------------------------------------------------
1 | language: php
2 | php:
3 | - 5.6
4 | - 7.0
5 | - 7.1
6 | - 7.2
7 | before_script:
8 | - composer self-update
9 | - composer install
10 | - phpenv rehash
11 | script:
12 | - vendor/bin/phpunit -v --colors --coverage-text
13 | notifications:
14 | email:
15 | - artodeto@bazzline.net
16 | sudo: false
17 |
--------------------------------------------------------------------------------
/CHANGELOG.md:
--------------------------------------------------------------------------------
1 | # Change Log
2 |
3 | All notable changes to this project will be documented in this file.
4 |
5 | The format is based on [Keep a Changelog](http://keepachangelog.com/)
6 | and this project adheres to [Semantic Versioning](http://semver.org/).
7 |
8 | ## [Open]
9 |
10 | ### To Add
11 |
12 | * to discuss
13 | * add [dispatcher](https://github.com/jyggen/curl/blob/master/src/Dispatcher.php) or HandlerGenerator/HandlerFactory
14 | * https://secure.php.net/manual/en/function.curl-init.php
15 | * https://secure.php.net/manual/en/function.curl-multi-init.php
16 | * add RequestModifier
17 | * e.g. for adding the JsonModifier which converts the data into a json, adds the fitting ContentType etc.
18 | * add support for parallel request execution like in the [stil/curl](https://github.com/stil/curl-easy) library
19 | * replace current dispatcher and logging dispatcher strategy with an event driven approach (currently only needed for logging)?
20 | * create Request Data Domain Object
21 | * create Request Options Domain Object
22 |
23 | ### To Change
24 |
25 | ## [Unreleased]
26 |
27 | ### Added
28 |
29 | * added php 7.2 to the travis test
30 |
31 | ### Changed
32 |
33 | * updated composer.json file and restricted php version to 5.6 as minimum
34 |
35 | ## [1.0.0](https://github.com/bazzline/php_component_curl/tree/1.0.0) - released at 2017-04-23
36 |
37 | ### Added
38 |
39 | * support for php version 7.1
40 |
41 | ### Changed
42 |
43 | * dropped support for php version below 5.6
44 | * moved release history from the README.md into this dedicated CHANGELOG.md
45 | * replaced "array()" notation with "[]"
46 |
47 | ## [0.15.1](https://github.com/bazzline/php_component_curl/tree/0.15.1) - released at 2017-03-29
48 |
49 | ### Changed
50 |
51 | * moved phpunit dependency to 5.7
52 |
53 | ## [0.15.0](https://github.com/bazzline/php_component_curl/tree/0.15.0) - released at 2016-10-27
54 |
55 | ### Changed
56 |
57 | * support to send data when calling http method DELETE
58 |
59 | ## [0.14.4](https://github.com/bazzline/php_component_curl/tree/0.14.4) - released at 2016-09-20
60 |
61 | ### Added
62 |
63 | * [AcceptLanguate](https://github.com/bazzline/php_component_curl/blob/0.14.4/source/HeaderLine/AcceptLanguage.php) header line
64 |
65 | ## [0.14.3](https://github.com/bazzline/php_component_curl/tree/0.14.3) - released at 2016-09-19
66 |
67 | ### Added
68 |
69 | * [AcceptEncoding](https://github.com/bazzline/php_component_curl/blob/0.14.3/source/HeaderLine/AcceptEncoding.php) header line
70 | * [Custom](https://github.com/bazzline/php_component_curl/blob/0.14.3/source/HeaderLine/Custom.php) header line
71 | * started more examples section
72 |
73 | ### Changed
74 |
75 | * updated phpunit to 5.5.*
76 |
77 | ## [0.14.2](https://github.com/bazzline/php_component_curl/tree/0.14.2) - released at 2016-05-30
78 |
79 | ### Changed
80 |
81 | * relaxed dependency to mockery
82 |
83 | ## [0.14.1](https://github.com/bazzline/php_component_curl/tree/0.14.1) - released at 2016-03-11
84 |
85 | ### Changed
86 |
87 | * removed *.php* for examples and made them executable
88 | * updated dependencies
89 |
90 | ## [0.14.0](https://github.com/bazzline/php_component_curl/tree/0.14.0) - released at 2016-02-26
91 |
92 | ### Changed
93 |
94 | * removed default header "application/x-www-form-urlencoded; charset=UTF-8" and added new *ContentTypeUtf8Html*
95 |
96 | ## [0.13.0](https://github.com/bazzline/php_component_curl/tree/0.13.0) - released at 2016-02-17
97 |
98 | ### Changed
99 |
100 | * fixed "ConverteJsonToArayBehaviour" by merging [pull request 3](https://github.com/bazzline/php_component_curl/pull/3)
101 |
102 | ## [0.12.0](https://github.com/bazzline/php_component_curl/tree/0.12.0) - released at 2016-02-08
103 |
104 | ### Added
105 |
106 | * *curl_close($handler)* in default *Dispatcher*
107 |
108 | ### Changed
109 |
110 | * fixed bug in *BuilderFactory::createRequestFromFactory()*
111 | * fixed bug in *RequestFactory::create()*
112 |
113 | ## [0.11.0](https://github.com/bazzline/php_component_curl/tree/0.11.0) - released at 2016-02-08
114 |
115 | * fixed major bug in *createRequestFromFactory* to *BuilderFactory*
116 | * refactored internals of Builder::andFetchTheResponse()
117 | * refactored internals of Request::execute()
118 | * refactored internals of RequestFactory::create()
119 |
120 | ## [0.10.0](https://github.com/bazzline/php_component_curl/tree/0.10.0) - released at 08.02.2016
121 |
122 | ### Added
123 |
124 | * public *overwriteRequestFactory()* to *BuilderFactory*
125 |
126 | ### Changed
127 |
128 | * fixed broken links in the readme
129 | * moved to *psr-4* autoloading
130 | * removed dedicated integration test for php 5.3.3
131 |
132 | ## [0.9.1](https://github.com/bazzline/php_component_curl/tree/0.9.1) - released at 2016-01-14
133 |
134 | ### Changed
135 |
136 | * updated dependencies
137 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | GNU LESSER GENERAL PUBLIC LICENSE
2 | Version 3, 29 June 2007
3 |
4 | Copyright (C) 2007 Free Software Foundation, Inc.
5 | Everyone is permitted to copy and distribute verbatim copies
6 | of this license document, but changing it is not allowed.
7 |
8 |
9 | This version of the GNU Lesser General Public License incorporates
10 | the terms and conditions of version 3 of the GNU General Public
11 | License, supplemented by the additional permissions listed below.
12 |
13 | 0. Additional Definitions.
14 |
15 | As used herein, "this License" refers to version 3 of the GNU Lesser
16 | General Public License, and the "GNU GPL" refers to version 3 of the GNU
17 | General Public License.
18 |
19 | "The Library" refers to a covered work governed by this License,
20 | other than an Application or a Combined Work as defined below.
21 |
22 | An "Application" is any work that makes use of an interface provided
23 | by the Library, but which is not otherwise based on the Library.
24 | Defining a subclass of a class defined by the Library is deemed a mode
25 | of using an interface provided by the Library.
26 |
27 | A "Combined Work" is a work produced by combining or linking an
28 | Application with the Library. The particular version of the Library
29 | with which the Combined Work was made is also called the "Linked
30 | Version".
31 |
32 | The "Minimal Corresponding Source" for a Combined Work means the
33 | Corresponding Source for the Combined Work, excluding any source code
34 | for portions of the Combined Work that, considered in isolation, are
35 | based on the Application, and not on the Linked Version.
36 |
37 | The "Corresponding Application Code" for a Combined Work means the
38 | object code and/or source code for the Application, including any data
39 | and utility programs needed for reproducing the Combined Work from the
40 | Application, but excluding the System Libraries of the Combined Work.
41 |
42 | 1. Exception to Section 3 of the GNU GPL.
43 |
44 | You may convey a covered work under sections 3 and 4 of this License
45 | without being bound by section 3 of the GNU GPL.
46 |
47 | 2. Conveying Modified Versions.
48 |
49 | If you modify a copy of the Library, and, in your modifications, a
50 | facility refers to a function or data to be supplied by an Application
51 | that uses the facility (other than as an argument passed when the
52 | facility is invoked), then you may convey a copy of the modified
53 | version:
54 |
55 | a) under this License, provided that you make a good faith effort to
56 | ensure that, in the event an Application does not supply the
57 | function or data, the facility still operates, and performs
58 | whatever part of its purpose remains meaningful, or
59 |
60 | b) under the GNU GPL, with none of the additional permissions of
61 | this License applicable to that copy.
62 |
63 | 3. Object Code Incorporating Material from Library Header Files.
64 |
65 | The object code form of an Application may incorporate material from
66 | a header file that is part of the Library. You may convey such object
67 | code under terms of your choice, provided that, if the incorporated
68 | material is not limited to numerical parameters, data structure
69 | layouts and accessors, or small macros, inline functions and templates
70 | (ten or fewer lines in length), you do both of the following:
71 |
72 | a) Give prominent notice with each copy of the object code that the
73 | Library is used in it and that the Library and its use are
74 | covered by this License.
75 |
76 | b) Accompany the object code with a copy of the GNU GPL and this license
77 | document.
78 |
79 | 4. Combined Works.
80 |
81 | You may convey a Combined Work under terms of your choice that,
82 | taken together, effectively do not restrict modification of the
83 | portions of the Library contained in the Combined Work and reverse
84 | engineering for debugging such modifications, if you also do each of
85 | the following:
86 |
87 | a) Give prominent notice with each copy of the Combined Work that
88 | the Library is used in it and that the Library and its use are
89 | covered by this License.
90 |
91 | b) Accompany the Combined Work with a copy of the GNU GPL and this license
92 | document.
93 |
94 | c) For a Combined Work that displays copyright notices during
95 | execution, include the copyright notice for the Library among
96 | these notices, as well as a reference directing the user to the
97 | copies of the GNU GPL and this license document.
98 |
99 | d) Do one of the following:
100 |
101 | 0) Convey the Minimal Corresponding Source under the terms of this
102 | License, and the Corresponding Application Code in a form
103 | suitable for, and under terms that permit, the user to
104 | recombine or relink the Application with a modified version of
105 | the Linked Version to produce a modified Combined Work, in the
106 | manner specified by section 6 of the GNU GPL for conveying
107 | Corresponding Source.
108 |
109 | 1) Use a suitable shared library mechanism for linking with the
110 | Library. A suitable mechanism is one that (a) uses at run time
111 | a copy of the Library already present on the user's computer
112 | system, and (b) will operate properly with a modified version
113 | of the Library that is interface-compatible with the Linked
114 | Version.
115 |
116 | e) Provide Installation Information, but only if you would otherwise
117 | be required to provide such information under section 6 of the
118 | GNU GPL, and only to the extent that such information is
119 | necessary to install and execute a modified version of the
120 | Combined Work produced by recombining or relinking the
121 | Application with a modified version of the Linked Version. (If
122 | you use option 4d0, the Installation Information must accompany
123 | the Minimal Corresponding Source and Corresponding Application
124 | Code. If you use option 4d1, you must provide the Installation
125 | Information in the manner specified by section 6 of the GNU GPL
126 | for conveying Corresponding Source.)
127 |
128 | 5. Combined Libraries.
129 |
130 | You may place library facilities that are a work based on the
131 | Library side by side in a single library together with other library
132 | facilities that are not Applications and are not covered by this
133 | License, and convey such a combined library under terms of your
134 | choice, if you do both of the following:
135 |
136 | a) Accompany the combined library with a copy of the same work based
137 | on the Library, uncombined with any other library facilities,
138 | conveyed under the terms of this License.
139 |
140 | b) Give prominent notice with the combined library that part of it
141 | is a work based on the Library, and explaining where to find the
142 | accompanying uncombined form of the same work.
143 |
144 | 6. Revised Versions of the GNU Lesser General Public License.
145 |
146 | The Free Software Foundation may publish revised and/or new versions
147 | of the GNU Lesser General Public License from time to time. Such new
148 | versions will be similar in spirit to the present version, but may
149 | differ in detail to address new problems or concerns.
150 |
151 | Each version is given a distinguishing version number. If the
152 | Library as you received it specifies that a certain numbered version
153 | of the GNU Lesser General Public License "or any later version"
154 | applies to it, you have the option of following the terms and
155 | conditions either of that published version or of any later version
156 | published by the Free Software Foundation. If the Library as you
157 | received it does not specify a version number of the GNU Lesser
158 | General Public License, you may choose any version of the GNU Lesser
159 | General Public License ever published by the Free Software Foundation.
160 |
161 | If the Library as you received it specifies that a proxy can decide
162 | whether future versions of the GNU Lesser General Public License shall
163 | apply, that proxy's public statement of acceptance of any version is
164 | permanent authorization for you to choose that version for the
165 | Library.
166 |
167 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Simple Curl Wrapper Component for PHP
2 |
3 | This project aims to deliver an easy to use and free as in freedom object oriented php curl command component.
4 |
5 | The build status of the current master branch is tracked by Travis CI:
6 | [](http://travis-ci.org/bazzline/php_component_curl)
7 | [](https://packagist.org/packages/net_bazzline/php_component_curl)
8 |
9 | The scrutinizer status is:
10 | [](https://scrutinizer-ci.com/g/bazzline/php_component_curl/)
11 |
12 | The versioneye status is:
13 | [](https://www.versioneye.com/user/projects/553941560b24225ef6000002)
14 |
15 | Take a look on [openhub.net](https://www.openhub.net/p/php_component_curl).
16 |
17 | The current change log can be found [here](https://github.com/bazzline/php_component_curl/blob/master/CHANGELOG.md).
18 |
19 | This component is not developed to replace [guzzle](http://docs.guzzlephp.org/en/latest/).
20 |
21 | # Example
22 |
23 | ## By Using The Builder
24 |
25 | ```php
26 | //it is always good to ship the component with a factory to easy up usage
27 | use Net\Bazzline\Component\Curl\BuilderFactory;
28 | use Net\Bazzline\Component\Curl\Option\Timeout;
29 |
30 | $factory = new BuilderFactory();
31 | $builder = $factory->create();
32 | $url = 'http://www.foo.bar';
33 | $timeout = new Timeout(10); //set the timeout to 10 seconds
34 |
35 | /**
36 | * you can also use:
37 | * //assuming that $dispatcher is an instance of DispatcherInterface
38 | * //assuming that $requestFactory is an instance of RequestFactory
39 | * $builder->overwriteDispatcher($dispatcher);
40 | * $builder->overwriteRequestFactory($requestFactory);
41 | */
42 |
43 | $response = $builder->usePost()
44 | ->onTheUrl($url)
45 | ->withTheData($data)
46 | ->withTheParameters(array('descendingOrderBy' => 'id'))
47 | ->withTheOption($timeout)
48 | ->andFetchTheResponse();
49 |
50 | /**
51 | * you can also use:
52 | * $builder->withTheHeaderLine($headLine) //add the headline you want
53 | * $builder->withResponseModifier($modifier) //add the response modifier you want
54 | */
55 |
56 | echo 'content: ' . $response->content() . PHP_EOL;
57 | echo 'content type: ' . $response->contentType() . PHP_EOL;
58 | echo 'error:' . $response->error() . PHP_EOL;
59 | echo 'error code:' . $response->errorCode() . PHP_EOL;
60 | echo 'head lines: ' . var_export($response->headerLines(), true) . PHP_EOL;
61 | echo 'status code: ' . $response->statusCode() . PHP_EOL;
62 | ```
63 |
64 | ## By Using The Request
65 |
66 | ```php
67 | //it is always good to ship the component with a factory to easy up usage
68 | $factory = new Net\Bazzline\Component\Curl\RequestFactory();
69 | $request = $factory->create();
70 | $url = 'http://www.foo.bar';
71 |
72 | $response = $request->get($url);
73 |
74 | echo 'content: ' . $response->content() . PHP_EOL;
75 | echo 'content type: ' . $response->contentType() . PHP_EOL;
76 | echo 'error:' . $response->error() . PHP_EOL;
77 | echo 'error code:' . $response->errorCode() . PHP_EOL;
78 | echo 'head lines: ' . var_export($response->headerLines(), true) . PHP_EOL;
79 | echo 'status code: ' . $response->statusCode() . PHP_EOL;
80 | ```
81 |
82 | ## Executable Examples
83 |
84 | * [Delete Request](https://github.com/bazzline/php_component_curl/blob/master/example/make_a_delete_request)
85 | * [Get Request](https://github.com/bazzline/php_component_curl/blob/master/example/make_a_delete_request)
86 | * [Patch Request](https://github.com/bazzline/php_component_curl/blob/master/example/make_a_patch_request)
87 | * [Post Request](https://github.com/bazzline/php_component_curl/blob/master/example/make_a_post_request)
88 | * [Put Request](https://github.com/bazzline/php_component_curl/blob/master/example/make_a_put_request)
89 |
90 | ## More Examples
91 |
92 | ### Post Request With Basic Authentication
93 |
94 | ```
95 | //begin of runtime environments
96 | $factory = new BuilderFactory();
97 | $builder = $factory->create();
98 | $data = array(
99 | 'there' => 'is',
100 | 'no' => 'foo',
101 | 'without' => 'a bar'
102 | );
103 | $password = '';
104 | $username = 'foo@bar.ru';
105 | $url = 'https://foo.bar.ru/api/my/rest/endpoint/v1';
106 | //end of runtime environments
107 |
108 | //begin building the request
109 | $builder->asJson();
110 | $builder->onTheUrl($url);
111 | $builder->withTheData($data);
112 | $builder->withTheOption(new SetBasicAuthentication());
113 | $builder->withTheOption(new SetUsernameAndPassword($username, $password));
114 | $builder->usePost();
115 | //end building the request
116 |
117 | $request = $builder->andFetchTheResponse();
118 | echo PHP_EOL . 'dumping the request' . PHP_EOL;
119 | var_dump($request);
120 | ```
121 |
122 | # Terms
123 |
124 | * [Dispatcher](https://github.com/bazzline/php_component_curl/blob/master/source/Net/Bazzline/Component/Curl/Dispatcher/Dispatcher.php)
125 | * doing the curl request
126 | * if you want to use pure curl, use this class
127 | * [Request](https://github.com/bazzline/php_component_curl/blob/master/source/Net/Bazzline/Component/Curl/Request/Request.php)
128 | * object oriented approach reflecting the request
129 | * [HeadLine](https://github.com/bazzline/php_component_curl/blob/master/source/Net/Bazzline/Component/Curl/HeadLine/HeadLineInterface.php)
130 | * object oriented [http headers](https://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html) ([list](https://en.wikipedia.org/wiki/List_of_HTTP_header_fields) of available headers), start a pull request if you need more
131 | * [Options](https://github.com/bazzline/php_component_curl/blob/master/source/Net/Bazzline/Component/Curl/Option/OptionInterface.php)
132 | * object oriented curl options, start a pull request if you need more
133 | * Parameters
134 | * all the parameters you want to add to your url - they are urlencoded automatically
135 | * Url
136 | * the url of your endpoint
137 | * [Response](https://github.com/bazzline/php_component_curl/blob/master/source/Net/Bazzline/Component/Curl/Response/Response.php)
138 | * object oriented approach reflecting the response
139 | * [ResponseBehaviour](https://github.com/bazzline/php_component_curl/blob/master/source/Net/Bazzline/Component/Curl/ResponseBehaviour/ResponseBehaviourInterface.php)
140 | * interface to interact with the response
141 | * either modify the response (by creating a new one)
142 | * change the flow by throwing an exception if the response does not fits your needs (as example)
143 | * [Builder](https://github.com/bazzline/php_component_curl/blob/master/source/Net/Bazzline/Component/Curl/Builder/Builder.php)
144 | * provides a fluent interface to easy up using curl
145 | * it takes care of all :-)
146 |
147 | # Not Available Curl Options
148 |
149 | In general, the php version is limiting the available [curl options](http://php.net/manual/en/curl.constants.php).
150 | Furthermore, some options are not implemented because of their hardcoded usage in the *Response* or the *Dispatcher* (you can set it but they would be overwritten).
151 |
152 | This options are:
153 |
154 | * used in the *Request*
155 | * CURLOPT_CUSTOMREQUEST
156 | * CURLOPT_HTTPHEADER
157 | * CURLOPT_POSTFIELDS
158 | * used in the *Dispatcher*
159 | * CURLINFO_HEADER_OUT
160 | * CURLOPT_HEADERFUNCTION
161 | * CURLOPT_RETURNTRANSFER
162 |
163 | If you want to change this, you either have to extend the existing *Request* or *Dispatcher* object.
164 |
165 | # Install
166 |
167 | ## By Hand
168 |
169 | ```
170 | mkdir -p vendor/net_bazzline/php_component_curl
171 | cd vendor/net_bazzline/php_component_curl
172 | git clone https://github.com/bazzline/php_component_curl .
173 | ```
174 |
175 | ## With [Packagist](https://packagist.org/packages/net_bazzline/php_component_curl)
176 |
177 | ```
178 | composer require net_bazzline/php_component_curl:dev-master
179 | ```
180 |
181 | # Links
182 |
183 | * http://resttesttest.com/
184 |
185 | ## Other Components Available
186 |
187 | * https://github.com/php-mod/curl
188 | * https://github.com/anlutro/php-curl
189 | * https://github.com/hamstar/curl
190 | * https://github.com/jyggen/curl
191 | * https://github.com/ixudra/Curl
192 | * https://github.com/brodkinca/BCA-PHP-CURL
193 | * https://github.com/miliqi/laravel-curl
194 | * https://github.com/andrefigueira/Lib-Curl
195 |
196 | # Final Words
197 |
198 | Star it if you like it :-). Add issues if you need it. Pull patches if you enjoy it. Write a blog entry if you use it. [Donate something](https://gratipay.com/~stevleibelt) if you love it :-].
199 |
--------------------------------------------------------------------------------
/composer.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "net_bazzline/php_component_curl",
3 | "description": "free as in freedom simple object oriented curl request and response component (YACC - yet another curl component)",
4 | "keywords": [
5 | "bazzline",
6 | "psr",
7 | "psr-4",
8 | "curl",
9 | "oop",
10 | "yet another",
11 | "request",
12 | "response",
13 | "dispatcher",
14 | "lgpl",
15 | "free as in freedom",
16 | "yacc",
17 | "php56",
18 | "php7",
19 | "changelog"
20 | ],
21 | "type": "library",
22 | "minimum-stability": "dev",
23 | "require": {
24 | "net_bazzline/php_component_toolbox": "1.9.*",
25 | "php": ">=5.6"
26 | },
27 | "require-dev": {
28 | "mockery/mockery": "0.9.*",
29 | "phpunit/phpunit": "^5.7"
30 | },
31 | "license": "LGPL-3.0",
32 | "authors": [
33 | {
34 | "name": "Stev Leibelt",
35 | "email": "artodeto@bazzline.net",
36 | "homepage": "https://artodeto.bazzline.net",
37 | "role": "Developer"
38 | }
39 | ],
40 | "autoload": {
41 | "psr-4": {
42 | "Net\\Bazzline\\Component\\Curl\\": "source/"
43 | }
44 | },
45 | "autoload-dev": {
46 | "psr-4": {
47 | "Test\\Net\\Bazzline\\Component\\Curl\\": "test/"
48 | }
49 | }
50 | }
51 |
--------------------------------------------------------------------------------
/example/make_a_delete_request:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env php
2 |
5 | * @since 2015-12-10
6 | */
7 |
8 | require_once __DIR__ . '/../vendor/autoload.php';
9 |
10 | use Net\Bazzline\Component\Curl\Builder\BuilderFactory;
11 | use Net\Bazzline\Component\Curl\Dispatcher\LoggingDispatcher;
12 |
13 | $factory = new BuilderFactory();
14 | $factory->overwriteDispatcher(new LoggingDispatcher());
15 | $builder = $factory->create();
16 | $url = ($argc > 1) ? $argv[1] : 'https://httpbin.org/get';
17 |
18 | $response = $builder->onTheUrl($url)
19 | ->useDelete()
20 | ->andFetchTheResponse();
21 |
22 | echo 'content: ' . $response->content() . PHP_EOL;
23 | echo 'content type: ' . $response->contentType() . PHP_EOL;
24 | echo 'head lines: ' . var_export($response->headerLines(), true) . PHP_EOL;
25 | echo 'error:' . $response->error() . PHP_EOL;
26 | echo 'error code:' . $response->errorCode() . PHP_EOL;
27 | echo 'status code: ' . $response->statusCode() . PHP_EOL;
28 |
--------------------------------------------------------------------------------
/example/make_a_get_request:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env php
2 |
5 | * @since 2015-12-10
6 | */
7 |
8 | require_once __DIR__ . '/../vendor/autoload.php';
9 |
10 | use Net\Bazzline\Component\Curl\Builder\BuilderFactory;
11 | use Net\Bazzline\Component\Curl\Dispatcher\LoggingDispatcher;
12 |
13 | $factory = new BuilderFactory();
14 | $factory->overwriteDispatcher(new LoggingDispatcher());
15 | $builder = $factory->create();
16 | $url = ($argc > 1) ? $argv[1] : 'https://httpbin.org/get';
17 |
18 | $response = $builder->onTheUrl($url)
19 | ->useGet()
20 | ->andFetchTheResponse();
21 |
22 | echo 'content: ' . $response->content() . PHP_EOL;
23 | echo 'content type: ' . $response->contentType() . PHP_EOL;
24 | echo 'head lines: ' . var_export($response->headerLines(), true) . PHP_EOL;
25 | echo 'error:' . $response->error() . PHP_EOL;
26 | echo 'error code:' . $response->errorCode() . PHP_EOL;
27 | echo 'status code: ' . $response->statusCode() . PHP_EOL;
28 |
--------------------------------------------------------------------------------
/example/make_a_patch_request:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env php
2 |
5 | * @since 2015-12-10
6 | */
7 |
8 | require_once __DIR__ . '/../vendor/autoload.php';
9 |
10 | use Net\Bazzline\Component\Curl\Builder\BuilderFactory;
11 | use Net\Bazzline\Component\Curl\Dispatcher\LoggingDispatcher;
12 |
13 | $factory = new BuilderFactory();
14 | $factory->overwriteDispatcher(new LoggingDispatcher());
15 | $builder = $factory->create();
16 | $url = ($argc > 1) ? $argv[1] : 'https://httpbin.org/get';
17 |
18 | $response = $builder->onTheUrl($url)
19 | ->usePatch()
20 | ->andFetchTheResponse();
21 |
22 | echo 'content: ' . $response->content() . PHP_EOL;
23 | echo 'content type: ' . $response->contentType() . PHP_EOL;
24 | echo 'head lines: ' . var_export($response->headerLines(), true) . PHP_EOL;
25 | echo 'error:' . $response->error() . PHP_EOL;
26 | echo 'error code:' . $response->errorCode() . PHP_EOL;
27 | echo 'status code: ' . $response->statusCode() . PHP_EOL;
28 |
--------------------------------------------------------------------------------
/example/make_a_post_request:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env php
2 |
5 | * @since 2015-12-10
6 | */
7 |
8 | require_once __DIR__ . '/../vendor/autoload.php';
9 |
10 | use Net\Bazzline\Component\Curl\Builder\BuilderFactory;
11 | use Net\Bazzline\Component\Curl\Dispatcher\LoggingDispatcher;
12 |
13 | $factory = new BuilderFactory();
14 | $factory->overwriteDispatcher(new LoggingDispatcher());
15 | $builder = $factory->create();
16 | $url = ($argc > 1) ? $argv[1] : 'https://httpbin.org/get';
17 |
18 | $response = $builder->onTheUrl($url)
19 | ->usePost()
20 | ->andFetchTheResponse();
21 |
22 | echo 'content: ' . $response->content() . PHP_EOL;
23 | echo 'content type: ' . $response->contentType() . PHP_EOL;
24 | echo 'head lines: ' . var_export($response->headerLines(), true) . PHP_EOL;
25 | echo 'error:' . $response->error() . PHP_EOL;
26 | echo 'error code:' . $response->errorCode() . PHP_EOL;
27 | echo 'status code: ' . $response->statusCode() . PHP_EOL;
28 |
--------------------------------------------------------------------------------
/example/make_a_put_request:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env php
2 |
5 | * @since 2015-12-10
6 | */
7 |
8 | require_once __DIR__ . '/../vendor/autoload.php';
9 |
10 | use Net\Bazzline\Component\Curl\Builder\BuilderFactory;
11 | use Net\Bazzline\Component\Curl\Dispatcher\LoggingDispatcher;
12 |
13 | $factory = new BuilderFactory();
14 | $factory->overwriteDispatcher(new LoggingDispatcher());
15 | $builder = $factory->create();
16 | $url = ($argc > 1) ? $argv[1] : 'https://httpbin.org/get';
17 |
18 | $response = $builder->onTheUrl($url)
19 | ->usePut()
20 | ->andFetchTheResponse();
21 |
22 | echo 'content: ' . $response->content() . PHP_EOL;
23 | echo 'content type: ' . $response->contentType() . PHP_EOL;
24 | echo 'head lines: ' . var_export($response->headerLines(), true) . PHP_EOL;
25 | echo 'error:' . $response->error() . PHP_EOL;
26 | echo 'error code:' . $response->errorCode() . PHP_EOL;
27 | echo 'status code: ' . $response->statusCode() . PHP_EOL;
28 |
--------------------------------------------------------------------------------
/phpunit.xml.dist:
--------------------------------------------------------------------------------
1 |
11 |
12 |
13 |
14 | test/
15 |
16 |
17 |
18 |
--------------------------------------------------------------------------------
/source/Builder/Builder.php:
--------------------------------------------------------------------------------
1 |
4 | * @since 2015-12-08
5 | */
6 | namespace Net\Bazzline\Component\Curl\Builder;
7 |
8 | use Exception;
9 | use Net\Bazzline\Component\Curl\HeaderLine\HeaderLineInterface;
10 | use Net\Bazzline\Component\Curl\HeaderLine\ContentTypeIsUtf8Json;
11 | use Net\Bazzline\Component\Curl\Option\OptionInterface;
12 | use Net\Bazzline\Component\Curl\Request\Request;
13 | use Net\Bazzline\Component\Curl\Response\Response;
14 | use Net\Bazzline\Component\Curl\ResponseBehaviour\ConvertJsonToArrayBehaviour;
15 | use Net\Bazzline\Component\Curl\ResponseBehaviour\ResponseBehaviourInterface;
16 | use Net\Bazzline\Component\Toolbox\HashMap\Merge;
17 | use RuntimeException;
18 |
19 | class Builder
20 | {
21 | const METHOD_DELETE = 0;
22 | const METHOD_GET = 1;
23 | const METHOD_PATCH = 2;
24 | const METHOD_POST = 3;
25 | const METHOD_PUT = 4;
26 |
27 | /** @var boolean */
28 | private $asJson;
29 |
30 | /** @var null|string|array */
31 | private $data;
32 |
33 | /** @var array|ResponseBehaviourInterface[] */
34 | private $defaultResponseBehaviours;
35 |
36 | /** @var Merge */
37 | private $merge;
38 |
39 | /** @var int */
40 | private $method;
41 |
42 | /** @var array */
43 | private $parameters;
44 |
45 | /** @var Request */
46 | private $request;
47 |
48 | /** @var array|ResponseBehaviourInterface[] */
49 | private $responseBehaviours;
50 |
51 | /** @var string */
52 | private $url;
53 |
54 | /**
55 | * @param Request $request
56 | * @param Merge $merge
57 | * @param array|ResponseBehaviourInterface[] $defaultResponseBehaviours
58 | */
59 | public function __construct(Request $request, Merge $merge, array $defaultResponseBehaviours = [])
60 | {
61 | $this->defaultResponseBehaviours = $defaultResponseBehaviours;
62 | $this->merge = $merge;
63 | $this->request = $request;
64 | $this->reset();
65 | }
66 |
67 | /**
68 | * @return Response
69 | * @throws Exception|RuntimeException
70 | */
71 | public function andFetchTheResponse()
72 | {
73 | //begin of dependencies
74 | $asJson = $this->asJson;
75 | $merge = $this->merge;
76 | $data = $this->data;
77 | $method = $this->method;
78 | $parameters = $this->parameters;
79 | $request = $this->request;
80 | $url = $this->url;
81 | //end of dependencies
82 |
83 | //begin of business logic
84 | /** @var ResponseBehaviourInterface[] $behaviours */
85 | $behaviours = $merge($this->responseBehaviours, $this->defaultResponseBehaviours);
86 | $data = $this->convertToJsonIfNeeded($data, $asJson);
87 | $response = $this->fetchResponseFromRequestOrThrowRuntimeException(
88 | $method,
89 | $request,
90 | $url,
91 | $parameters,
92 | $data
93 | );
94 | $response = $this->applyBehaviours($behaviours, $response);
95 | //end of business logic
96 |
97 | return $response;
98 | }
99 |
100 | /**
101 | * @return $this
102 | */
103 | public function asJson()
104 | {
105 | $this->asJson = true;
106 | $this->request->addHeaderLine(new ContentTypeIsUtf8Json());
107 | $this->responseBehaviours[] = new ConvertJsonToArrayBehaviour();
108 |
109 | return $this;
110 | }
111 |
112 | /**
113 | * @param bool $alsoTheDefaults
114 | * @return $this
115 | */
116 | public function reset($alsoTheDefaults = false)
117 | {
118 | $this->asJson = false;
119 | $this->data = null;
120 | $this->parameters = [];
121 | $this->request->reset($alsoTheDefaults);
122 | $this->responseBehaviours = [];
123 | $this->url = null;
124 |
125 | return $this;
126 | }
127 |
128 | /**
129 | * @param string $url
130 | * @return $this
131 | */
132 | public function onTheUrl($url)
133 | {
134 | $this->url = $url;
135 |
136 | return $this;
137 | }
138 |
139 | /**
140 | * @param null|string|array $data
141 | * @return $this
142 | */
143 | public function withTheData($data)
144 | {
145 | $this->data = $data;
146 |
147 | return $this;
148 | }
149 |
150 | /**
151 | * @param HeaderLineInterface $line
152 | * @return $this
153 | */
154 | public function withTheHeaderLine(HeaderLineInterface $line)
155 | {
156 | $this->request->addHeaderLine($line);
157 |
158 | return $this;
159 | }
160 |
161 | /**
162 | * @param OptionInterface $option
163 | * @return $this
164 | */
165 | public function withTheOption(OptionInterface $option)
166 | {
167 | $this->request->addOption($option);
168 |
169 | return $this;
170 | }
171 |
172 | /**
173 | * @param array $parameters
174 | * @return $this
175 | */
176 | public function withTheParameters(array $parameters)
177 | {
178 | $this->parameters = $parameters;
179 |
180 | return $this;
181 | }
182 |
183 | /**
184 | * @param string $line
185 | * @return $this
186 | */
187 | public function withTheRawHeaderLine($line)
188 | {
189 | $this->request->addRawHeaderLine($line);
190 |
191 | return $this;
192 | }
193 |
194 | /**
195 | * @param string $key
196 | * @param string $value
197 | * @return $this
198 | */
199 | public function withTheRawOption($key, $value)
200 | {
201 | $this->request->addRawOption($key, $value);
202 |
203 | return $this;
204 | }
205 |
206 | /**
207 | * @param ResponseBehaviourInterface $behaviour
208 | * @return $this
209 | */
210 | public function withTheResponseBehaviour(ResponseBehaviourInterface $behaviour)
211 | {
212 | $this->responseBehaviours[] = $behaviour;
213 |
214 | return $this;
215 | }
216 |
217 | //@todo better naming?
218 | // callDelete
219 | /**
220 | * @return $this
221 | */
222 | public function useDelete()
223 | {
224 | $this->method = self::METHOD_DELETE;
225 |
226 | return $this;
227 | }
228 |
229 | /**
230 | * @return $this
231 | */
232 | public function useGet()
233 | {
234 | $this->method = self::METHOD_GET;
235 |
236 | return $this;
237 | }
238 |
239 | /**
240 | * @return $this
241 | */
242 | public function usePatch()
243 | {
244 | $this->method = self::METHOD_PATCH;
245 |
246 | return $this;
247 | }
248 |
249 | /**
250 | * @return $this
251 | */
252 | public function usePost()
253 | {
254 | $this->method = self::METHOD_POST;
255 |
256 | return $this;
257 | }
258 |
259 | /**
260 | * @return $this
261 | */
262 | public function usePut()
263 | {
264 | $this->method = self::METHOD_PUT;
265 |
266 | return $this;
267 | }
268 |
269 | /**
270 | * @param array|ResponseBehaviourInterface[] $behaviours
271 | * @param Response $response
272 | * @return Response
273 | */
274 | private function applyBehaviours(array $behaviours, Response $response)
275 | {
276 | foreach ($behaviours as $behaviour) {
277 | $response = $behaviour->behave($response);
278 | }
279 |
280 | return $response;
281 | }
282 |
283 | /**
284 | * @param mixed $data
285 | * @param boolean $convertIt
286 | * @return mixed
287 | */
288 | private function convertToJsonIfNeeded($data, $convertIt)
289 | {
290 | return ($convertIt) ? json_encode($data) : $data;
291 | }
292 |
293 | /**
294 | * @param string $method
295 | * @param Request $request
296 | * @param string $url
297 | * @param array $parameters
298 | * @param mixed $data
299 | * @return Response
300 | * @throws RuntimeException
301 | */
302 | private function fetchResponseFromRequestOrThrowRuntimeException($method, Request $request, $url, array $parameters, $data)
303 | {
304 | switch ($method) {
305 | case self::METHOD_DELETE:
306 | $response = $request->delete($url, $parameters, $data);
307 | break;
308 | case self::METHOD_GET:
309 | $response = $request->get($url, $parameters);
310 | break;
311 | case self::METHOD_PATCH:
312 | $response = $request->patch($url, $parameters, $data);
313 | break;
314 | case self::METHOD_POST:
315 | $response = $request->post($url, $parameters, $data);
316 | break;
317 | case self::METHOD_PUT:
318 | $response = $request->put($url, $parameters, $data);
319 | break;
320 | default:
321 | throw new RuntimeException(
322 | 'no http method set'
323 | );
324 | }
325 |
326 | return $response;
327 | }
328 | }
329 |
--------------------------------------------------------------------------------
/source/Builder/BuilderFactory.php:
--------------------------------------------------------------------------------
1 |
4 | * @since 2015-12-09
5 | */
6 | namespace Net\Bazzline\Component\Curl\Builder;
7 |
8 | use Net\Bazzline\Component\Curl\Dispatcher\DispatcherInterface;
9 | use Net\Bazzline\Component\Curl\FactoryInterface;
10 | use Net\Bazzline\Component\Curl\Request\Request;
11 | use Net\Bazzline\Component\Curl\Request\RequestFactory;
12 | use Net\Bazzline\Component\Toolbox\HashMap\Merge;
13 |
14 | class BuilderFactory implements FactoryInterface
15 | {
16 | /** @var DispatcherInterface */
17 | private $dispatcher;
18 |
19 | /** @var RequestFactory */
20 | private $factory;
21 |
22 | /**
23 | * @return Builder|mixed
24 | */
25 | public function create()
26 | {
27 | $builder = new Builder(
28 | $this->createRequestFromFactory(),
29 | new Merge()
30 | );
31 |
32 | return $builder;
33 | }
34 |
35 | /**
36 | * @param DispatcherInterface $dispatcher
37 | */
38 | public function overwriteDispatcher(DispatcherInterface $dispatcher)
39 | {
40 | $this->dispatcher = $dispatcher;
41 | }
42 |
43 | /**
44 | * @param RequestFactory $factory
45 | */
46 | public function overwriteRequestFactory(RequestFactory $factory)
47 | {
48 | $this->factory = $factory;
49 | }
50 |
51 | /**
52 | * @return Request
53 | */
54 | protected function createRequestFromFactory()
55 | {
56 | $dispatcher = $this->dispatcher;
57 | $isInvalidFactory = (!($this->factory instanceof RequestFactory));
58 | $isValidDispatcher = ($dispatcher instanceof DispatcherInterface);
59 |
60 | if ($isInvalidFactory) {
61 | $this->factory = new RequestFactory();
62 | }
63 |
64 | if ($isValidDispatcher) {
65 | $this->factory->overwriteDispatcher($dispatcher);
66 | }
67 |
68 | $factory = $this->factory;
69 |
70 | return $factory->create();
71 | }
72 | }
73 |
--------------------------------------------------------------------------------
/source/Dispatcher/Dispatcher.php:
--------------------------------------------------------------------------------
1 |
4 | * @since 2015-12-09
5 | */
6 |
7 | namespace Net\Bazzline\Component\Curl\Dispatcher;
8 |
9 | use Net\Bazzline\Component\Curl\Response\Response;
10 |
11 | class Dispatcher implements DispatcherInterface
12 | {
13 | /** @var array */
14 | private $headerLines;
15 |
16 | /**
17 | * @param string $url
18 | * @param array $options
19 | * @return Response
20 | */
21 | public function dispatch($url, array $options = [])
22 | {
23 | $this->reset();
24 | $handler = $this->getHandler($url);
25 | $handler = $this->setOptions($handler, $options);
26 | $response = $this->execute($handler);
27 |
28 | return $response;
29 | }
30 |
31 | /**
32 | * @param resource $handler
33 | * @return Response
34 | */
35 | protected function execute($handler)
36 | {
37 | $content = curl_exec($handler);
38 | $contentType = curl_getinfo($handler, CURLINFO_CONTENT_TYPE);
39 | //@see http://stackoverflow.com/a/10667879
40 | $error = curl_error($handler);
41 | $errorCode = curl_errno($handler);
42 | $statusCode = curl_getinfo($handler, CURLINFO_HTTP_CODE);
43 | //@todo investigate if needed http://www.ivangabriele.com/php-how-to-use-4-methods-delete-get-post-put-in-a-restful-api-client-using-curl/
44 | //@todo how to handle response code 100 - other header? - http://stackoverflow.com/a/23939785
45 | curl_close($handler);
46 |
47 | return new Response($content, $contentType, $error, $errorCode, $this->headerLines, $statusCode);
48 | }
49 |
50 | /**
51 | * @param string $url
52 | * @return resource
53 | */
54 | protected function getHandler($url)
55 | {
56 | $handler = curl_init($url);
57 |
58 | return $handler;
59 | }
60 |
61 | /**
62 | * @param resource $handler
63 | * @param array $options
64 | * @return resource
65 | */
66 | protected function setOptions($handler, array $options)
67 | {
68 | $options[CURLINFO_HEADER_OUT] = 1;
69 | $options[CURLOPT_HEADERFUNCTION] = [
70 | $this,
71 | 'processHeadLine'
72 | ];
73 | $options[CURLOPT_RETURNTRANSFER] = true;
74 |
75 | curl_setopt_array($handler, $options);
76 |
77 | return $handler;
78 | }
79 |
80 |
81 |
82 | /**
83 | * @param resource $handler
84 | * @param string $string
85 | * @return int
86 | */
87 | private function processHeadLine($handler, $string)
88 | {
89 | $delimiter = ':';
90 | $exploded = explode($delimiter, trim($string));
91 | $isValid = (count($exploded) === 2);
92 |
93 | if ($isValid) {
94 | $prefix = array_shift($exploded);
95 | $this->headerLines[$prefix] = implode($delimiter, $exploded); //needed because of lines like "Date: Thu, 17 Dec 2015 16:47:42 GMT"
96 | }
97 |
98 | return strlen($string);
99 | }
100 |
101 | private function reset()
102 | {
103 | $this->headerLines = [];
104 | }
105 | }
106 |
--------------------------------------------------------------------------------
/source/Dispatcher/DispatcherInterface.php:
--------------------------------------------------------------------------------
1 |
4 | * @since: 2015-12-14
5 | */
6 |
7 | namespace Net\Bazzline\Component\Curl\Dispatcher;
8 |
9 | use Net\Bazzline\Component\Curl\Response\Response;
10 |
11 | interface DispatcherInterface
12 | {
13 | /**
14 | * @param string $url
15 | * @param array $options
16 | * @return Response
17 | */
18 | public function dispatch($url, array $options = []);
19 | }
20 |
--------------------------------------------------------------------------------
/source/Dispatcher/LoggingDispatcher.php:
--------------------------------------------------------------------------------
1 |
4 | * @since 2015-12-21
5 | */
6 |
7 | namespace Net\Bazzline\Component\Curl\Dispatcher;
8 |
9 | use Net\Bazzline\Component\Curl\Response\Response;
10 |
11 | class LoggingDispatcher extends Dispatcher
12 | {
13 | /**
14 | * @param string $url
15 | * @param array $options
16 | * @return Response
17 | */
18 | public function dispatch($url, array $options = [])
19 | {
20 | $this->log($url, $options);
21 |
22 | return parent::dispatch($url, $options);
23 | }
24 |
25 | /**
26 | * @param $url
27 | * @param array $options
28 | */
29 | protected function log($url, array $options)
30 | {
31 | echo 'url: ' . $url . PHP_EOL;
32 | echo 'options: ' . PHP_EOL;
33 | echo var_export($options, true) . PHP_EOL;
34 | }
35 | }
36 |
--------------------------------------------------------------------------------
/source/FactoryInterface.php:
--------------------------------------------------------------------------------
1 | prefix() . ': ' . $this->suffix();
13 | }
14 |
15 | /**
16 | * @return string
17 | */
18 | abstract protected function prefix();
19 |
20 | /**
21 | * @return string
22 | */
23 | abstract protected function suffix();
24 | }
25 |
--------------------------------------------------------------------------------
/source/HeaderLine/AcceptEncoding.php:
--------------------------------------------------------------------------------
1 |
4 | * @since: 2016-09-19
5 | */
6 | namespace Net\Bazzline\Component\Curl\HeaderLine;
7 |
8 | class AcceptEncoding extends AbstractHeaderLine
9 | {
10 | /** @var string */
11 | private $prefix;
12 |
13 | /** @var string */
14 | private $suffix;
15 |
16 | /**
17 | * AcceptEncoding constructor.
18 | *
19 | * @param array|string[] $encodings - e.g. ['gzip', 'deflate']
20 | */
21 | public function __construct(array $encodings)
22 | {
23 | $this->prefix = 'Accept-Encoding';
24 | $this->suffix = implode($encodings);
25 | }
26 |
27 | /**
28 | * @return string
29 | */
30 | protected function prefix()
31 | {
32 | return $this->prefix;
33 | }
34 |
35 | /**
36 | * @return string
37 | */
38 | protected function suffix()
39 | {
40 | return $this->suffix;
41 | }
42 | }
43 |
--------------------------------------------------------------------------------
/source/HeaderLine/AcceptLanguage.php:
--------------------------------------------------------------------------------
1 |
4 | * @since: 2016-09-19
5 | */
6 | namespace Net\Bazzline\Component\Curl\HeaderLine;
7 |
8 | class AcceptLanguage extends AbstractHeaderLine
9 | {
10 | /** @var string */
11 | private $prefix;
12 |
13 | /** @var string */
14 | private $suffix;
15 |
16 | /**
17 | * AcceptLanguage constructor.
18 | *
19 | * @param string $content - compress, gzip | * | compress;q=0.5, gzip;q=1.0 | gzip;q=1.0, identity; q=0.5, *;q=0
20 | */
21 | public function __construct($content)
22 | {
23 | $this->prefix = 'Accept-Encoding';
24 | $this->suffix = $content;
25 | }
26 |
27 | /**
28 | * @return string
29 | */
30 | protected function prefix()
31 | {
32 | return $this->prefix;
33 | }
34 |
35 | /**
36 | * @return string
37 | */
38 | protected function suffix()
39 | {
40 | return $this->suffix;
41 | }
42 | }
43 |
--------------------------------------------------------------------------------
/source/HeaderLine/ContentTypeIsUtf8Form.php:
--------------------------------------------------------------------------------
1 |
4 | * @since: 2016-09-19
5 | */
6 | namespace Net\Bazzline\Component\Curl\HeaderLine;
7 |
8 | class Custom extends AbstractHeaderLine
9 | {
10 | /** @var string */
11 | private $prefix;
12 |
13 | /** @var string */
14 | private $suffix;
15 |
16 | /**
17 | * Custom constructor.
18 | *
19 | * @param string $identifier - e.g. My-Header-Line - "X-" will be prefixed automatically
20 | * @param string $value - e.g. bazzline
21 | */
22 | public function __construct($identifier, $value)
23 | {
24 | $this->prefix = 'X-' . $identifier;
25 | $this->suffix = $value;
26 | }
27 |
28 | /**
29 | * @return string
30 | */
31 | protected function prefix()
32 | {
33 | return $this->prefix;
34 | }
35 |
36 | /**
37 | * @return string
38 | */
39 | protected function suffix()
40 | {
41 | return $this->suffix;
42 | }
43 | }
44 |
--------------------------------------------------------------------------------
/source/HeaderLine/HeaderLineInterface.php:
--------------------------------------------------------------------------------
1 |
4 | * @since 2015-12-08
5 | */
6 | namespace Net\Bazzline\Component\Curl\HeaderLine;
7 |
8 | interface HeaderLineInterface
9 | {
10 | /**
11 | * @return string
12 | */
13 | public function line();
14 | }
15 |
--------------------------------------------------------------------------------
/source/Option/AbstractAuthentication.php:
--------------------------------------------------------------------------------
1 | valueForThisOption = $valueForThisOption;
16 | }
17 |
18 | /**
19 | * @return array
20 | */
21 | public function value()
22 | {
23 | return $this->valueForThisOption;
24 | }
25 | }
--------------------------------------------------------------------------------
/source/Option/AbstractSetOptionClosureValue.php:
--------------------------------------------------------------------------------
1 | valueForThisOption = $valueForThisOption;
18 | }
19 |
20 | /**
21 | * @return Closure
22 | */
23 | public function value()
24 | {
25 | return $this->valueForThisOption;
26 | }
27 | }
--------------------------------------------------------------------------------
/source/Option/AbstractSetOptionIntValue.php:
--------------------------------------------------------------------------------
1 | valueForThisOption = $valueForThisOption;
16 | }
17 |
18 | /**
19 | * @return int
20 | */
21 | public function value()
22 | {
23 | return $this->valueForThisOption;
24 | }
25 | }
--------------------------------------------------------------------------------
/source/Option/AbstractSetOptionMixedValue.php:
--------------------------------------------------------------------------------
1 | valueForThisOption = $valueForThisOption;
16 | }
17 |
18 | /**
19 | * @return mixed
20 | */
21 | public function value()
22 | {
23 | return $this->valueForThisOption;
24 | }
25 | }
--------------------------------------------------------------------------------
/source/Option/AbstractSetOptionStreamValue.php:
--------------------------------------------------------------------------------
1 | valueForThisOption = $valueForThisOption;
16 | }
17 |
18 | /**
19 | * @return resource
20 | */
21 | public function value()
22 | {
23 | return $this->valueForThisOption;
24 | }
25 | }
--------------------------------------------------------------------------------
/source/Option/AbstractSetOptionStringValue.php:
--------------------------------------------------------------------------------
1 | valueForThisOption = $valueForThisOption;
16 | }
17 |
18 | /**
19 | * @return string
20 | */
21 | public function value()
22 | {
23 | return $this->valueForThisOption;
24 | }
25 | }
--------------------------------------------------------------------------------
/source/Option/AbstractSetOptionToFalse.php:
--------------------------------------------------------------------------------
1 | password = $password;
22 | $this->username = $username;
23 | }
24 |
25 | /**
26 | * @return int
27 | */
28 | public function identifier()
29 | {
30 | return CURLOPT_USERPWD;
31 | }
32 |
33 | /**
34 | * @return mixed
35 | */
36 | public function value()
37 | {
38 | return $this->username . ':' . $this->password;
39 | }
40 | }
--------------------------------------------------------------------------------
/source/Option/Authorization/EnableNetrc.php:
--------------------------------------------------------------------------------
1 |
4 | * @since 2015-12-08
5 | */
6 | namespace Net\Bazzline\Component\Curl\Option;
7 |
8 | interface OptionInterface
9 | {
10 | /**
11 | * @return int
12 | */
13 | public function identifier();
14 |
15 | /**
16 | * @return mixed
17 | */
18 | public function value();
19 | }
--------------------------------------------------------------------------------
/source/Option/Security/DisableSslVerifyHost.php:
--------------------------------------------------------------------------------
1 | key = $key;
20 | $this->value = $value;
21 | }
22 |
23 | /**
24 | * @return int
25 | */
26 | public function identifier()
27 | {
28 | return $this->key;
29 | }
30 |
31 | /**
32 | * @return mixed
33 | */
34 | public function value()
35 | {
36 | return $this->value;
37 | }
38 | }
--------------------------------------------------------------------------------
/source/Option/Transfer/DisableDnsUseGlobalCache.php:
--------------------------------------------------------------------------------
1 |
4 | * @since: 2015-12-09
5 | */
6 |
7 | namespace Net\Bazzline\Component\Curl\Request;
8 |
9 | use Net\Bazzline\Component\Curl\Dispatcher\DispatcherInterface;
10 | use Net\Bazzline\Component\Curl\HeaderLine\HeaderLineInterface;
11 | use Net\Bazzline\Component\Curl\Option\OptionInterface;
12 | use Net\Bazzline\Component\Curl\Response\Response;
13 | use Net\Bazzline\Component\Toolbox\HashMap\Merge;
14 |
15 | class Request
16 | {
17 | //@see: http://developer.sugarcrm.com/2013/08/30/doing-put-and-delete-with-curl-in-php/
18 | const HTTP_METHOD_DELETE = 'DELETE';
19 | const HTTP_METHOD_GET = 'GET';
20 | const HTTP_METHOD_PATCH = 'PATCH';
21 | const HTTP_METHOD_POST = 'POST';
22 | const HTTP_METHOD_PUT = 'PUT';
23 |
24 | /** @var array */
25 | private $defaultHeaderLines = [];
26 |
27 | /** @var array */
28 | private $defaultOptions = [];
29 |
30 | /** @var DispatcherInterface */
31 | private $dispatcher;
32 |
33 | /** @var array */
34 | private $headerLines = [];
35 |
36 | /** @var Merge */
37 | private $merge;
38 |
39 | /** @var array */
40 | private $options = [];
41 |
42 | /**
43 | * @param DispatcherInterface $dispatcher
44 | * @param Merge $merge
45 | * @param array $defaultHeaderLines
46 | * =>
47 | * @param array $defaultOptions
48 | * either:
49 | * =>
50 | * or:
51 | * =>
52 | */
53 | public function __construct(DispatcherInterface $dispatcher, Merge $merge, array $defaultHeaderLines = [], array $defaultOptions = [])
54 | {
55 | $this->defaultHeaderLines = $defaultHeaderLines;
56 | $this->defaultOptions = $defaultOptions;
57 | $this->dispatcher = $dispatcher;
58 | $this->merge = $merge;
59 | }
60 |
61 | /**
62 | * @return Request
63 | */
64 | public function __clone()
65 | {
66 | return new self(
67 | $this->dispatcher,
68 | $this->merge,
69 | $this->defaultHeaderLines,
70 | $this->defaultOptions
71 | );
72 | }
73 |
74 | /**
75 | * @param HeaderLineInterface $line
76 | */
77 | public function addHeaderLine(HeaderLineInterface $line)
78 | {
79 | $this->headerLines[] = $line->line();
80 | }
81 |
82 | /**
83 | * @param OptionInterface $option
84 | */
85 | public function addOption(OptionInterface $option)
86 | {
87 | $this->options[$option->identifier()] = $option->value();
88 | }
89 |
90 | /**
91 | * @param string $line - CURLOPT_* - see: http://php.net/manual/en/function.curl-setopt.php
92 | */
93 | public function addRawHeaderLine($line)
94 | {
95 | $this->headerLines[] = $line;
96 | }
97 |
98 | /**
99 | * @param string $key - CURLOPT_* - see: http://php.net/manual/en/function.curl-setopt.php
100 | * @param mixed $value
101 | */
102 | public function addRawOption($key, $value)
103 | {
104 | $this->options[$key] = $value;
105 | }
106 |
107 | /**
108 | * @param string $url
109 | * @param array $parameters
110 | * @return Response
111 | */
112 | public function get($url, array $parameters = [])
113 | {
114 | return $this->execute(
115 | $url,
116 | self::HTTP_METHOD_GET,
117 | $parameters,
118 | []
119 | );
120 | }
121 |
122 | /**
123 | * @param string $url
124 | * @param array $parameters
125 | * @param null|string|array $data
126 | * @return Response
127 | */
128 | public function post($url, array $parameters = [], $data = null)
129 | {
130 | return $this->execute(
131 | $url,
132 | self::HTTP_METHOD_POST,
133 | $parameters,
134 | $data
135 | );
136 | }
137 |
138 | /**
139 | * @param string $url
140 | * @param array $parameters
141 | * @param null|string|array $data
142 | * @return Response
143 | */
144 | public function put($url, array $parameters = [], $data = null)
145 | {
146 | return $this->execute(
147 | $url,
148 | self::HTTP_METHOD_PUT,
149 | $parameters,
150 | $data
151 | );
152 | }
153 |
154 | /**
155 | * @param string $url
156 | * @param array $parameters
157 | * @param null|string|array $data
158 | * @return Response
159 | */
160 | public function patch($url, array $parameters = [], $data = null)
161 | {
162 | return $this->execute(
163 | $url,
164 | self::HTTP_METHOD_PATCH,
165 | $parameters,
166 | $data
167 | );
168 | }
169 |
170 | /**
171 | * @param string $url
172 | * @param array $parameters
173 | * @param null|string|array $data
174 | * @return Response
175 | */
176 | public function delete($url, array $parameters = [], $data = null)
177 | {
178 | return $this->execute(
179 | $url,
180 | self::HTTP_METHOD_DELETE,
181 | $parameters,
182 | $data
183 | );
184 | }
185 |
186 | /**
187 | * @see: https://de.wikipedia.org/wiki/Representational_State_Transfer
188 | public function head($url)
189 | {
190 | }
191 | public function options($url)
192 | {
193 | }
194 | public function trace($url)
195 | {
196 | }
197 | */
198 |
199 | /**
200 | * @param bool|false $alsoTheDefaults
201 | */
202 | public function reset($alsoTheDefaults = false)
203 | {
204 | $this->headerLines = [];
205 | $this->options = [];
206 |
207 | if ($alsoTheDefaults) {
208 | $this->defaultHeaderLines = [];
209 | $this->defaultOptions = [];
210 | }
211 | }
212 |
213 | /**
214 | * @param array $options
215 | * @param mixed $data
216 | * @return array
217 | */
218 | private function addDataToTheOptionsIfDataIsValid(array $options, $data)
219 | {
220 | $isDataProvided = (!is_null($data));
221 |
222 | if ($isDataProvided) {
223 | $dataIsNotFromTypeScalar = (!is_scalar($data));
224 |
225 | if ($dataIsNotFromTypeScalar) {
226 | $data = http_build_query($data);
227 | }
228 |
229 | $dataStringContainsContent = (strlen($data) > 0);
230 |
231 | if ($dataStringContainsContent) {
232 | $options[CURLOPT_POSTFIELDS] = $data; //@see: http://www.lornajane.net/posts/2009/putting-data-fields-with-php-curl
233 | }
234 | }
235 |
236 | return $options;
237 | }
238 |
239 | /**
240 | * @param array $parameters
241 | * @param string $url
242 | * @return string
243 | */
244 | private function addParametersToTheUrlIfParametersAreProvided(array $parameters, $url)
245 | {
246 | $areParametersProvided = (!empty($parameters));
247 |
248 | if ($areParametersProvided) {
249 | $parametersAsString = http_build_query($parameters);
250 | $isParameterStringValid = (strlen($parametersAsString) > 0);
251 |
252 | if ($isParameterStringValid) {
253 | $urlWithParameters = $url . '?' . http_build_query($parameters);
254 | } else {
255 | $urlWithParameters = $url;
256 | }
257 | } else {
258 | $urlWithParameters = $url;
259 | }
260 |
261 | return $urlWithParameters;
262 | }
263 |
264 | /**
265 | * @param string $url
266 | * @param string $method
267 | * @param null|array $parameters
268 | * @param null|string|array $data
269 | * @return Response
270 | */
271 | private function execute($url, $method, array $parameters = [], $data = null)
272 | {
273 | //begin of dependencies
274 | $dispatcher = $this->dispatcher;
275 | $merge = $this->merge;
276 | $headerLines = $merge($this->headerLines, $this->defaultHeaderLines);
277 | $options = $merge($this->options, $this->defaultOptions);
278 | $headerLines[] = 'X-HTTP-Method-Override: ' . $method; //@see: http://tr.php.net/curl_setopt#109634
279 | //end of dependencies
280 |
281 | //begin of business logic
282 | $options[CURLOPT_CUSTOMREQUEST] = $method; //@see: http://tr.php.net/curl_setopt#109634
283 | $options[CURLOPT_HTTPHEADER] = $headerLines;
284 | //@todo what about binary transfer?
285 |
286 | $options = $this->addDataToTheOptionsIfDataIsValid($options, $data);
287 | $urlWithParameters = $this->addParametersToTheUrlIfParametersAreProvided($parameters, $url);
288 | $response = $dispatcher->dispatch($urlWithParameters, $options);
289 | //end of business logic
290 |
291 | return $response;
292 | }
293 | }
294 |
--------------------------------------------------------------------------------
/source/Request/RequestFactory.php:
--------------------------------------------------------------------------------
1 | createDefaultHeaderLines(
25 | $this->getDefaultRawHeaderLine(),
26 | $this->getDefaultHeaderLines()
27 | );
28 |
29 | $defaultOptions = $this->createDefaultOptions(
30 | $this->getDefaultRawOptions(),
31 | $this->getDefaultOptions()
32 | );
33 |
34 | $request = new Request(
35 | $this->getDispatcher(),
36 | new Merge(),
37 | $defaultHeaderLines,
38 | $defaultOptions
39 | );
40 |
41 | return $request;
42 | }
43 |
44 | /**
45 | * @param DispatcherInterface $dispatcher
46 | */
47 | public function overwriteDispatcher(DispatcherInterface $dispatcher)
48 | {
49 | $this->dispatcher = $dispatcher;
50 | }
51 |
52 | /**
53 | * @return DispatcherInterface
54 | */
55 | protected function getDispatcher()
56 | {
57 | $createDispatcher = !($this->dispatcher instanceof DispatcherInterface);
58 |
59 | if ($createDispatcher) {
60 | $this->dispatcher = $this->getNewDispatcher();
61 | }
62 |
63 | return $this->dispatcher;
64 | }
65 |
66 | /**
67 | * @return DispatcherInterface
68 | */
69 | protected function getNewDispatcher()
70 | {
71 | return new Dispatcher();
72 | }
73 |
74 | /**
75 | * @return array|HeaderLineInterface[]
76 | */
77 | protected function getDefaultHeaderLines()
78 | {
79 | return [];
80 | }
81 |
82 | /**
83 | * @return array
84 | */
85 | protected function getDefaultRawHeaderLine()
86 | {
87 | return [];
88 | }
89 |
90 | /**
91 | * @return array|OptionInterface[]
92 | */
93 | protected function getDefaultOptions()
94 | {
95 | return [
96 | new SetTimeOutInSeconds(10)
97 | ];
98 | }
99 |
100 | /**
101 | * @return array
102 | */
103 | protected function getDefaultRawOptions()
104 | {
105 | return [
106 | CURLOPT_AUTOREFERER => true,
107 | CURLOPT_CONNECTTIMEOUT => 5,
108 | CURLOPT_FOLLOWLOCATION => true,
109 | CURLOPT_MAXREDIRS => 10,
110 | CURLOPT_USERAGENT => 'net/bazzline curl component for php'
111 | ];
112 | }
113 |
114 | /**
115 | * @param array $rawHeaderLines
116 | * @param array|HeaderLineInterface[] $headerLines
117 | * @return array
118 | */
119 | private function createDefaultHeaderLines(array $rawHeaderLines, array $headerLines)
120 | {
121 | $defaultHeaderLines = $rawHeaderLines;
122 |
123 | foreach ($headerLines as $headerLine) {
124 | $defaultHeaderLines[] = $headerLine->line();
125 | }
126 |
127 | return $defaultHeaderLines;
128 | }
129 |
130 | /**
131 | * @param array $rawOptions
132 | * @param array|OptionInterface[] $options
133 | * @return array
134 | */
135 | private function createDefaultOptions(array $rawOptions, array $options)
136 | {
137 | $defaultOptions = $rawOptions;
138 |
139 | foreach ($options as $option) {
140 | $defaultOptions[$option->identifier()] = $option->value();
141 | }
142 |
143 | return $defaultOptions;
144 | }
145 | }
146 |
--------------------------------------------------------------------------------
/source/Response/Response.php:
--------------------------------------------------------------------------------
1 |
4 | * @since: 2015-12-09
5 | */
6 |
7 | namespace Net\Bazzline\Component\Curl\Response;
8 |
9 | use InvalidArgumentException;
10 |
11 | class Response
12 | {
13 | const ARRAY_KEY_CONTENT = 'content';
14 | const ARRAY_KEY_CONTENT_TYPE = 'content_type';
15 | const ARRAY_KEY_ERROR = 'error';
16 | const ARRAY_KEY_ERROR_CODE = 'error_code';
17 | const ARRAY_KEY_STATUS_CODE = 'status_code';
18 |
19 | /** @var null|mixed */
20 | private $content;
21 |
22 | /** @var null|string */
23 | private $contentType;
24 |
25 | /** @var null|string */
26 | private $error;
27 |
28 | /** @var null|int */
29 | private $errorCode;
30 |
31 | /** @var array */
32 | private $headerLines;
33 |
34 | /** @var null|int */
35 | private $statusCode;
36 |
37 | /**
38 | * @param mixed $content
39 | * @param string $contentType
40 | * @param string $error
41 | * @param int $errorCode
42 | * @param array $headerLines
43 | * @param int $statusCode
44 | */
45 | public function __construct($content, $contentType, $error, $errorCode, array $headerLines, $statusCode)
46 | {
47 | $this->content = $content;
48 | $this->contentType = $contentType;
49 | $this->error = $error;
50 | $this->errorCode = $errorCode;
51 | $this->headerLines = $headerLines;
52 | $this->statusCode = $statusCode;
53 | }
54 |
55 | /**
56 | * @return null|mixed
57 | */
58 | public function content()
59 | {
60 | return $this->content;
61 | }
62 |
63 | /**
64 | * @return null|string
65 | */
66 | public function contentType()
67 | {
68 | return $this->contentType;
69 | }
70 |
71 | /**
72 | * @param string $prefix
73 | * @return null|string
74 | * @throws InvalidArgumentException
75 | */
76 | public function headerLine($prefix)
77 | {
78 | $valueIsNotAvailable = (!isset($this->headerLines[$prefix]));
79 |
80 | if ($valueIsNotAvailable) {
81 | throw new InvalidArgumentException(
82 | 'no headline available for prefix: "' . $prefix . '"'
83 | );
84 | }
85 |
86 | return $this->headerLines[$prefix];
87 | }
88 |
89 | /**
90 | * @return array
91 | */
92 | public function headerLines()
93 | {
94 | return $this->headerLines;
95 | }
96 |
97 | /**
98 | * @return null|string
99 | */
100 | public function error()
101 | {
102 | return $this->error;
103 | }
104 |
105 | /**
106 | * @return null|int
107 | * @see: http://curl.haxx.se/libcurl/c/libcurl-errors.html
108 | */
109 | public function errorCode()
110 | {
111 | return $this->errorCode;
112 | }
113 |
114 | /**
115 | * @return null|int
116 | */
117 | public function statusCode()
118 | {
119 | return $this->statusCode;
120 | }
121 |
122 | /**
123 | * @return array
124 | */
125 | public function convertIntoAnArray()
126 | {
127 | return [
128 | self::ARRAY_KEY_CONTENT => $this->content,
129 | self::ARRAY_KEY_CONTENT_TYPE => $this->contentType,
130 | self::ARRAY_KEY_ERROR => $this->error,
131 | self::ARRAY_KEY_ERROR_CODE => $this->errorCode,
132 | self::ARRAY_KEY_STATUS_CODE => $this->statusCode
133 | ];
134 | }
135 | }
136 |
--------------------------------------------------------------------------------
/source/ResponseBehaviour/ConvertJsonToArrayBehaviour.php:
--------------------------------------------------------------------------------
1 |
4 | * @since 2015-12-09
5 | */
6 | namespace Net\Bazzline\Component\Curl\ResponseBehaviour;
7 |
8 | use Exception;
9 | use Net\Bazzline\Component\Curl\Response\Response;
10 |
11 | class ConvertJsonToArrayBehaviour implements ResponseBehaviourInterface
12 | {
13 | /**
14 | * Since the Response is immutable, each behaviour has to return a new
15 | * Response instance
16 | *
17 | * @param Response $response
18 | * @return Response
19 | * @throws Exception
20 | */
21 | public function behave(Response $response)
22 | {
23 | return new Response(
24 | json_decode($response->content(), true),
25 | $response->contentType(),
26 | $response->error(),
27 | $response->errorCode(),
28 | $response->headerLines(),
29 | $response->statusCode()
30 | );
31 | }
32 | }
33 |
--------------------------------------------------------------------------------
/source/ResponseBehaviour/ResponseBehaviourInterface.php:
--------------------------------------------------------------------------------
1 |
4 | * @since 2015-12-08
5 | */
6 | namespace Net\Bazzline\Component\Curl\ResponseBehaviour;
7 |
8 | use Exception;
9 | use Net\Bazzline\Component\Curl\Response\Response;
10 |
11 | interface ResponseBehaviourInterface
12 | {
13 | /**
14 | * Since the Response is immutable, each behaviour has to return a new
15 | * Response instance
16 | *
17 | * @param Response $response
18 | * @return Response
19 | * @throws Exception
20 | */
21 | public function behave(Response $response);
22 | }
23 |
--------------------------------------------------------------------------------
/source/ResponseBehaviour/ThrowRuntimeExceptionIfStatusCodeIsAboveTheLimitBehaviour.php:
--------------------------------------------------------------------------------
1 |
4 | * @since 2015-12-09
5 | */
6 | namespace Net\Bazzline\Component\Curl\ResponseBehaviour;
7 |
8 | use Exception;
9 | use Net\Bazzline\Component\Curl\Response\Response;
10 | use RuntimeException;
11 |
12 | class ThrowRuntimeExceptionIfStatusCodeIsAboveTheLimitBehaviour implements ResponseBehaviourInterface
13 | {
14 | /** @var int */
15 | private $statusCode;
16 |
17 | /**
18 | * @param int $firstStatusCodeThatIsOverTheLimit
19 | */
20 | public function __construct($firstStatusCodeThatIsOverTheLimit = 400)
21 | {
22 | $this->statusCode = (int) $firstStatusCodeThatIsOverTheLimit;
23 | }
24 |
25 | /**
26 | * Since the Response is immutable, each behaviour has to return a new
27 | * Response instance
28 | *
29 | * @param Response $response
30 | * @return Response
31 | * @throws Exception|RuntimeException
32 | */
33 | public function behave(Response $response)
34 | {
35 | $statusCodeIsToHigh = ($response->statusCode() > $this->statusCode);
36 |
37 | if ($statusCodeIsToHigh) {
38 | throw new RuntimeException(
39 | 'limit of status code exceeded. dumping response: ' .
40 | implode(', ', $response->convertIntoAnArray())
41 | );
42 | }
43 |
44 | return $response;
45 | }
46 | }
47 |
--------------------------------------------------------------------------------
/test/AbstractTestCase.php:
--------------------------------------------------------------------------------
1 |
4 | * @since: 2015-12-14
5 | */
6 |
7 | namespace Test\Net\Bazzline\Component\Curl;
8 |
9 | use Mockery;
10 | use Net\Bazzline\Component\Curl\Builder\Builder;
11 | use Net\Bazzline\Component\Curl\Dispatcher\DispatcherInterface;
12 | use Net\Bazzline\Component\Curl\Request\Request;
13 | use Net\Bazzline\Component\Curl\Response\Response;
14 | use Net\Bazzline\Component\Toolbox\HashMap\Merge;
15 | use PHPUnit_Framework_TestCase;
16 |
17 | abstract class AbstractTestCase extends PHPUnit_Framework_TestCase
18 | {
19 |
20 | /**
21 | * @param string $method
22 | * @param array $headerLines
23 | * @param array $options
24 | * @param null|mixed $data
25 | * @return array
26 | */
27 | protected function buildDispatcherOptions($method, array $headerLines = [], array $options = [], $data = null)
28 | {
29 | $isDataProvided = (!is_null($data));
30 | $headerLines[] = 'X-HTTP-Method-Override: ' . $method; //@see: http://tr.php.net/curl_setopt#109634
31 | $dispatcherOptions = $options;
32 |
33 | $dispatcherOptions[CURLOPT_CUSTOMREQUEST] = $method;
34 | $dispatcherOptions[CURLOPT_HTTPHEADER] = $headerLines;
35 |
36 | if ($isDataProvided) {
37 | $dispatcherOptions[CURLOPT_POSTFIELDS] = $data;
38 | }
39 |
40 | return $dispatcherOptions;
41 | }
42 |
43 | /**
44 | * @return Mockery\MockInterface|\Net\Bazzline\Component\Curl\ResponseBehaviour\ResponseBehaviourInterface'
45 | */
46 | protected function getMockOfTheBehaviour()
47 | {
48 | return Mockery::mock('Net\Bazzline\Component\Curl\ResponseBehaviour\ResponseBehaviourInterface');
49 | }
50 |
51 | /**
52 | * @return Mockery\MockInterface|DispatcherInterface
53 | */
54 | protected function getMockOfTheDispatcher()
55 | {
56 | return Mockery::mock('Net\Bazzline\Component\Curl\Dispatcher\DispatcherInterface');
57 | }
58 |
59 | /**
60 | * @param Request $request
61 | * @param array $defaultResponseBehaviours
62 | * @return Builder
63 | */
64 | protected function getNewBuilder(Request $request, array $defaultResponseBehaviours = [])
65 | {
66 | return new Builder($request, new Merge(), $defaultResponseBehaviours);
67 | }
68 |
69 | /**
70 | * @param DispatcherInterface $dispatcher
71 | * @param array $defaultHeaderLines
72 | * @param array $defaultOptions
73 | * @return Request
74 | */
75 | protected function getNewRequest(DispatcherInterface $dispatcher, array $defaultHeaderLines = [], array $defaultOptions = [])
76 | {
77 | return new Request($dispatcher, new Merge(), $defaultHeaderLines, $defaultOptions);
78 | }
79 |
80 | /**
81 | * @param mixed $content
82 | * @param string $contentType
83 | * @param string $error
84 | * @param int $errorCode
85 | * @param array $headLines
86 | * @param int $statusCode
87 | * @return Response
88 | */
89 | protected function getNewResponse($content = 'example content', $contentType = 'example content type', $error = '', $errorCode = 0, array $headLines = [], $statusCode = 200)
90 | {
91 | return new Response($content, $contentType, $error, $errorCode, $headLines, $statusCode);
92 | }
93 |
94 | /**
95 | * @return string
96 | */
97 | protected function getUrl()
98 | {
99 | return 'http://www.foo.bar';
100 | }
101 | }
102 |
--------------------------------------------------------------------------------
/test/Builder/BuilderTest.php:
--------------------------------------------------------------------------------
1 |
4 | * @since 2015-12-16
5 | */
6 | namespace Test\Net\Bazzline\Component\Curl\Builder;
7 |
8 | use Test\Net\Bazzline\Component\Curl\AbstractTestCase;
9 |
10 | class BuilderTest extends AbstractTestCase
11 | {
12 | public function testFetchTheResponse()
13 | {
14 | $dispatcher = $this->getMockOfTheDispatcher();
15 | $request = $this->getNewRequest($dispatcher);
16 | $builder = $this->getNewBuilder($request);
17 | $response = $this->getNewResponse();
18 |
19 | $dispatcher->shouldReceive('dispatch')
20 | ->with(
21 | $this->getUrl(),
22 | $this->buildDispatcherOptions('PUT')
23 | )
24 | ->andReturn($response)
25 | ->once();
26 |
27 | $builder->onTheUrl($this->getUrl());
28 | $builder->usePut();
29 |
30 | $builder->andFetchTheResponse();
31 | }
32 |
33 | public function testFetchTheResponseAsJson()
34 | {
35 | $dispatcher = $this->getMockOfTheDispatcher();
36 | $request = $this->getNewRequest($dispatcher);
37 | $builder = $this->getNewBuilder($request);
38 | $response = $this->getNewResponse();
39 |
40 | $dispatcher->shouldReceive('dispatch')
41 | ->with(
42 | $this->getUrl(),
43 | $this->buildDispatcherOptions(
44 | 'PUT',
45 | [
46 | 'Content-Type: application/json; charset=UTF-8'
47 | ],
48 | [],
49 | json_encode(null)
50 | )
51 | )
52 | ->andReturn($response)
53 | ->once();
54 |
55 | $builder->asJson();
56 | $builder->onTheUrl($this->getUrl());
57 | $builder->usePut();
58 |
59 | $builder->andFetchTheResponse();
60 | }
61 |
62 | public function testFetchTheResponseWithBehaviours()
63 | {
64 | $behaviour = $this->getMockOfTheBehaviour();
65 | $dispatcher = $this->getMockOfTheDispatcher();
66 | $request = $this->getNewRequest($dispatcher);
67 | $builder = $this->getNewBuilder($request);
68 | $response = $this->getNewResponse();
69 |
70 | $behaviour->shouldReceive('behave')
71 | ->with($response)
72 | ->andReturn($response)
73 | ->once();
74 |
75 | $dispatcher->shouldReceive('dispatch')
76 | ->with(
77 | $this->getUrl(),
78 | $this->buildDispatcherOptions('PUT')
79 | )
80 | ->andReturn($response)
81 | ->once();
82 |
83 | $builder->onTheUrl($this->getUrl());
84 | $builder->usePut();
85 | $builder->withTheResponseBehaviour($behaviour);
86 |
87 | $builder->andFetchTheResponse();
88 | }
89 | }
90 |
--------------------------------------------------------------------------------
/test/Request/RequestTest.php:
--------------------------------------------------------------------------------
1 |
4 | * @since: 2015-12-14
5 | */
6 |
7 | namespace Test\Net\Bazzline\Component\Curl\Request;
8 |
9 | use Net\Bazzline\Component\Curl\HeaderLine\ContentTypeIsUtf8Json;
10 | use Net\Bazzline\Component\Curl\Option\Behaviour\SetTimeOutInSeconds;
11 | use stdClass;
12 | use Test\Net\Bazzline\Component\Curl\AbstractTestCase;
13 |
14 | class RequestTest extends AbstractTestCase
15 | {
16 | /**
17 | * @return array
18 | */
19 | public function testCaseWithUrlParameters()
20 | {
21 | $url = $this->getUrl();
22 |
23 | return [
24 | 'with parameters' => [
25 | 'parameters' => [],
26 | 'url' => $url,
27 | 'expected_url' => $url
28 | ],
29 | 'with parameter parameter only' => [
30 | 'parameters' => [
31 | 'key'
32 | ],
33 | 'url' => $url,
34 | 'expected_url' => $url . '?0=key'
35 | ],
36 | 'with parameter key only' => [
37 | 'parameters' => [
38 | 'key' => null
39 | ],
40 | 'url' => $url,
41 | 'expected_url' => $url
42 | ],
43 | 'with one parameter' => [
44 | 'parameters' => [
45 | 'key' => 'value'
46 | ],
47 | 'url' => $url,
48 | 'expected_url' => $url . '?key=value'
49 | ],
50 | 'with two parameter' => [
51 | 'parameters' => [
52 | 'one' => 'value',
53 | 'two' => 'value'
54 | ],
55 | 'url' => $url,
56 | 'expected_url' => $url . '?one=value&two=value'
57 | ],
58 | 'with multiple parameter' => [
59 | 'parameters' => [
60 | 'one' => 'value',
61 | 'two' => 'value',
62 | 'three' => 'value'
63 | ],
64 | 'url' => $url,
65 | 'expected_url' => $url . '?one=value&two=value&three=value'
66 | ],
67 | 'with nested parameter' => [
68 | 'parameters' => [
69 | 'key' => [
70 | 'one',
71 | 'two',
72 | 'three'
73 | ]
74 | ],
75 | 'url' => $url,
76 | 'expected_url' => $url . '?key%5B0%5D=one&key%5B1%5D=two&key%5B2%5D=three'
77 | ]
78 | ];
79 | }
80 |
81 | /**
82 | * @return array
83 | */
84 | public function testCaseWithUrlParametersAndData()
85 | {
86 | $testCaseTemplates = $this->testCaseWithUrlParameters();
87 | $testCases = [];
88 | $object = new stdClass();
89 |
90 | $object->bar = 'foo';
91 | $object->foo = 'bar';
92 |
93 | foreach ($testCaseTemplates as $name => $template) {
94 | $testCases[$name . ' without data'] = [
95 | 'parameters' => $template['parameters'],
96 | 'data' => null,
97 | 'url' => $template['url'],
98 | 'expected_url' => $template['expected_url'],
99 | 'expected_data' => null
100 | ];
101 | $testCases[$name . ' with int as data'] = [
102 | 'parameters' => $template['parameters'],
103 | 'data' => 42,
104 | 'url' => $template['url'],
105 | 'expected_url' => $template['expected_url'],
106 | 'expected_data' => 42
107 | ];
108 | $testCases[$name . ' with string as data'] = [
109 | 'parameters' => $template['parameters'],
110 | 'data' => 'there is no foo without a bar',
111 | 'url' => $template['url'],
112 | 'expected_url' => $template['expected_url'],
113 | 'expected_data' => 'there is no foo without a bar'
114 | ];
115 | $testCases[$name . ' with array as data'] = [
116 | 'parameters' => $template['parameters'],
117 | 'data' => [
118 | 'there' => 'is',
119 | 'no' => 'foo',
120 | 'without' => 'a',
121 | 'bar'
122 | ],
123 | 'url' => $template['url'],
124 | 'expected_url' => $template['expected_url'],
125 | 'expected_data' => 'there=is&no=foo&without=a&0=bar'
126 | ];
127 | $testCases[$name . ' with object as data'] = [
128 | 'parameters' => $template['parameters'],
129 | 'data' => $object,
130 | 'url' => $template['url'],
131 | 'expected_url' => $template['expected_url'],
132 | 'expected_data' => 'bar=foo&foo=bar'
133 | ];
134 | }
135 |
136 | return $testCases;
137 | }
138 |
139 | public function testClone()
140 | {
141 | $dispatcher = $this->getMockOfTheDispatcher();
142 | $headerLines = [
143 | 'foo: bar'
144 | ];
145 | $options = [
146 | CURLOPT_AUTOREFERER => true
147 | ];
148 | $request = $this->getNewRequest($dispatcher, $headerLines, $options);
149 | $response = $this->getNewResponse();
150 |
151 | $dispatcher->shouldReceive('dispatch')
152 | ->with(
153 | $this->getUrl(),
154 | $this->buildDispatcherOptions('PUT', $headerLines, $options)
155 | )
156 | ->andReturn($response)
157 | ->once();
158 |
159 | $clonedRequest = clone $request;
160 |
161 | $clonedRequest->put($this->getUrl());
162 | }
163 |
164 | public function testAddHeaderLine()
165 | {
166 | $dispatcher = $this->getMockOfTheDispatcher();
167 | $headerLine = new ContentTypeIsUtf8Json();
168 | $request = $this->getNewRequest($dispatcher, [], []);
169 | $response = $this->getNewResponse();
170 |
171 | $request->addHeaderLine($headerLine);
172 |
173 | $dispatcher->shouldReceive('dispatch')
174 | ->with(
175 | $this->getUrl(),
176 | $this->buildDispatcherOptions(
177 | 'PUT',
178 | [
179 | $headerLine->line()
180 | ],
181 | []
182 | )
183 | )
184 | ->andReturn($response)
185 | ->once();
186 |
187 | $request->put($this->getUrl());
188 | }
189 |
190 | public function testAddOption()
191 | {
192 | $dispatcher = $this->getMockOfTheDispatcher();
193 | $option = new SetTimeOutInSeconds(__LINE__);
194 | $request = $this->getNewRequest($dispatcher, [], []);
195 | $response = $this->getNewResponse();
196 |
197 | $request->addOption($option);
198 |
199 | $dispatcher->shouldReceive('dispatch')
200 | ->with(
201 | $this->getUrl(),
202 | $this->buildDispatcherOptions(
203 | 'PUT',
204 | [],
205 | [
206 | $option->identifier() => $option->value()
207 | ]
208 | )
209 | )
210 | ->andReturn($response)
211 | ->once();
212 |
213 | $request->put($this->getUrl());
214 | }
215 |
216 | public function testAddRawHeaderLine()
217 | {
218 | $dispatcher = $this->getMockOfTheDispatcher();
219 | $headerLine = 'foo: bar';
220 | $request = $this->getNewRequest($dispatcher, [], []);
221 | $response = $this->getNewResponse();
222 |
223 | $request->addRawHeaderLine($headerLine);
224 |
225 | $dispatcher->shouldReceive('dispatch')
226 | ->with(
227 | $this->getUrl(),
228 | $this->buildDispatcherOptions(
229 | 'PUT',
230 | [
231 | $headerLine
232 | ],
233 | []
234 | )
235 | )
236 | ->andReturn($response)
237 | ->once();
238 |
239 | $request->put($this->getUrl());
240 | }
241 |
242 | public function testAddRawOption()
243 | {
244 | $dispatcher = $this->getMockOfTheDispatcher();
245 | $request = $this->getNewRequest($dispatcher, [], []);
246 | $response = $this->getNewResponse();
247 |
248 | $request->addRawOption('foo', 'bar');
249 |
250 | $dispatcher->shouldReceive('dispatch')
251 | ->with(
252 | $this->getUrl(),
253 | $this->buildDispatcherOptions(
254 | 'PUT',
255 | [],
256 | [
257 | 'foo' => 'bar'
258 | ]
259 | )
260 | )
261 | ->andReturn($response)
262 | ->once();
263 |
264 | $request->put($this->getUrl());
265 | }
266 |
267 |
268 |
269 | /**
270 | * @dataProvider testCaseWithUrlParameters
271 | * @param array $parameters
272 | * @param $url
273 | * @param $expectedUrl
274 | */
275 | public function testGet(array $parameters, $url, $expectedUrl)
276 | {
277 | $dispatcher = $this->getMockOfTheDispatcher();
278 | $request = $this->getNewRequest($dispatcher);
279 | $response = $this->getNewResponse();
280 |
281 | $dispatcher->shouldReceive('dispatch')
282 | ->with(
283 | $expectedUrl,
284 | $this->buildDispatcherOptions('GET')
285 | )
286 | ->andReturn($response)
287 | ->once();
288 |
289 | $request->get($url, $parameters);
290 | }
291 |
292 |
293 |
294 | /**
295 | * @dataProvider testCaseWithUrlParameters
296 | * @param array $parameters
297 | * @param $url
298 | * @param $expectedUrl
299 | */
300 | public function testDelete(array $parameters, $url, $expectedUrl)
301 | {
302 | $dispatcher = $this->getMockOfTheDispatcher();
303 | $request = $this->getNewRequest($dispatcher);
304 | $response = $this->getNewResponse();
305 |
306 | $dispatcher->shouldReceive('dispatch')
307 | ->with(
308 | $expectedUrl,
309 | $this->buildDispatcherOptions('DELETE')
310 | )
311 | ->andReturn($response)
312 | ->once();
313 |
314 | $request->delete($url, $parameters);
315 | }
316 |
317 |
318 |
319 | /**
320 | * @dataProvider testCaseWithUrlParametersAndData
321 | * @param array $parameters
322 | * @param mixed $data
323 | * @param string $url
324 | * @param string $expectedUrl
325 | * @param mixed $expectedData
326 | */
327 | public function testPatch(array $parameters, $data, $url, $expectedUrl, $expectedData)
328 | {
329 | $dispatcher = $this->getMockOfTheDispatcher();
330 | $request = $this->getNewRequest($dispatcher);
331 | $response = $this->getNewResponse();
332 |
333 | $dispatcher->shouldReceive('dispatch')
334 | ->with(
335 | $expectedUrl,
336 | $this->buildDispatcherOptions(
337 | 'PATCH',
338 | [],
339 | [],
340 | $expectedData
341 | )
342 | )
343 | ->andReturn($response)
344 | ->once();
345 |
346 | $request->patch($url, $parameters, $data);
347 | }
348 |
349 |
350 |
351 | /**
352 | * @dataProvider testCaseWithUrlParametersAndData
353 | * @param array $parameters
354 | * @param mixed $data
355 | * @param string $url
356 | * @param string $expectedUrl
357 | * @param mixed $expectedData
358 | */
359 | public function testPost(array $parameters, $data, $url, $expectedUrl, $expectedData)
360 | {
361 | $dispatcher = $this->getMockOfTheDispatcher();
362 | $request = $this->getNewRequest($dispatcher);
363 | $response = $this->getNewResponse();
364 |
365 | $dispatcher->shouldReceive('dispatch')
366 | ->with(
367 | $expectedUrl,
368 | $this->buildDispatcherOptions(
369 | 'POST',
370 | [],
371 | [],
372 | $expectedData
373 | )
374 | )
375 | ->andReturn($response)
376 | ->once();
377 |
378 | $request->post($url, $parameters, $data);
379 | }
380 |
381 |
382 |
383 | /**
384 | * @dataProvider testCaseWithUrlParametersAndData
385 | * @param array $parameters
386 | * @param mixed $data
387 | * @param string $url
388 | * @param string $expectedUrl
389 | * @param mixed $expectedData
390 | */
391 | public function testPut(array $parameters, $data, $url, $expectedUrl, $expectedData)
392 | {
393 | $dispatcher = $this->getMockOfTheDispatcher();
394 | $request = $this->getNewRequest($dispatcher);
395 | $response = $this->getNewResponse();
396 |
397 | $dispatcher->shouldReceive('dispatch')
398 | ->with(
399 | $expectedUrl,
400 | $this->buildDispatcherOptions(
401 | 'PUT',
402 | [],
403 | [],
404 | $expectedData
405 | )
406 | )
407 | ->andReturn($response)
408 | ->once();
409 |
410 | $request->put($url, $parameters, $data);
411 | }
412 |
413 | public function testRestWithoutResettingTheDefaults()
414 | {
415 | $dispatcher = $this->getMockOfTheDispatcher();
416 | $request = $this->getNewRequest($dispatcher, [], []);
417 | $response = $this->getNewResponse();
418 |
419 | $request->addRawOption('foo', 'bar');
420 | $request->reset();
421 |
422 | $dispatcher->shouldReceive('dispatch')
423 | ->with(
424 | $this->getUrl(),
425 | $this->buildDispatcherOptions('PUT')
426 | )
427 | ->andReturn($response)
428 | ->once();
429 |
430 | $request->put($this->getUrl());
431 | }
432 |
433 | public function testRestWithResettingTheDefaults()
434 | {
435 | $dispatcher = $this->getMockOfTheDispatcher();
436 | $request = $this->getNewRequest(
437 | $dispatcher,
438 | [
439 | 'foo' => 'bar'
440 | ],
441 | []
442 | );
443 | $response = $this->getNewResponse();
444 |
445 | $request->reset(true);
446 |
447 | $dispatcher->shouldReceive('dispatch')
448 | ->with(
449 | $this->getUrl(),
450 | $this->buildDispatcherOptions('PUT')
451 | )
452 | ->andReturn($response)
453 | ->once();
454 |
455 | $request->put($this->getUrl());
456 | }
457 | }
458 |
--------------------------------------------------------------------------------
/test/Response/ResponseTest.php:
--------------------------------------------------------------------------------
1 |
4 | * @since: 2015-12-14
5 | */
6 |
7 | namespace Test\Net\Bazzline\Component\Curl;
8 |
9 | class ResponseTest extends AbstractTestCase
10 | {
11 | public function testHeaderLineWithExistingPrefixes()
12 | {
13 | $content = 'the content';
14 | $contentType = 'the content type';
15 | $error = 'this is an error';
16 | $errorCode = __LINE__;
17 | $headerLines = [
18 | 'bar' => 'foo',
19 | 'foo' => 'bar'
20 | ];
21 | $statusCode = __LINE__;
22 |
23 | $response = $this->getNewResponse($content, $contentType, $error, $errorCode, $headerLines, $statusCode);
24 |
25 | foreach ($headerLines as $prefix => $suffix) {
26 | $this->assertEquals($suffix, $response->headerLine($prefix));
27 | }
28 | }
29 |
30 | /**
31 | * @expectedException \InvalidArgumentException
32 | * @expectedExceptionMessage no headline available for prefix: "foobar"
33 | */
34 | public function testHeaderLineWithNotExistingPrefixes()
35 | {
36 | $content = 'the content';
37 | $contentType = 'the content type';
38 | $error = 'this is an error';
39 | $errorCode = __LINE__;
40 | $headerLines = [];
41 | $statusCode = __LINE__;
42 |
43 | $response = $this->getNewResponse($content, $contentType, $error, $errorCode, $headerLines, $statusCode);
44 |
45 | $this->assertEquals(null, $response->headerLine('foobar'));
46 | }
47 |
48 | public function testAll()
49 | {
50 | $content = 'the content';
51 | $contentType = 'the content type';
52 | $error = 'this is an error';
53 | $errorCode = __LINE__;
54 | $headerLines = [];
55 | $statusCode = __LINE__;
56 |
57 | $response = $this->getNewResponse($content, $contentType, $error, $errorCode, $headerLines, $statusCode);
58 |
59 | $this->assertEquals($content, $response->content());
60 | $this->assertEquals($contentType, $response->contentType());
61 | $this->assertEquals($error, $response->error());
62 | $this->assertEquals($errorCode, $response->errorCode());
63 | $this->assertEquals($headerLines, $response->headerLines());
64 | $this->assertEquals($statusCode, $response->statusCode());
65 | }
66 | }
67 |
--------------------------------------------------------------------------------
/test/ResponseBehaviour/ConvertJsonToArrayBehaviourTest.php:
--------------------------------------------------------------------------------
1 |
4 | * @since: 2015-12-16
5 | */
6 |
7 | namespace Test\Net\Bazzline\Component\Curl\ResponseBehaviour;
8 |
9 | use Net\Bazzline\Component\Curl\ResponseBehaviour\ConvertJsonToArrayBehaviour;
10 | use Test\Net\Bazzline\Component\Curl\AbstractTestCase;
11 |
12 | class ConvertJsonToArrayBehaviourTest extends AbstractTestCase
13 | {
14 | public function testBehaviour()
15 | {
16 | $behaviour = new ConvertJsonToArrayBehaviour();
17 | $response = $this->getNewResponse();
18 |
19 | $behavedResponse = $behaviour->behave($response);
20 | $expectedContent = json_decode($response->content(), true);
21 |
22 | $this->assertEquals($expectedContent, $behavedResponse->content());
23 | }
24 | }
25 |
--------------------------------------------------------------------------------
/test/ResponseBehaviour/ThrowRuntimeExceptionIfStatusCodeIsAboveTheLimitBehaviourTest.php:
--------------------------------------------------------------------------------
1 |
4 | * @since: 2015-12-16
5 | */
6 |
7 | namespace Test\Net\Bazzline\Component\Curl\ResponseBehaviour;
8 |
9 | use Net\Bazzline\Component\Curl\Response\Response;
10 | use Net\Bazzline\Component\Curl\ResponseBehaviour\ThrowRuntimeExceptionIfStatusCodeIsAboveTheLimitBehaviour;
11 | use RuntimeException;
12 | use Test\Net\Bazzline\Component\Curl\AbstractTestCase;
13 |
14 | class ThrowRuntimeExceptionIfStatusCodeIsAboveTheLimitBehaviourTest extends AbstractTestCase
15 | {
16 | /**
17 | * @return array
18 | */
19 | public function testCases()
20 | {
21 | return [
22 | 'status code below limit' => [
23 | 0,
24 | 1,
25 | $this->createResponse(0),
26 | false
27 | ],
28 | 'status code on the limit' => [
29 | 1,
30 | 1,
31 | $this->createResponse(1),
32 | true
33 | ],
34 | 'status code over the limit' => [
35 | 2,
36 | 1,
37 | $this->createResponse(2),
38 | true
39 | ]
40 | ];
41 | }
42 |
43 | /**
44 | * @dataProvider testCases
45 | * @param int $statusCode
46 | * @param int $firstStatusCodeThatIsOverTheLimit
47 | * @param Response $response
48 | * @param bool $exceptionExpected
49 | */
50 | public function testBehaviour($statusCode, $firstStatusCodeThatIsOverTheLimit, Response $response, $exceptionExpected)
51 | {
52 | $behaviour = new ThrowRuntimeExceptionIfStatusCodeIsAboveTheLimitBehaviour($firstStatusCodeThatIsOverTheLimit);
53 |
54 | try {
55 | $behaviour->behave($response);
56 | } catch (RuntimeException $exception) {
57 | if ($exceptionExpected) {
58 | $expectedExceptionMessage = 'limit of status code exceeded. dumping response: ' . implode(', ', $response->convertIntoAnArray());
59 | $this->assertEquals($exception->getMessage(), $expectedExceptionMessage);
60 | } else {
61 | $this->fail('exception not expected: ' . $exception->getMessage());
62 | }
63 | }
64 | }
65 |
66 | /**
67 | * @param int $statusCode
68 | * @return Response
69 | */
70 | private function createResponse($statusCode)
71 | {
72 | return $this->getNewResponse('example content', 'example content type', '', 0, [], $statusCode);
73 | }
74 | }
75 |
--------------------------------------------------------------------------------
/test/bootstrap.php:
--------------------------------------------------------------------------------
1 |