├── .gitignore
├── .travis.yml
├── CHANGELOG.md
├── INSTALLATION.md
├── LICENSE
├── README.md
├── bin
└── build.php
├── composer.json
├── phpcs.xml
├── phpunit.xml
├── src
└── Interfax
│ ├── Client.php
│ ├── Document.php
│ ├── Documents.php
│ ├── Exception
│ └── RequestException.php
│ ├── File.php
│ ├── GenericFactory.php
│ ├── Image.php
│ ├── Inbound.php
│ ├── Inbound
│ └── Fax.php
│ ├── Outbound.php
│ ├── Outbound
│ ├── Delivery.php
│ └── Fax.php
│ └── Resource.php
└── tests
└── Interfax
├── BaseTest.php
├── ClientTest.php
├── DocumentTest.php
├── DocumentsTest.php
├── FileTest.php
├── ImageTest.php
├── Inbound
└── FaxTest.php
├── InboundTest.php
├── Outbound
├── DeliveryTest.php
└── FaxTest.php
├── OutboundTest.php
└── test.pdf
/.gitignore:
--------------------------------------------------------------------------------
1 | .DS_Store
2 | /build/
3 | /vendor/
4 | .idea
5 | composer.lock
6 |
7 |
--------------------------------------------------------------------------------
/.travis.yml:
--------------------------------------------------------------------------------
1 | language: php
2 | php:
3 | - 7.3
4 | - 7.4
5 | - 8.0
6 | - 8.1
7 | install:
8 | - composer install --no-interaction
9 | - php -v
10 | - phpunit --version
11 | - echo "$TRAVIS_TAG"
12 | - echo "$TRAVIS_COMMIT"
13 | - echo "$TRAVIS_BUILD_NUMBER"
14 | before_deploy:
15 | - php ./bin/build.php
16 | - export RELEASE_PKG_FILE=$(ls build/*zip)
17 |
18 | deploy:
19 | provider: releases
20 | api_key:
21 | secure: QM1l+bhiQOLnZaRWVG+9KJ4sx8k2qKD4zveFyh9N1hHI3SV1zv3UKrHR3O2a6RL433smzBhwuCVmz5TT0m/V2yixl7ti7Bij7ENNqrvTWJTvAUbF5gCmXZbVmjBxggAVSsWo3szZgMSe1dDrdBkEQwOTADp9vUv49GhPLRCjfSr0+AR2woPhL6dphwpmha6UIl1eSDF6StaIVf+KIj1v794oAyWqe2sWjsPP9CwYZeNTJXMZwvSClKD7MTRgtbYJJYwkCmVWUJwqGLEbHCUMRrSUsvLkQkmlEymYS2T9buCnUHSUSrHe23UKyCYhUTFxDqSyuYsGbtpa7mdLe6ShqHl6PrkIsyugkXfAw6Td+M8VEyaAD68+7xhw6NEJHo7mpQzHLrd+t2jIfQgD6d3NsiioTdv5srgyMos1X+yjjM4f9dqzmp8ltaQXlcBgo+WKPW9V98rJCLR+UaCoyScbi/jKH/CdQUhdkIP1QMfyfRNGBSeqNtvhm554A0kfh3Euf2oicjeGOI3oRVXPvETSxOuBhiIQ+pJSn9qDnkntLlS3swX29OPqzTzZQ/Qpm8rGlCmcJIUeFfplrMmAZs+dgFTo/hcxvWzVHC3b+6XvQkGy9NR9Tc0hnm7yTFdExnP8rHeVDNHtU4E+yvjKYA/uvacyDEJ/tXeSwHCgUjIljiY=
22 | file: ${RELEASE_PKG_FILE}
23 | skip_cleanup: true
24 | on:
25 | tags: true
26 | condition: $TRAVIS_PHP_VERSION = 7.4
27 | repo: interfax/interfax-php
28 |
--------------------------------------------------------------------------------
/CHANGELOG.md:
--------------------------------------------------------------------------------
1 | # Changelog
2 |
3 | All notable changes to this project will be documented in this file. This project adheres to [Semantic Versioning](http://semver.org/).
4 |
5 | ## 2.0.0
6 |
7 | ### Changed
8 | + Conform to PSR12 coding standard
9 | + Composer dependency updates to match PHP version constraints for split branch versions of the library
10 | + README updates to reflect branch differences for library
11 |
12 | ### Fixed
13 | + Revert phpunit suggestion to dev dependency with correct version constraints
14 | + Restore missing CHANGELOG contents
15 |
16 | ## 1.1.5
17 |
18 | ### Fixed
19 | + Guzzle 7 support
20 |
21 | 1.1.4
22 | =====
23 | + accept any 2xx status responses from interfax api
24 | + minor improvement to response exception generation
25 |
26 | 1.1.3
27 | =====
28 | + Enhancement: Make fax id available when first created
29 |
30 | 1.1.2
31 | =====
32 | + [BUG] Fix bug in marking inbound faxes as read/unread
33 |
34 |
35 | 1.1.1
36 | =====
37 | + Bugfix: urlencode filename attribute for multipart fax document upload.
38 |
39 | 1.1.0
40 | =====
41 | + Fluent method signatures where appropriate on Fax and Document objects.
42 | + Distinct Test namespace to ensure individual test file running is supported.
43 |
44 | 1.0.3
45 | =====
46 | + Documentation correction for the outbound fax status retrieval.
47 |
48 | 1.0.2
49 | =====
50 | + Update to project structure to support automatic package generation.
51 |
52 | 1.0.1
53 | =====
54 | + Added INSTALLATION.md file to document how to use the library outside of a composer managed framework.
55 | + Added support for using stream resources to send faxes.
56 |
57 | 1.0.0
58 | =====
59 | + Initial release
60 |
--------------------------------------------------------------------------------
/INSTALLATION.md:
--------------------------------------------------------------------------------
1 | # InterFAX PHP Library
2 |
3 | This file provides more detail as to how to install the Interfax PHP library in a project.
4 |
5 | ## Standard installation
6 |
7 | The standard approach is to use the composer dependency manager to add the library to your project requirements:
8 |
9 | ```bash
10 | composer require interfax/interfax
11 | ```
12 |
13 | ## Standalone installation
14 |
15 | Many projects may not use composer to manage their dependencies. In these circumstances, it's possible to include the library
16 | as a self contained dependency. The following steps will allow you to do this.
17 |
18 | 1. Clone the Interfax PHP repo into your project.
19 | 1. Inside the Interfax PHP directory, download composer.
20 | 1. Run composer to download the dependencies for the Interfax library.
21 | 1. Back in your main project file(s), include the autoload file generated by composer to include the library and its dependencies.
22 | 1. Follow the documentation to use the library as normal.
23 |
24 | ### Example project
25 |
26 | Assuming a simple project for Acme Corp that consists of a single ```index.php``` file.
27 |
28 | #### Download the library
29 |
30 | ```sh
31 | cd acme-corp
32 | git clone https://github.com/interfax/interfax-php.git
33 | cd interfax-php
34 | ```
35 |
36 | #### Setup Composer
37 |
38 | Assuming composer is not already installed globally, install it into a bin directory.
39 |
40 | ```sh
41 | mkdir bin
42 | ```
43 | _Note the [composer site](http://getcomposer.org) has more detailed instructions for installation, the following is a small simplification_
44 | ```sh
45 | php -r "copy('https://getcomposer.org/installer', 'composer-setup.php');"
46 | php composer-setup.php --install-dir=bin
47 | php -r "unlink('composer-setup.php');"
48 | ```
49 |
50 | ### Download dependencies
51 |
52 | Simply run the install command to download the dependencies
53 |
54 | ```sh
55 | php ./bin/composer.phar install --no-dev
56 | ```
57 |
58 | _The 'no-dev' option prevents the testing dependencies for the library from being installed to save space/bandwidth_
59 |
60 | ### Use the library
61 |
62 | inside acme-corp/index.php
63 |
64 | ```php
65 | require_once(__DIR__ . '/interfax-php/vendor/autoload.php');
66 |
67 | use Interfax\Client;
68 |
69 | $interfax = new Client(['username' => 'username', 'password' => 'password']);
70 | // etc
71 | ```
72 |
73 | ### Deployment
74 |
75 | When it comes to deploying the project, the following paths will be required:
76 |
77 | ```
78 | acme-corp/interfax-php/src/
79 | acme-corp/interfax-php/vendor/
80 | ```
81 |
82 | The rest of the files can safely be ignored.
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2016 InterFAX
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # InterFAX PHP Library
2 |
3 | [](https://badge.fury.io/ph/interfax%2Finterfax)[](https://travis-ci.com/interfax/interfax-php)
4 |
5 | [Installation](#installation) | [Getting Started](#getting-started) | [Contributing](#contributing) | [Usage](#usage) | [License](#license)
6 |
7 | Send and receive faxes in PHP with the [InterFAX](https://www.interfax.net/en/dev) REST API.
8 |
9 | ## Installation
10 |
11 | Two versions of this library exist, 1.x and 2.x. The 1.x version provides support for older versions of PHP, whilst the 2.x branch is designed to support the more recent releases of the language:
12 |
13 | | Package Version | Minimum PHP Version | Maximum PHP Version |
14 | |-----------------|----------------------|---------------------|
15 | | 1.x | 5.6 | 7.2 |
16 | | 2.x | 7.3 | 8.1 |
17 |
18 | ### Composer
19 |
20 | The preferred method of installation is via [Packagist](http://www.packagist.org) and [Composer](http://www.composer.org). Run the following command to install the package and add it as a requirement to your project's `composer.json`:
21 |
22 | ```bash
23 | composer require interfax/interfax
24 | ```
25 |
26 | with 1.x version constraint
27 | ```bash
28 | composer require interfax/interfax:"^1"
29 | ```
30 |
31 | or with 2.x version constraint
32 |
33 | ```bash
34 | composer require interfax/interfax:"^2"
35 | ```
36 |
37 | ### Download the release
38 |
39 | You can download the package in its entirety (from 1.0.2 onward). The [Releases](https://github.com/interfax/interfax-php/releases) page lists all stable versions. Download any file
40 | with the name `interFAX-PHP-[RELEASE_NAME].zip` for a package including this library and its dependencies.
41 |
42 | Uncompress the zip file you download, and include the autoloader in your project:
43 |
44 | ```php
45 | require_once '/path/to/interFAX-PHP-[RELEASE_NAME]/vendor/autoload.php';
46 | ```
47 |
48 | You may wish to rename the release folder to not include the RELEASE_NAME, so that you can drop in future versions without changing the include.
49 |
50 | ### Build it yourself
51 |
52 | The [installation](INSTALLATION.md) docs explain how to create a standalone installation.
53 |
54 | ## Getting started
55 |
56 | To send a fax for a pdf file:
57 |
58 | ```php
59 | use Interfax\Client;
60 |
61 | $interfax = new Client(['username' => 'username', 'password' => 'password']);
62 | $fax = $interfax->deliver(['faxNumber' => '+11111111112', 'file' => 'folder/file.pdf']);
63 |
64 | // get the latest status:
65 | $fax->refresh()->status; // Pending if < 0. Error if > 0
66 |
67 | // Simple polling
68 | while ($fax->refresh()->status < 0) {
69 | sleep(5);
70 | }
71 | ```
72 |
73 | # Usage
74 |
75 | [Client](#client) | [Account](#account) | [Outbound](#outbound) | [Inbound](#inbound) | [Documents](#documents) | [Helper Classes](#helper-classes) | [Query Parameters](#query-parameters) | [Exceptions](#exceptions)
76 |
77 | ## Client
78 |
79 | The client follows the [12-factor](http://12factor.net/config) apps principle and can be either set directly or via environment variables.
80 |
81 | ```php
82 | $client = new Interfax\Client(['username' => '...', 'password' => '...']);
83 |
84 | // Alternative: will utilise environment variables:
85 | // * INTERFAX_USERNAME
86 | // * INTERFAX_PASSWORD
87 |
88 | $client = new Interfax\Client();
89 | ```
90 | ### Send a Fax
91 |
92 | To send a fax, call the deliver method on the client with the appropriate array of parameters.
93 |
94 | ```php
95 | $client = new Interfax\Client(['username' => '...', 'password' => '...']);
96 | $fax = $client->deliver([
97 | 'faxNumber' => '+442086090368',
98 | 'file' => __DIR__ . '/../tests/Interfax/test.pdf'
99 | ]);
100 | ```
101 |
102 | The ```deliver``` method will take either a ```file``` or ```files``` argument. The ```files``` is an array of file values.
103 |
104 | Each ```file``` entry can be:
105 |
106 | * local path - if the file is larger than the allowed limit, it will be automatically uploaded as an ```Interfax\Document```
107 | * uri (from an ```Interfax\Document```)
108 | * an array defining a streamed resource (see below)
109 | * ```Interfax\File```
110 | * ```Interfax\Document```
111 |
112 | #### Sending a stream
113 |
114 | Because of the high degree of flexibility that PHP stream resources offer, it's not practical to retrieve information automatically from a stream to send as a fax. As such, there are certain required parameters that must be provided:
115 |
116 | ```php
117 | $stream = fopen('/tmp/fax.pdf', 'rb');
118 | $fax = $client->deliver([
119 | 'faxNumber' => '+442086090368',
120 | 'file' => [$stream, ['name' => 'fax.pdf', 'mime_type' => 'application/pdf']]
121 | ```
122 |
123 | Note that it is assumed that the stream will not exceed the file size limitation for an inline file to be sent. However, if a size parameter is provided for the stream, and this exceeds the limit, it will be automatically uploaded as a ```Interfax\Document```
124 |
125 | [Documentation](https://www.interfax.net/en/dev/rest/reference/2918)
126 |
127 | ## Account
128 |
129 | ### Balance
130 |
131 | Determine the remaining faxing credits in your account.
132 |
133 | ```php
134 | echo $client->getBalance();
135 | // (string) 9.86
136 | ```
137 |
138 | **More:** [documentation](https://www.interfax.net/en/dev/rest/reference/3001)
139 |
140 | ## Outbound
141 |
142 | [Get list](#get-outbound-fax-list) | [Get completed list](#get-completed-fax-list) | [Get record](#get-outbound-fax-record) | [Get image](#get-outbound-fax-image) | [Cancel fax](#cancel-an-outbound-fax) | [Search](#search-fax-list) | [Resend fax](#resend-a-fax)
143 |
144 | ```Interfax\Client``` has an outbound property that can be accessed:
145 |
146 | ```php
147 | $outbound = $client->outbound;
148 | ```
149 |
150 | ### Get outbound fax list
151 |
152 | ```php
153 | $faxes = $client->outbound->recent();
154 | // Interfax\Outbound\Fax[]
155 | ```
156 |
157 | **Options:** [`limit`, `lastId`, `sortOrder`, `userId`](https://www.interfax.net/en/dev/rest/reference/2920)
158 |
159 | ----
160 |
161 | ### Get completed fax list
162 |
163 | ```php
164 | $fax_ids = [ ... ]; // array of fax ids
165 | $client->outbound->completed($fax_ids);
166 | // Interfax\Outbound\Fax[]
167 | ```
168 |
169 | ### Get outbound fax record
170 |
171 | `$client->outbound->find(fax_id)`
172 |
173 | Retrieves information regarding a previously-submitted fax, including its current status.
174 |
175 | ```php
176 | $fax = $client->outbound->find(123456);
177 | //Interfax\Outbound\Fax || null
178 | ```
179 |
180 | [Documentation](https://www.interfax.net/en/dev/rest/reference/2921)
181 |
182 | ### Get outbound fax image
183 |
184 | `$client->outbound->find(fax_id)->image()`
185 |
186 | The image is retrieved via a method on the outbound fax image object.
187 |
188 | ```php
189 | $fax = $client->outbound->find(123456);
190 | if ($fax) {
191 | $image = $fax->image();
192 | $image->save('path/to/save/file/to.tif');
193 | }
194 | ```
195 |
196 | ### Cancel an outbound fax
197 |
198 | `$client->outbound->find(fax_id)->cancel();`
199 |
200 | A fax is cancelled via a method on the `Interfax\Outbound\Fax` model.
201 |
202 | ```php
203 | $fax = $client->outbound->find(123456);
204 | if ($fax) {
205 | $fax->cancel();
206 | }
207 | ```
208 |
209 | ### Search fax list
210 |
211 | `$client->outbound->search($options)`
212 |
213 | Search for outbound faxes with a hash array of options keyed by the accepted search parameters for the outbound search API endpoint.
214 |
215 | ```php
216 | $faxes = $client->outbound->search(['faxNumber' => '+1230002305555']);
217 | // Interfax\Outbound\Fax[]
218 | ```
219 |
220 | **Options:** [`ids`, `reference`, `dateFrom`, `dateTo`, `status`, `userId`, `faxNumber`, `limit`, `offset`](https://www.interfax.net/en/dev/rest/reference/2959)
221 |
222 | ### Resend a Fax
223 |
224 | `$client->outbound->resend($id[,$newNumber])`
225 |
226 | Resend the fax identified by the given id (optionally to a new fax number).
227 |
228 | ```php
229 | $fax = $client->outbound->resend($id);
230 | // Interfax\Outbound\Fax sent to the original number
231 | $fax = $client->outbound->resend($id, $new_number);
232 | // Interfax\Outbound\Fax sent to the $new_number
233 | ```
234 |
235 | Returns a new `Interfax\Outbound\Fax` representing the newly created outbound fax.
236 |
237 | ## Inbound
238 |
239 | [Get list](#get-inbound-fax-list) | [Get record](#get-inbound-fax-record) | [Get image](#get-inbound-fax-image) | [Get emails](#get-forwarding-emails) | [Mark as read](#mark-as-readunread) | [Resend to email](#resend-inbound-fax)
240 |
241 | ```Interfax\Client``` has an ```inbound``` property that supports the API endpoints for receiving faxes, as described in the [Documentation](https://www.interfax.net/en/dev/rest/reference/2913)
242 |
243 | ```php
244 | $inbound = $client->inbound;
245 | //Interfax\Inbound
246 | ```
247 |
248 | ### Get inbound fax list
249 |
250 | `$inbound->incoming($options = []);`
251 |
252 | Retrieves a user's list of inbound faxes.
253 |
254 | ```php
255 | $faxes = $inbound->incoming();
256 | //\Interfax\Inbound\Fax[]
257 | $faxes = $inbound->incoming(['unreadOnly' => true ...]); // see docs for list of supported query params
258 | //\Interfax\Inbound\Fax[]
259 | ```
260 |
261 | [Documentation](https://www.interfax.net/en/dev/rest/reference/2935)
262 |
263 | ---
264 |
265 | ### Get inbound fax record
266 |
267 | `$inbound->find($id);`
268 |
269 | Retrieves a single fax's metadata (receive time, sender number, etc.).
270 |
271 | ```php
272 | $fax = $inbound->find(123456);
273 | //\Interfax\Inbound\Fax || null
274 | ```
275 |
276 | null is returned if the resource is not found. Note that this could be because the user is not permissioned for the specific fax.
277 |
278 | [Documentation](https://www.interfax.net/en/dev/rest/reference/2938)
279 |
280 | ---
281 |
282 | ### Get inbound fax image
283 |
284 | `$inbound->find($id)->image()`
285 |
286 | The image is retrieved via a method on the inbound fax object.
287 |
288 | ```php
289 | $fax = $client->inbound->find(123456);
290 | if ($fax) {
291 | $image = $fax->image();
292 | $image->save('path/to/save/file/to.pdf');
293 | }
294 | ```
295 |
296 | [Documentation](https://www.interfax.net/en/dev/rest/reference/2937)
297 |
298 | ---
299 |
300 | ### Get forwarding emails
301 |
302 | `$inbound->find($id)->emails()`
303 |
304 | The forwarding email details are retrieved via a method on the inbound fax object.
305 |
306 | ```php
307 | $fax = $client->inbound->find(123456);
308 | if ($fax) {
309 | $emails = $fax->emails(); // array structure of forwarding emails.
310 | }
311 | ```
312 |
313 | The returned array is a reflection of the values returned from the emails endpoint of the REST API:
314 |
315 | ```php
316 | [
317 | [
318 | 'emailAddress' => 'username@interfax.net',
319 | 'messageStatus' => 0,
320 | 'completionTime' => '2012-0623T17 => 24 => 11'
321 | ],
322 | //...
323 | ];
324 | ```
325 |
326 | [Documentation](https://www.interfax.net/en/dev/rest/reference/2930)
327 |
328 | ---
329 |
330 | ### Mark as read/unread
331 |
332 | `$inbound->find($id)->markRead();`
333 | `$inbound->find($id)->markUnread();`
334 |
335 | The inbound fax object provides methods to change the read status.
336 |
337 | ```php
338 | $fax = $client->inbound->find(123456);
339 | if ($fax) {
340 | $fax->markUnread(); // returns true
341 | $fax->markRead(); //returns true
342 | }
343 | ```
344 |
345 | [Documentation](https://www.interfax.net/en/dev/rest/reference/2936)
346 |
347 | ---
348 |
349 | ### Resend inbound fax
350 |
351 | `$inbound->find($id)->resend();`
352 |
353 | The resend method is on the inbound fax object.
354 |
355 | ```php
356 | $fax = $client->inbound->find(123456);
357 | if ($fax) {
358 | $fax->resend();
359 | }
360 | ```
361 |
362 | ---
363 |
364 | ## Documents
365 |
366 | [Create](#create-document) | [Upload chunk](#upload-chunk) | [Properties](#document-properties) | [Cancel](#cancel-document)
367 |
368 | The ```Interfax\Document``` class allows for the uploading of larger files for faxing. The following is an example of how one should be created:
369 |
370 | ```php
371 | $document = $client->documents->create('test.pdf', filesize('test.pdf'));
372 | $stream = fopen('test.pdf', 'rb');
373 | $current = 0;
374 | while (!feof($stream)) {
375 | $chunk = fread($stream, 500);
376 | $end = $current + strlen($chunk);
377 | $doc->upload($current, $end-1, $chunk);
378 | $current = $end;
379 | }
380 | fclose($stream);
381 | ```
382 |
383 | ### Create document
384 |
385 | ```php
386 | $params = [...]; // see documentation for possible params
387 | $document = $client->documents->create($filename, filesize($filename), $params);
388 | // Interfax\Document
389 | ```
390 |
391 | [Documentation](https://www.interfax.net/en/dev/rest/reference/2967)
392 |
393 | ### Upload chunk
394 |
395 | ```php
396 | $document->upload($start, $end, $data); // returns the document object.
397 | ```
398 |
399 | Note no verification of data takes place - an exception wil be raised if values do not match appropriately.
400 |
401 | ### Document properties
402 |
403 | As per the [documentation](https://www.interfax.net/en/dev/rest/reference/2965) a Document has a number of properties which are accessible:
404 |
405 | ```php
406 | $document->status;
407 | $document->fileName;
408 | $document->refresh()->attributes();
409 | ```
410 |
411 | ```php
412 | $document->location;
413 | // or as returned by the API:
414 | $document->uri;
415 | ```
416 |
417 | ### Cancel document
418 |
419 | `$document->cancel(); //returns the $document instance`
420 |
421 | Can be done prior to completion or afterward
422 |
423 | ## Helper Classes
424 |
425 | ### Outbound Fax
426 |
427 | The `Interfax\Outbound\Fax` class wraps the details of any fax sent, and is returned by most of the ```Outbound``` methods.
428 |
429 | It offers several methods to manage or retrieve information about the fax.
430 |
431 | ```php
432 | // fluent methods that return the $fax instance
433 | $fax->refresh(); // refreshes the data on the fax object
434 | $fax->cancel(); // cancel the fax, returns true on success
435 | $fax->hide(); // hides the faxes from the fax lists
436 |
437 | $image = $fax->image(); // returns Interfax\Image
438 | $new_fax = $fax->resend('+1111111'); // returns a new Interfax\Outbound\Fax
439 | $fax->attributes(); // hash array of fax data properties - see details below
440 | ```
441 |
442 | ### Outbound fax properties
443 |
444 | Properties on the Fax vary depending on which method call has been used to create the instance. Requesting a property that has not been received will raise a SPL ```\OutOfBoundsException```
445 |
446 | [Documentation](https://www.interfax.net/en/dev/rest/reference/2921)
447 |
448 | These are all accessible on a fax instance:
449 |
450 | ```php
451 | echo $fax->completionTime
452 | echo $fax->duration
453 | ...
454 | ```
455 |
456 | Note values will all be returned as strings.
457 |
458 | For convenience, a hash array of the properties can be retrieved
459 |
460 | ```php
461 | $fax->attributes();
462 | ```
463 |
464 | Status should always be available. The values of the status codes are [Documented here](https://www.interfax.net/en/help/error_codes)
465 |
466 | ### Inbound Fax
467 |
468 | The incoming equivalent of the outbound fax class, the ```Interfax\Inbound\Fax``` class wraps the details of any incoming fax, and is returned by the ```Interfax\Inbound``` methods where appropriate.
469 |
470 | ```php
471 | // fluent methods that return the $fax instance for method chaining
472 | $fax->refresh(); // reload properties of the inbound fax
473 | $fax->markRead(); // mark the fax read - returns true or throws exception
474 | $fax->markUnread(); // mark the fax unread - returns true or throws exception
475 | $fax->resend();
476 |
477 | $image = $fax->image(); // Returns a Interfax\Image for this fax
478 | $email_array = $fax->emails(); // see below for details on the structure of this array
479 | $fax->attributes(); // hash array of properties
480 | ```
481 |
482 | ## Query parameters
483 |
484 | Where methods support a hash array structure of query parameters, these will be passed through to the API endpoint as provided. This ensures that any future parameters that might be added will be supported by the API as is.
485 |
486 | The only values that are manipulated are booleans, which will be translated to the text 'TRUE' and 'FALSE' as appropriate.
487 |
488 | [Documentation](https://www.interfax.net/en/dev/rest/reference/2927)
489 |
490 | ## Exceptions
491 |
492 | Any method call that involves a call to the Interfax RESTful API may throw an instance of ```Interfax\Exception\RequestException```.
493 |
494 | An exception is thrown for any requests that do not return a successful HTTP Status code. The goal of this Exception is to provide a convenience wrapper around information that may have been returned.
495 |
496 | Certain responses from the API will provide more detail, and where this occurs, it will be appended to the message of the Exception.
497 |
498 | ```
499 | try {
500 | $interfax->deliver(...);
501 | } catch (Interfax\Exception\RequestException $e) {
502 | echo $e->getMessage();
503 | // contains text detail that is available
504 | echo $e->getStatusCode();
505 | // the http status code that was received
506 | throw $e->getWrappedException();
507 | // The underlying Guzzle exception that was caught by the Interfax Client.
508 | }
509 | ```
510 |
511 | ## Contributing
512 |
513 | 1. **Fork** the repo on GitHub
514 | 2. **Clone** the project to your own machine
515 | 3. **Commit** changes to your own branch
516 | 4. **Push** your work back up to your fork
517 | 5. Submit a **Pull request** so that we can review your changes
518 |
519 | ### Which version of the library?
520 |
521 | Functionality for the API in both versions of the library should be the same, and its therefore intended that the core code continues to be the same in both versions. The differences primarily exist to enable continuity of test coverage as PHP evolves (and phpunit evolves with it)
522 |
523 | As such, the core functionality should be developed in a way that will work with PHP 5.6 and up, and be consistent in both versions. Usage of newer language features in PHP will not be accepted in the core code.
524 |
525 | ### Running tests
526 |
527 | Ensure that composer is installed, then run the following commands.
528 |
529 | ```sh
530 | composer install
531 | ./vendor/bin/phpunit
532 | ```
533 |
534 | ## License
535 |
536 | This library is released under the [MIT License](LICENSE).
537 |
--------------------------------------------------------------------------------
/bin/build.php:
--------------------------------------------------------------------------------
1 | isDir() ? rmdir($file) : unlink($file);
31 | }
32 | return true;
33 | }
34 |
35 | function copyDirectory($from, $to)
36 | {
37 | $from_real = realpath($from);
38 |
39 | if (!mkdir($to)) return false;
40 | $to_real = realpath($to);
41 |
42 | $from_len = strlen($from_real)+1;
43 | $di = new RecursiveDirectoryIterator($from_real, FilesystemIterator::SKIP_DOTS);
44 | $ri = new RecursiveIteratorIterator($di, RecursiveIteratorIterator::SELF_FIRST);
45 | foreach ( $ri as $file ) {
46 | $file->isDir()
47 | ? mkdir($to_real . '/' . substr($file->getRealPath(), $from_len))
48 | : copy($file->getRealPath(), $to_real . '/' . substr($file->getRealPath(), $from_len));
49 | }
50 |
51 | return true;
52 | }
53 |
54 | function copyRequiredFiles($base_path, $build_path)
55 | {
56 | if (!copyDirectory($base_path . '/src', $build_path . '/src')) return false;
57 | if (!copy($base_path . '/composer.json', $build_path. '/composer.json')) return false;
58 | if (!copy($base_path . '/composer.lock', $build_path. '/composer.lock')) return false;
59 | return true;
60 | }
61 |
62 | function runComposerInstall($build_path)
63 | {
64 | return `composer install --no-dev --no-interaction --optimize-autoloader --working-dir={$build_path}` == 0;
65 | }
66 |
67 | function createCompressedFiles($build_path)
68 | {
69 | $real_bp = realpath($build_path);
70 | $bp_len = strlen($real_bp) + 1;
71 | $archive = new ZipArchive();
72 | $archive->open($real_bp . '/' . getReleaseName() . '.zip', ZIPARCHIVE::CREATE);
73 | foreach (['src', 'vendor'] as $dir) {
74 | $build_dir = $real_bp . '/' . $dir;
75 |
76 | $di = new RecursiveDirectoryIterator($build_dir, FilesystemIterator::SKIP_DOTS);
77 | $ri = new RecursiveIteratorIterator($di, RecursiveIteratorIterator::SELF_FIRST);
78 | foreach ($ri as $file) {
79 | $file->isDir()
80 | ? $archive->addEmptyDir(substr($file->getRealPath(), $bp_len))
81 | : $archive->addFile($file, substr($file->getRealPath(), $bp_len));
82 | }
83 | }
84 | $archive->close();
85 | return true;
86 | }
87 |
88 | function getReleaseName()
89 | {
90 | return 'interFAX-PHP-' . Interfax\Client::VERSION;
91 | }
--------------------------------------------------------------------------------
/composer.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "interfax/interfax",
3 | "description": "Send and receive faxes with InterFAX",
4 | "type": "library",
5 | "require": {
6 | "php": "^7.3|^7.4|^8",
7 | "guzzlehttp/guzzle": "^7.0"
8 | },
9 | "require-dev": {
10 | "mikey179/vfsstream": "^1.6.7",
11 | "squizlabs/php_codesniffer": "^3",
12 | "phpunit/phpunit": "^9"
13 | },
14 | "license": "MIT",
15 | "authors": [
16 | {
17 | "name": "InterFAX",
18 | "email": "dev@interfax.net"
19 | },
20 | {
21 | "name": "Mike Smith",
22 | "email": "mike.smith@camc-ltd.co.uk"
23 | }
24 | ],
25 | "autoload": {
26 | "psr-4": {
27 | "Interfax\\": "src/Interfax",
28 | "Test\\": "tests"
29 | }
30 | }
31 | }
32 |
--------------------------------------------------------------------------------
/phpcs.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | PHPCS configuration file.
6 |
9 | src
10 | tests
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 | */*Test.php
21 |
22 |
23 |
24 |
--------------------------------------------------------------------------------
/phpunit.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
12 |
13 |
14 |
15 | ./tests/
16 |
17 |
18 |
19 |
20 |
--------------------------------------------------------------------------------
/src/Interfax/Client.php:
--------------------------------------------------------------------------------
1 |
10 | * @copyright Copyright (c) 2016, InterFAX
11 | * @license MIT
12 | */
13 |
14 | namespace Interfax;
15 |
16 | use GuzzleHttp\Client as GuzzleClient;
17 | use Interfax\Exception\RequestException;
18 | use Interfax\Outbound\Fax;
19 | use Psr\Http\Message\ResponseInterface;
20 |
21 | class Client
22 | {
23 | const VERSION = '2.0.0';
24 |
25 | /**
26 | * @var GenericFactory
27 | */
28 | private $factory;
29 |
30 | /**
31 | * @var Outbound
32 | */
33 | protected $outbound;
34 | /**
35 | * @var Inbound
36 | */
37 | protected $inbound;
38 | /**
39 | * @var Documents
40 | */
41 | protected $documents;
42 |
43 | protected static $ENV_USERNAME = 'INTERFAX_USERNAME';
44 | protected static $ENV_PASSWORD = 'INTERFAX_PASSWORD';
45 | protected static $DEFAULT_BASE_URI = 'https://rest.interfax.net';
46 |
47 | public $username;
48 | public $password;
49 |
50 | /**
51 | * @var GuzzleClient
52 | */
53 | protected $http;
54 |
55 | /**
56 | * @var bool
57 | */
58 | private $debug = false;
59 | private $base_uri;
60 |
61 | /**
62 | * Client constructor.
63 | * @param array $params
64 | * 'username' - string
65 | * 'password' - string
66 | * 'base_uri' - string override the API endpoint base (useful for testing)
67 | * 'debug' - bool - put the Guzzle client into debug mode
68 | * @param GenericFactory|null $factory - allows for testing injection with abstract class instantiation
69 | * @throws \InvalidArgumentException
70 | */
71 | public function __construct($params = [], GenericFactory $factory = null)
72 | {
73 | if ($params === null || !is_array($params)) {
74 | throw new \InvalidArgumentException('array of parameters expected to instantiate ' . __CLASS__);
75 | }
76 |
77 | $username = array_key_exists('username', $params) ? $params['username'] : getenv(static::$ENV_USERNAME);
78 | $password = array_key_exists('password', $params) ? $params['password'] : getenv(static::$ENV_PASSWORD);
79 |
80 | if (array_key_exists('debug', $params)) {
81 | $this->debug = $params['debug'];
82 | }
83 | if (array_key_exists('base_uri', $params)) {
84 | $this->base_uri = rtrim($params['base_uri'], '/');
85 | }
86 |
87 | $this->username = $username;
88 | $this->password = $password;
89 | if ($this->username === '' || $this->password === '') {
90 | throw new \InvalidArgumentException(
91 | 'Username and Password must be provided or defined as environment variables '
92 | . static::$ENV_USERNAME . ' & ' . static::$ENV_PASSWORD
93 | );
94 | }
95 |
96 | // if its not injected, we instantiate directly
97 | if ($factory === null) {
98 | $factory = new GenericFactory();
99 | }
100 |
101 | $this->factory = $factory;
102 | }
103 |
104 | private static $cached_accessible = [
105 | 'outbound' => 'Interfax\Outbound',
106 | 'inbound' => 'Interfax\Inbound',
107 | 'documents' => 'Interfax\Documents'
108 | ];
109 |
110 | /**
111 | * Simplifies the route to accessing specific 'route' classes for the client
112 | *
113 | * @param $name
114 | * @return mixed
115 | */
116 | public function __get($name)
117 | {
118 | if (in_array($name, array_keys(static::$cached_accessible))) {
119 | if (!$this->$name) {
120 | $this->$name = $this->factory->instantiateClass(static::$cached_accessible[$name], [$this]);
121 | }
122 | return $this->$name;
123 | }
124 | }
125 |
126 | /**
127 | * @return GuzzleClient
128 | */
129 | protected function getHttpClient()
130 | {
131 | if (!$this->http) {
132 | $config = ['base_uri' => $this->base_uri ?: static::$DEFAULT_BASE_URI];
133 | if ($this->debug) {
134 | $config['debug'] = true;
135 | }
136 | $this->http = $this->factory->instantiateClass(
137 | 'GuzzleHttp\Client',
138 | [$config]
139 | );
140 | }
141 |
142 | return $this->http;
143 | }
144 |
145 | /**
146 | * @return string
147 | */
148 | public function getUserAgent()
149 | {
150 | return 'InterFAX PHP ' . static::VERSION;
151 | }
152 |
153 | /**
154 | * @return array
155 | */
156 | protected function getBaseRequestParams()
157 | {
158 | return [
159 | 'auth' => [$this->username, $this->password],
160 | 'headers' => [
161 | 'User-Agent' => $this->getUserAgent()
162 | ]
163 | ];
164 | }
165 |
166 | /**
167 | * @param array $params
168 | * @return array
169 | */
170 | protected function getCompleteRequestParams($params = [])
171 | {
172 | $complete = array_merge_recursive($this->getBaseRequestParams(), $params);
173 |
174 | if (array_key_exists('query', $complete)) {
175 | foreach ($complete['query'] as $k => $v) {
176 | if (is_bool($v)) {
177 | $complete['query'][$k] = $v ? 'TRUE' : 'FALSE';
178 | }
179 | }
180 | }
181 |
182 | return $complete;
183 | }
184 |
185 | /**
186 | * POST request.
187 | *
188 | * @param $uri
189 | * @param array $params
190 | * @param $multipart
191 | * @return string|array
192 | * @throws RequestException
193 | */
194 | public function post($uri, $params = [], $multipart = [])
195 | {
196 | if ($multipart && count($multipart)) {
197 | $request_params = $this->getCompleteRequestParams(array_merge($params, ['multipart' => $multipart]));
198 | } else {
199 | $request_params = $this->getCompleteRequestParams($params);
200 | }
201 |
202 | try {
203 | return $this->parseResponse(
204 | $this->getHttpClient()->request('POST', $uri, $request_params)
205 | );
206 | } catch (\GuzzleHttp\Exception\RequestException $e) {
207 | throw RequestException::create('Problem with POST request', $e);
208 | }
209 | }
210 |
211 | /**
212 | * GET request.
213 | *
214 | * @param $uri
215 | * @param array $params
216 | * @return string|array
217 | * @throws RequestException
218 | */
219 | public function get($uri, $params = [])
220 | {
221 | $request_params = $this->getCompleteRequestParams($params);
222 |
223 | try {
224 | $response = $this->getHttpClient()->request('GET', $uri, $request_params);
225 | return $this->parseResponse($response);
226 | } catch (\GuzzleHttp\Exception\RequestException $e) {
227 | throw RequestException::create('Problem with GET request', $e);
228 | }
229 | }
230 |
231 | /**
232 | * @param $uri
233 | * @return int - status code of the API request
234 | *
235 | */
236 | public function delete($uri)
237 | {
238 | $params = $this->getCompleteRequestParams();
239 | try {
240 | $response = $this->getHttpClient()->request('DELETE', $uri, $params);
241 | return $response->getStatusCode();
242 | } catch (\GuzzleHttp\Exception\RequestException $e) {
243 | throw RequestException::create('Problem with DELETE request', $e);
244 | }
245 | }
246 |
247 | /**
248 | * Parses the responses in a consistent manner for handling by various classes.
249 | *
250 | * @param ResponseInterface $response
251 | * @return mixed|string|array
252 | * @throws RequestException
253 | */
254 | protected function parseResponse(ResponseInterface $response)
255 | {
256 | if ($response->getStatusCode() >= 200 && $response->getStatusCode() < 300) {
257 | if ($location = $response->getHeaderLine('Location')) {
258 | return $location;
259 | } elseif ($response->getHeaderLine('Content-Type') === 'text/json') {
260 | return json_decode((string) $response->getBody(), true);
261 | } else {
262 | return $response->getBody();
263 | }
264 | } else {
265 | throw new RequestException(
266 | 'Unexpected response code',
267 | RequestException::$UNEXPECTED_RESPONSE_CODE,
268 | $response->getStatusCode()
269 | );
270 | }
271 | }
272 |
273 | /**
274 | * @param $params
275 | * @return Fax
276 | * @throws \InvalidArgumentException
277 | *
278 | */
279 | public function deliver($params)
280 | {
281 | $delivery = $this->factory->instantiateClass('Interfax\Outbound\Delivery', [$this, $params]);
282 | return $delivery->send();
283 | }
284 |
285 | /**
286 | * @return string
287 | * @throws RequestException
288 | */
289 | public function getBalance()
290 | {
291 | return $this->get('/accounts/self/ppcards/balance');
292 | }
293 |
294 | public function getBaseUri()
295 | {
296 | return $this->getHttpClient()->getConfig('base_uri');
297 | }
298 | }
299 |
--------------------------------------------------------------------------------
/src/Interfax/Document.php:
--------------------------------------------------------------------------------
1 |
10 | * @author Mike Smith
11 | * @copyright Copyright (c) 2016, InterFAX
12 | * @license MIT
13 | */
14 |
15 | namespace Interfax;
16 |
17 | class Document extends Resource
18 | {
19 | protected static $resource_uri_stem = '/outbound/documents/';
20 |
21 | /**
22 | * @param $start
23 | * @param $end
24 | * @param $data
25 | * @return self
26 | * @throws \Interfax\Exception\RequestException
27 | */
28 | public function upload($start, $end, $data)
29 | {
30 | $params = [
31 | 'headers' => [
32 | 'Range' => 'bytes=' . $start . '-' . $end,
33 | 'Content-Length' => $end - $start + 1,
34 | ],
35 | 'body' => $data
36 | ];
37 |
38 | $this->client->post($this->resource_uri, $params);
39 |
40 | return $this;
41 | }
42 |
43 | /**
44 | * @return self
45 | */
46 | public function cancel()
47 | {
48 | $this->client->delete($this->resource_uri);
49 | $this->record = [];
50 | return $this;
51 | }
52 |
53 | public function getHeaderLocation()
54 | {
55 | return $this->client->getBaseUri() . $this->resource_uri;
56 | }
57 | }
58 |
--------------------------------------------------------------------------------
/src/Interfax/Documents.php:
--------------------------------------------------------------------------------
1 |
10 | * @author Mike Smith
11 | * @copyright Copyright (c) 2016, InterFAX
12 | * @license MIT
13 | */
14 |
15 | namespace Interfax;
16 |
17 | class Documents
18 | {
19 | /**
20 | * @var GenericFactory
21 | */
22 | private $factory;
23 |
24 | /**
25 | * @var Client
26 | */
27 | protected $client;
28 |
29 | public function __construct(Client $client, GenericFactory $factory = null)
30 | {
31 | $this->client = $client;
32 | if ($factory === null) {
33 | $factory = new GenericFactory();
34 | }
35 | $this->factory = $factory;
36 | }
37 |
38 | /**
39 | * @param $document_name - name used when defining document on the API
40 | * @param $size - in bytes
41 | * @param array $params - additional parameters to be used when creating the document on the API
42 | * @return Document
43 | * @throws \Interfax\Exception\RequestException
44 | */
45 | public function create($document_name, $size, $params = [])
46 | {
47 | $all_params = array_merge($params, [
48 | 'name' => $document_name,
49 | 'size' => $size
50 | ]);
51 |
52 | $location = $this->client->post('/outbound/documents', ['query' => $all_params]);
53 |
54 | $path = parse_url($location, PHP_URL_PATH);
55 | $bits = explode('/', $path);
56 | $id = array_pop($bits);
57 | $all_params['id'] = $id;
58 | // spoof the attributes for the Document object from the given parameters
59 | return $this->factory->instantiateClass('Interfax\Document', [$this->client, $id, $all_params]);
60 | }
61 |
62 | /**
63 | * Get list of the available documents previously uploaded.
64 | *
65 | * @return array
66 | */
67 | public function available($query_params = [])
68 | {
69 | $params = [];
70 | if (count($query_params)) {
71 | $params = ['query' => $query_params];
72 | }
73 |
74 | $response = $this->client->get('/outbound/documents', $params);
75 |
76 | if (is_array($response)) {
77 | $result = [];
78 | foreach ($response as $definition) {
79 | $result[] = $this->factory->instantiateClass('Interfax\Document', [$this->client, $definition]);
80 | }
81 | return $result;
82 | }
83 |
84 | throw new \RuntimeException('A reasonable but unhandled response was received');
85 | }
86 | }
87 |
--------------------------------------------------------------------------------
/src/Interfax/Exception/RequestException.php:
--------------------------------------------------------------------------------
1 |
10 | * @author Mike Smith
11 | * @copyright Copyright (c) 2016, InterFAX
12 | * @license MIT
13 | */
14 |
15 | namespace Interfax\Exception;
16 |
17 | use GuzzleHttp\Exception\RequestException as GuzzleException;
18 |
19 | /**
20 | * Class RequestException
21 | * @package Interfax\Exception
22 | */
23 | class RequestException extends \RuntimeException
24 | {
25 | protected $http_status;
26 | protected $request_exception;
27 | public static $UNEXPECTED_RESPONSE_CODE = -9999;
28 |
29 | /**
30 | * RequestException constructor.
31 | * @param string $message
32 | * @param int $code
33 | * @param int $http_status
34 | * @param GuzzleException $request_exception
35 | * @param \Exception|null $previous
36 | */
37 | public function __construct(
38 | $message,
39 | $code,
40 | $http_status,
41 | GuzzleException $request_exception = null,
42 | \Exception $previous = null
43 | ) {
44 | $this->http_status = $http_status;
45 | $this->request_exception = $request_exception;
46 |
47 | parent::__construct($message, $code, $previous);
48 | }
49 |
50 | /**
51 | * @param $message
52 | * @param \GuzzleHttp\Exception\RequestException $exception
53 | * @return RequestException
54 | */
55 | public static function create($message, GuzzleException $exception)
56 | {
57 | $code = static::$UNEXPECTED_RESPONSE_CODE;
58 |
59 | $http_status = null;
60 | if ($exception->hasResponse()) {
61 | $response = $exception->getResponse();
62 | $http_status = $response->getStatusCode();
63 | if ($response->hasHeader('Content-Type') && $response->getHeaderLine('Content-Type') === 'text/json') {
64 | $json = json_decode((string)$response->getBody(), true);
65 | if ($json !== null) {
66 | if (array_key_exists('code', $json)) {
67 | $code = $json['code'];
68 | }
69 | if (array_key_exists('message', $json)) {
70 | $message .= ': ' . $json['message'];
71 | }
72 | }
73 | } else {
74 | $message .= ': ' . ($response->getBody() ?: 'no further information provided.');
75 | }
76 | }
77 |
78 | return new self($message, $code, $http_status, $exception);
79 | }
80 |
81 | /**
82 | * @return int
83 | */
84 | public function getStatusCode()
85 | {
86 | return $this->http_status;
87 | }
88 |
89 | /**
90 | * @return \GuzzleHttp\Exception\RequestException
91 | */
92 | public function getWrappedException()
93 | {
94 | return $this->request_exception;
95 | }
96 | }
97 |
--------------------------------------------------------------------------------
/src/Interfax/File.php:
--------------------------------------------------------------------------------
1 |
10 | * @copyright Copyright (c) 2016, InterFAX
11 | * @license MIT
12 | */
13 |
14 | namespace Interfax;
15 |
16 | use Doctrine\Instantiator\Exception\InvalidArgumentException;
17 |
18 | class File
19 | {
20 | /**
21 | * @var GenericFactory
22 | */
23 | private $factory;
24 | /**
25 | * @var Client
26 | */
27 | protected $client;
28 |
29 | protected $headers = [];
30 | protected $mime_type;
31 | protected $name;
32 | protected $body;
33 | protected $size;
34 | private $chunk_size;
35 | protected static $DEFAULT_CHUNK_SIZE = 1048576; // 1024*1024
36 |
37 | /**
38 | * File constructor.
39 | * @param $location
40 | * @param array $params
41 | * @throws \InvalidArgumentException
42 | */
43 | public function __construct(Client $client, $location, $params = [], GenericFactory $factory = null)
44 | {
45 | $this->client = $client;
46 | if ($factory === null) {
47 | $factory = new GenericFactory();
48 | }
49 |
50 | $this->factory = $factory;
51 |
52 | if (is_resource($location)) {
53 | $this->initialiseParams($params);
54 | $this->initialiseFromResource($location);
55 | } elseif (preg_match('/^https?:\/\//', $location)) {
56 | $this->initialiseFromUri($location);
57 | } else {
58 | $this->initialiseParams($params);
59 | $this->initialiseFromPath($location);
60 | }
61 | }
62 |
63 | /**
64 | * @param array $params
65 | */
66 | protected function initialiseParams($params = [])
67 | {
68 | if (array_key_exists('mime_type', $params)) {
69 | $this->setMimeType($params['mime_type']);
70 | }
71 |
72 | if (array_key_exists('name', $params)) {
73 | $this->name = $params['name'];
74 | }
75 |
76 | if (array_key_exists('chunk_size', $params)) {
77 | $this->chunk_size = $params['chunk_size'];
78 | } else {
79 | $this->chunk_size = static::$DEFAULT_CHUNK_SIZE;
80 | }
81 |
82 | if (array_key_exists('size', $params)) {
83 | $this->size = $params['size'];
84 | }
85 | }
86 |
87 | /**
88 | * @param $mime_type
89 | */
90 | public function setMimeType($mime_type)
91 | {
92 | $this->headers = [
93 | 'Content-Type' => $mime_type
94 | ];
95 | $this->mime_type = $mime_type;
96 | }
97 |
98 | protected function initialiseFromResource($resource)
99 | {
100 | $meta = stream_get_meta_data($resource);
101 | if (strpos($meta['mode'], 'r') === false) {
102 | throw new \InvalidArgumentException(
103 | 'Resource not opened with valid mode (r) for ' . __CLASS__
104 | );
105 | }
106 | $missing = [];
107 | foreach (['name', 'mime_type'] as $required) {
108 | if (!$this->$required) {
109 | $missing[] = $required;
110 | }
111 | }
112 | if (count($missing)) {
113 | throw new \InvalidArgumentException(
114 | 'Required parameters "' . implode(', ', $missing) . '" not set for resource initialisation of ' . __CLASS__
115 | );
116 | }
117 |
118 | if ($this->size && $this->size > $this->chunk_size) {
119 | $this->initialiseFromLargeResource($resource);
120 | } else {
121 | $this->body = $resource;
122 | }
123 | }
124 |
125 | /**
126 | * Simple abstraction to initialise a document for the given resource
127 | *
128 | * @param $resource
129 | * @return Document
130 | */
131 | private function createDocumentFromResource($resource)
132 | {
133 | $document = $this->client->documents->create($this->name, $this->size);
134 | $current = 0;
135 | while (!feof($resource)) {
136 | $chunk = fread($resource, $this->chunk_size);
137 | $end = $current + strlen($chunk);
138 | $document->upload($current, $end - 1, $chunk);
139 | $current = $end;
140 | }
141 | return $document;
142 | }
143 |
144 | /**
145 | * Use the given resource to create a Document on the Interfax server for this file.
146 | *
147 | * @param $resource
148 | */
149 | protected function initialiseFromLargeResource($resource)
150 | {
151 | $document = $this->createDocumentFromResource($resource);
152 | $this->initialiseFromUri($document->getHeaderLocation());
153 | }
154 |
155 | /**
156 | * @param $location
157 | * @throws \InvalidArgumentException
158 | */
159 | protected function initialiseFromPath($location)
160 | {
161 | if (!file_exists($location)) {
162 | throw new \InvalidArgumentException(
163 | $location . ' not found. File must exists on filesystem to construct ' . __CLASS__
164 | );
165 | }
166 |
167 | if (!$this->name) {
168 | $this->name = basename($location);
169 | }
170 | if (!$this->size) {
171 | $this->size = filesize($location);
172 | }
173 |
174 | if ($this->size > $this->chunk_size) {
175 | $this->initialiseFromLargeFile($location);
176 | } else {
177 | if (!$this->mime_type) {
178 | $finfo = finfo_open(FILEINFO_MIME_TYPE);
179 | $this->setMimeType(finfo_file($finfo, $location));
180 | }
181 |
182 | $this->body = fopen($location, 'r');
183 | }
184 | }
185 |
186 | /**
187 | * @param $location
188 | */
189 | protected function initialiseFromLargeFile($location)
190 | {
191 | $stream = fopen($location, 'rb');
192 | $document = $this->createDocumentFromResource($stream);
193 | fclose($stream);
194 |
195 | $this->initialiseFromUri($document->getHeaderLocation());
196 | }
197 |
198 | /**
199 | * @param $location
200 | */
201 | protected function initialiseFromUri($location)
202 | {
203 | $this->headers = [
204 | 'Content-Location' => $location
205 | ];
206 | $this->body = null;
207 | }
208 |
209 | /**
210 | * @return string
211 | */
212 | public function getHeader()
213 | {
214 | return $this->headers;
215 | }
216 |
217 | /**
218 | * @return string
219 | */
220 | public function getName()
221 | {
222 | return $this->name;
223 | }
224 |
225 | /**
226 | * @return mixed
227 | */
228 | public function getBody()
229 | {
230 | return $this->body;
231 | }
232 | }
233 |
--------------------------------------------------------------------------------
/src/Interfax/GenericFactory.php:
--------------------------------------------------------------------------------
1 |
10 | * @author Mike Smith
11 | * @copyright Copyright (c) 2016, InterFAX
12 | * @license MIT
13 | */
14 |
15 | namespace Interfax;
16 |
17 | class GenericFactory
18 | {
19 | public function instantiateClass($classname, $args = [])
20 | {
21 | if (count($args)) {
22 | $reflect = new \ReflectionClass($classname);
23 |
24 | return $reflect->newInstanceArgs($args);
25 | } else {
26 | return new $classname();
27 | }
28 | }
29 | }
30 |
--------------------------------------------------------------------------------
/src/Interfax/Image.php:
--------------------------------------------------------------------------------
1 |
10 | * @author Mike Smith
11 | * @copyright Copyright (c) 2016, InterFAX
12 | * @license MIT
13 | */
14 |
15 | namespace Interfax;
16 |
17 | use GuzzleHttp\Psr7\Stream;
18 | use RuntimeException;
19 |
20 | /**
21 | * Class Image
22 | *
23 | * Simple class to accept a response stream and allow content to be saved to a file
24 | *
25 | * @package Interfax
26 | */
27 | class Image
28 | {
29 | /**
30 | * @var Stream
31 | */
32 | private $stream;
33 |
34 | public function __construct(Stream $stream)
35 | {
36 | $this->stream = $stream;
37 | }
38 |
39 | /**
40 | * Note a return of false does not indicate that a file has not been created or written to,
41 | * just that it failed at some point.
42 | *
43 | * @param $path
44 | * @return bool
45 | * @throws \RuntimeException
46 | */
47 | public function save($path)
48 | {
49 | $handle = fopen($path, 'w');
50 |
51 | if (!$handle) {
52 | throw new \RuntimeException("Could not open {$path} for saving");
53 | }
54 |
55 | try {
56 | while (!$this->stream->eof()) {
57 | // TODO consider chunking size configuration
58 | fwrite($handle, $this->stream->read(1024 * 1024));
59 | }
60 | } catch (\RuntimeException $e) {
61 | // try to at least tidy up the resource
62 | fclose($handle);
63 | throw $e;
64 | }
65 |
66 | return fclose($handle);
67 | }
68 | }
69 |
--------------------------------------------------------------------------------
/src/Interfax/Inbound.php:
--------------------------------------------------------------------------------
1 |
10 | * @author Mike Smith
11 | * @copyright Copyright (c) 2016, InterFAX
12 | * @license MIT
13 | */
14 |
15 | namespace Interfax;
16 |
17 | use Interfax\Exception\RequestException;
18 |
19 | class Inbound
20 | {
21 | /**
22 | * @var Client
23 | */
24 | protected $client;
25 |
26 | /**
27 | * @var GenericFactory
28 | */
29 | protected $factory;
30 |
31 | /**
32 | * Inbound constructor.
33 | *
34 | * @param Client $client
35 | * @param GenericFactory|null $factory
36 | */
37 | public function __construct(Client $client, GenericFactory $factory = null)
38 | {
39 | $this->client = $client;
40 | if ($factory === null) {
41 | $factory = new GenericFactory();
42 | }
43 | $this->factory = $factory;
44 | }
45 |
46 | /**
47 | * Retrieve a list of incoming faxes for the Client account.
48 | *
49 | * @param array $query_params
50 | * @return Inbound\Fax[]
51 | * @throws \RuntimeException
52 | */
53 | public function incoming($query_params = [])
54 | {
55 | $params = [
56 | 'query' => $query_params
57 | ];
58 |
59 | $json = $this->client->get('/inbound/faxes', $params);
60 |
61 | if (is_array($json)) {
62 | $result = [];
63 | foreach ($json as $incoming) {
64 | $id = $incoming['messageId'];
65 | $result[] = $this->factory->instantiateClass('Interfax\Inbound\Fax', [$this->client, $id, $incoming]);
66 | }
67 | return $result;
68 | }
69 |
70 | throw new \RuntimeException('A reasonable but unhandled response was received');
71 | }
72 |
73 | /**
74 | * Search for an incoming fax with the given id.
75 | *
76 | * @param $id
77 | * @return \Interfax\Inbound\Fax|null
78 | * @throws RequestException
79 | * @throws \RuntimeException
80 | */
81 | public function find($id)
82 | {
83 | try {
84 | $json = $this->client->get('/inbound/faxes/' . $id);
85 |
86 | if (is_array($json)) {
87 | return $this->factory->instantiateClass('Interfax\Inbound\Fax', [$this->client, $id, $json]);
88 | }
89 | } catch (RequestException $e) {
90 | //TODO: test me
91 | if ((int) $e->getStatusCode() === 404) {
92 | return null;
93 | }
94 | throw $e;
95 | }
96 |
97 | throw new \RuntimeException('A reasonable but unhandled response was received');
98 | }
99 | }
100 |
--------------------------------------------------------------------------------
/src/Interfax/Inbound/Fax.php:
--------------------------------------------------------------------------------
1 |
10 | * @author Mike Smith
11 | * @copyright Copyright (c) 2016, InterFAX
12 | * @license MIT
13 | */
14 |
15 | namespace Interfax\Inbound;
16 |
17 | use Interfax\Client;
18 | use Interfax\Exception\RequestException;
19 | use Interfax\GenericFactory;
20 | use Interfax\Resource;
21 |
22 | class Fax extends Resource
23 | {
24 | protected static $resource_uri_stem = '/inbound/faxes/';
25 |
26 | /**
27 | * @param bool $unread
28 | * @return self
29 | * @throws RequestException
30 | */
31 | protected function mark($unread = true)
32 | {
33 | $this->client->post($this->resource_uri . '/mark', ['query' => ['unread' => $unread]]);
34 |
35 | return $this;
36 | }
37 |
38 | /**
39 | * @return self
40 | * @throws RequestException
41 | */
42 | public function markRead()
43 | {
44 | return $this->mark(false);
45 | }
46 |
47 | /**
48 | * @return self
49 | * @throws RequestException
50 | */
51 | public function markUnread()
52 | {
53 | return $this->mark(true);
54 | }
55 |
56 | /**
57 | * @param string $email
58 | * @return self
59 | * @throws RequestException
60 | */
61 | public function resend($email = null)
62 | {
63 | $params = [];
64 | if ($email !== null) {
65 | $params['query'] = ['email' => $email];
66 | }
67 | $this->client->post($this->resource_uri . '/resend', $params);
68 |
69 | return $this;
70 | }
71 |
72 | /**
73 | * @return \Interfax\Image
74 | * @throws RequestException
75 | */
76 | public function image()
77 | {
78 | $response = $this->client->get($this->resource_uri . '/image');
79 |
80 | return $this->factory->instantiateClass('Interfax\Image', [$response]);
81 | }
82 |
83 | /**
84 | * Returns an array of hasharrays with the structure returned from the emails endpoint.
85 | *
86 | * @return array
87 | * @throws RequestException
88 | */
89 | public function emails()
90 | {
91 | return $this->client->get($this->resource_uri . '/emails');
92 | }
93 | }
94 |
--------------------------------------------------------------------------------
/src/Interfax/Outbound.php:
--------------------------------------------------------------------------------
1 |
10 | * @author Mike Smith
11 | * @copyright Copyright (c) 2016, InterFAX
12 | * @license MIT
13 | */
14 |
15 | namespace Interfax;
16 |
17 | use Interfax\Exception\RequestException;
18 | use Interfax\Outbound\Fax;
19 |
20 | class Outbound
21 | {
22 | /**
23 | * @var GenericFactory
24 | */
25 | private $factory;
26 |
27 | protected $client;
28 |
29 | public function __construct(Client $client, GenericFactory $factory = null)
30 | {
31 | $this->client = $client;
32 | if ($factory === null) {
33 | $factory = new GenericFactory();
34 | }
35 | $this->factory = $factory;
36 | }
37 |
38 |
39 |
40 | /**
41 | * @param array $definitions
42 | * @return Fax[]
43 | * @throws \InvalidArgumentException
44 | */
45 | protected function createFaxes($definitions)
46 | {
47 | $res = [];
48 | foreach ($definitions as $f_data) {
49 | if (array_key_exists('id', $f_data)) {
50 | $res[] = $this->factory->instantiateClass(
51 | 'Interfax\Outbound\Fax',
52 | [$this->client, $f_data['id'], $f_data]
53 | );
54 | } else {
55 | throw new \InvalidArgumentException('No id attribute found in fax definition');
56 | }
57 | }
58 |
59 | return $res;
60 | }
61 |
62 | /**
63 | * @param array $ids
64 | * @return Fax[]
65 | * @throws \InvalidArgumentException
66 | * @throws RequestException
67 | */
68 | public function completed($ids = [])
69 | {
70 | $params = [];
71 | if (count($ids) === 0) {
72 | throw new \InvalidArgumentException('Must provide at least one id for completed request');
73 | }
74 |
75 | $params['query'] = ['ids' => implode(',', $ids)];
76 |
77 | $json = $this->client->get('/outbound/faxes/completed', $params);
78 | return $this->createFaxes($json);
79 | }
80 |
81 | /**
82 | * @param array $query_params
83 | * @return Outbound\Fax[]
84 | * @internal param $params
85 | */
86 | public function recent($query_params = [])
87 | {
88 | $params = [];
89 | if (count($query_params)) {
90 | $params = ['query' => $query_params];
91 | }
92 | return $this->createFaxes($this->client->get('/outbound/faxes', $params));
93 | }
94 |
95 |
96 | /**
97 | * @param $id
98 | * @param null $fax_number
99 | * @return mixed
100 | * @throws RequestException
101 | */
102 | public function resend($id, $fax_number = null)
103 | {
104 | $fax = $this->factory->instantiateClass('Interfax\Outbound\Fax', [$this->client, $id]);
105 |
106 | return $fax->resend($fax_number);
107 | }
108 |
109 | /**
110 | * Get an individual Fax resource for the given $id.
111 | *
112 | * @param $id
113 | * @return null|Interfax\Outbound\Fax
114 | */
115 | public function find($id)
116 | {
117 | try {
118 | $response = $this->client->get('/outbound/faxes/' . $id);
119 |
120 | if (is_array($response) && array_key_exists('id', $response)) {
121 | return $this->factory->instantiateClass(
122 | 'Interfax\Outbound\Fax',
123 | [$this->client, $response['id'], $response]
124 | );
125 | }
126 | } catch (\RuntimeException $e) {
127 | if ((int) $e->getStatusCode() === 404) {
128 | return null;
129 | }
130 | throw $e;
131 | }
132 |
133 | throw new \RuntimeException('A reasonable but unhandled response was received');
134 | }
135 |
136 | /**
137 | * @param array $params
138 | * @return Outbound\Fax[]
139 | * @throws \InvalidArgumentException
140 | * @throws RequestException
141 | */
142 | public function search($params = [])
143 | {
144 | return $this->createFaxes($this->client->get('/outbound/search', ['query' => $params]));
145 | }
146 | }
147 |
--------------------------------------------------------------------------------
/src/Interfax/Outbound/Delivery.php:
--------------------------------------------------------------------------------
1 |
10 | * @copyright Copyright (c) 2016, InterFAX
11 | * @license MIT
12 | */
13 |
14 | namespace Interfax\Outbound;
15 |
16 | use Interfax\Client;
17 | use Interfax\Exception\RequestException;
18 | use Interfax\File;
19 | use Interfax\GenericFactory;
20 |
21 | class Delivery
22 | {
23 | protected static $required_qparams = ['faxNumber'];
24 | protected $query_params = [];
25 | /**
26 | * @var File[]
27 | */
28 | protected $files = [];
29 | /**
30 | * @var \Interfax\Client
31 | */
32 | private $client;
33 |
34 | /**
35 | * Delivery constructor.
36 | *
37 | * @param \Interfax\Client $client
38 | * @param array $params
39 | * @param GenericFactory $factory
40 | * @throws \InvalidArgumentException
41 | */
42 | public function __construct(Client $client, $params = [], GenericFactory $factory = null)
43 | {
44 | $this->client = $client;
45 |
46 | $missing_qparams = array_diff(static::$required_qparams, array_keys($params));
47 |
48 | if (count($missing_qparams)) {
49 | throw new \InvalidArgumentException('missing required query parameters ' . implode(', ', $missing_qparams));
50 | }
51 |
52 | if ($factory === null) {
53 | $factory = new GenericFactory();
54 | }
55 |
56 | $this->factory = $factory;
57 |
58 | $this->resolveFiles($params);
59 |
60 | foreach ($params as $k => $v) {
61 | $this->query_params[$k] = $v;
62 | }
63 | }
64 |
65 | /**
66 | * Runs through the file/files parameter of params and instantiates File objects for delivery.
67 | *
68 | * @param $params
69 | * @throws \InvalidArgumentException
70 | */
71 | protected function resolveFiles(&$params)
72 | {
73 | // normalise to a single array of files
74 | $files = [];
75 | if (isset($params['file'])) {
76 | if (isset($params['files'])) {
77 | throw new \InvalidArgumentException('Can only provide file or files for ' . __CLASS__);
78 | }
79 | $files[] = $params['file'];
80 | unset($params['file']);
81 | } elseif (isset($params['files'])) {
82 | $files = $params['files'];
83 | unset($params['files']);
84 | } else {
85 | throw new \InvalidArgumentException('Must provide a file or files for Delivery');
86 | }
87 |
88 | // create file objects where necessary
89 | foreach ($files as $f) {
90 | if (is_object($f)) {
91 | $cls = get_class($f);
92 | if (is_a($f, 'Interfax\File')) {
93 | $this->files[] = $f;
94 | } elseif (is_a($f, 'Interfax\Document')) {
95 | $this->files[] = $this->factory->instantiateClass(
96 | 'Interfax\File',
97 | [$this->client, $f->getHeaderLocation()]
98 | );
99 | } else {
100 | throw new \InvalidArgumentException(
101 | 'File objects must be Interfax\File or Interfax\Document objects for Delivery. not ' . $cls
102 | );
103 | }
104 | } elseif (is_array($f)) {
105 | $args = array_merge([$this->client], $f);
106 | $this->files[] = $this->factory->instantiateClass('Interfax\File', $args);
107 | } else {
108 | // assumed to be a path
109 | $this->files[] = $this->factory->instantiateClass('Interfax\File', [$this->client, $f]);
110 | }
111 | }
112 | }
113 |
114 | /**
115 | * @return string
116 | */
117 | public function getMultipart()
118 | {
119 | $multipart = [];
120 | foreach ($this->files as $i => $file) {
121 | $multipart[] = [
122 | 'name' => 'file' . $i,
123 | 'filename' => urlencode($file->getName()),
124 | 'contents' => $file->getBody(),
125 | 'headers' => $file->getHeader(),
126 | ];
127 | }
128 | return $multipart;
129 | }
130 |
131 | /**
132 | * @return Fax
133 | * @throws \InvalidArgumentException
134 | * @throws RequestException
135 | */
136 | public function send()
137 | {
138 | $params = [
139 | 'query' => $this->query_params,
140 | ];
141 |
142 | if (count($this->files) > 1) {
143 | $location = $this->client->post('/outbound/faxes', $params, $this->getMultipart());
144 | } else {
145 | $params['headers'] = $this->files[0]->getHeader();
146 | $params['body'] = $this->files[0]->getBody();
147 | $location = $this->client->post('/outbound/faxes', $params);
148 | }
149 |
150 | // retrieve ID (last element of location path) for outbound fax object
151 | $path = parse_url($location, PHP_URL_PATH);
152 | $bits = explode('/', $path);
153 | return $this->factory->instantiateClass('Interfax\Outbound\Fax', [$this->client, array_pop($bits)]);
154 | }
155 | }
156 |
--------------------------------------------------------------------------------
/src/Interfax/Outbound/Fax.php:
--------------------------------------------------------------------------------
1 |
10 | * @copyright Copyright (c) 2016, InterFAX
11 | * @license MIT
12 | */
13 |
14 | namespace Interfax\Outbound;
15 |
16 | use Interfax\Client;
17 | use Interfax\Exception\RequestException;
18 | use Interfax\Image;
19 | use Interfax\Resource;
20 |
21 | class Fax extends Resource
22 | {
23 | protected static $resource_uri_stem = '/outbound/faxes/';
24 |
25 | /**
26 | * @return string
27 | */
28 | public function getLocation()
29 | {
30 | return $this->resource_uri;
31 | }
32 |
33 | /**
34 | * Resend the fax, possibly to a new fax number
35 | *
36 | * @param string $fax_number
37 | * @return $this
38 | * @throws RequestException
39 | */
40 | public function resend($fax_number = null)
41 | {
42 | $params = [];
43 | if ($fax_number !== null) {
44 | $params['query'] = ['faxNumber' => $fax_number];
45 | }
46 |
47 | $location = $this->client->post($this->resource_uri . '/resend', $params);
48 |
49 | $path = parse_url($location, PHP_URL_PATH);
50 | $bits = explode('/', $path);
51 | return $this->factory->instantiateClass(__CLASS__, [$this->client, array_pop($bits)]);
52 | }
53 |
54 | /**
55 | * @return self
56 | * @throws RequestException
57 | */
58 | public function cancel()
59 | {
60 | $this->client->post($this->resource_uri . '/cancel');
61 |
62 | return $this;
63 | }
64 |
65 | /**
66 | * @return self
67 | * @throws RequestException
68 | */
69 | public function hide()
70 | {
71 | $this->client->post($this->resource_uri . '/hide');
72 |
73 | return $this;
74 | }
75 |
76 | /**
77 | * @return Image
78 | * @throws RequestException
79 | */
80 | public function image()
81 | {
82 | $response = $this->client->get($this->resource_uri . '/image');
83 |
84 | return $this->factory->instantiateClass('Interfax\Image', [$response]);
85 | }
86 | }
87 |
--------------------------------------------------------------------------------
/src/Interfax/Resource.php:
--------------------------------------------------------------------------------
1 |
10 | * @author Mike Smith
11 | * @copyright Copyright (c) 2016, InterFAX
12 | * @license MIT
13 | */
14 |
15 | namespace Interfax;
16 |
17 | use Interfax\Exception\RequestException;
18 |
19 | /**
20 | * Class Resource
21 | *
22 | * Base Resource Class to be used for resource classes that are represented by specific endpoints on the API.
23 | *
24 | * @package Interfax
25 | */
26 | abstract class Resource
27 | {
28 | /**
29 | * @var GenericFactory
30 | */
31 | protected $factory;
32 |
33 | /**
34 | * @var Client
35 | */
36 | protected $client;
37 | /**
38 | * Base URI used for carrying out actions on the resource.
39 | *
40 | * @var string
41 | */
42 | protected $resource_uri;
43 | /**
44 | * Stores the internal properties of the resource.
45 | *
46 | * @var array
47 | */
48 | protected $record = [];
49 |
50 | /**
51 | * Should be overridden in inheriting class
52 | *
53 | * @var
54 | */
55 | protected static $resource_uri_stem;
56 |
57 | /**
58 | * Resource constructor.
59 | *
60 | * @param Client $client
61 | * @param $id
62 | * @param array $definition
63 | * @param GenericFactory|null $factory
64 | */
65 | public function __construct(Client $client, $id, $definition = [], GenericFactory $factory = null)
66 | {
67 | $this->client = $client;
68 |
69 | $this->resource_uri = static::$resource_uri_stem . $id;
70 | $this->record['id'] = $id;
71 |
72 | foreach ($definition as $k => $v) {
73 | $this->record[$k] = $v;
74 | }
75 |
76 | if ($factory === null) {
77 | $factory = new GenericFactory();
78 | }
79 | $this->factory = $factory;
80 | }
81 |
82 | /**
83 | * @param $name
84 | * @return mixed|null
85 | */
86 | public function __get($name)
87 | {
88 | if ($name === 'location') {
89 | return $this->resource_uri;
90 | }
91 |
92 | if (array_key_exists($name, $this->record)) {
93 | return $this->record[$name];
94 | }
95 |
96 | return null;
97 | }
98 |
99 | /**
100 | * @return array
101 | */
102 | public function attributes()
103 | {
104 | return $this->record;
105 | }
106 |
107 | /**
108 | * @return self
109 | * @throws RequestException
110 | */
111 | public function refresh()
112 | {
113 | $response = $this->client->get($this->resource_uri);
114 | $this->record = $response;
115 | return $this;
116 | }
117 | }
118 |
--------------------------------------------------------------------------------
/tests/Interfax/BaseTest.php:
--------------------------------------------------------------------------------
1 |
10 | * @author Mike Smith
11 | * @copyright Copyright (c) 2016, InterFAX
12 | * @license MIT
13 | */
14 |
15 | namespace Test\Interfax;
16 |
17 | use GuzzleHttp\Client as GuzzleClient;
18 | use GuzzleHttp\Handler\MockHandler;
19 | use GuzzleHttp\HandlerStack;
20 | use GuzzleHttp\Middleware;
21 | use Interfax\Client;
22 | use PHPUnit\Framework\TestCase;
23 |
24 | /**
25 | * Class BaseTest
26 | *
27 | * @package Interfax
28 | */
29 | abstract class BaseTest extends TestCase
30 | {
31 | private function getExpectedClassForFactory($obj)
32 | {
33 | $cls = get_class($obj);
34 | if (strpos($cls, 'Mock') === 0) {
35 | $r = new \ReflectionClass($obj);
36 | $cls = $r->getParentClass()->name;
37 | }
38 | return $cls;
39 | }
40 |
41 | /**
42 | * Provides a mock generic factory for handling instantiation of objects within the code structure
43 | *
44 | * @param array $returns
45 | * @return \PHPUnit_Framework_MockObject_MockObject
46 | */
47 | protected function getFactory($returns = [])
48 | {
49 | $factory = $this->getMockBuilder('Interfax\GenericFactory')
50 | ->onlyMethods(['instantiateClass'])
51 | ->getMock();
52 |
53 | $consecutiveReturns = array_map(
54 | function ($args) {
55 | return is_array($args)
56 | ? $args[0]
57 | : $args;
58 | },
59 | $returns
60 | );
61 |
62 | $factory->method('instantiateClass')
63 | ->will($this->onConsecutiveCalls(...$consecutiveReturns));
64 |
65 | return $factory;
66 | }
67 |
68 | // Basic wrapper to allow mocking out of different classes a Client might need to instantiate
69 | protected function getClientWithFactory($returns = [])
70 | {
71 | $factory = $this->getFactory($returns);
72 |
73 | return new Client(['username' => 'test_user', 'password' => 'test_password'], $factory);
74 | }
75 |
76 | protected function constructGuzzleWithResponses(&$container, $responses = [])
77 | {
78 | $mock = new MockHandler($responses);
79 |
80 | $stack = HandlerStack::create($mock);
81 |
82 | $history = Middleware::history($container);
83 |
84 | $stack->push($history);
85 |
86 | $guzzle = new GuzzleClient(['handler' => $stack]);
87 |
88 | return $guzzle;
89 | }
90 |
91 | // wrapper to allow "simple" inspection of the requests sent to the API endpoints
92 | protected function getClientWithResponses(&$container, $responses = [])
93 | {
94 | return $this->getClientWithFactory([$this->constructGuzzleWithResponses($container, $responses)]);
95 | }
96 | }
97 |
--------------------------------------------------------------------------------
/tests/Interfax/ClientTest.php:
--------------------------------------------------------------------------------
1 |
10 | * @author Mike Smith
11 | * @copyright Copyright (c) 2016, InterFAX
12 | * @license MIT
13 | */
14 |
15 | namespace Test\Interfax;
16 |
17 | use GuzzleHttp\Client as GuzzleClient;
18 | use GuzzleHttp\HandlerStack;
19 | use GuzzleHttp\Middleware;
20 | use GuzzleHttp\Handler\MockHandler;
21 | use GuzzleHttp\Psr7\Response;
22 | use Interfax\Client;
23 |
24 | class ClientTest extends BaseTest
25 | {
26 | protected function getClient($properties = [])
27 | {
28 | $client = new Client(['username' => 'test_user', 'password' => 'test_password']);
29 | foreach ($properties as $k => $v) {
30 | $client->$k = $v;
31 | }
32 |
33 | return $client;
34 | }
35 |
36 | public function test_constructing_with_variables_overrides_env()
37 | {
38 | $current_username = getenv('INTERFAX_USERNAME');
39 | $current_password = getenv('INTERFAX_PASSWORD');
40 | putenv('INTERFAX_USERNAME=env_username');
41 | putenv('INTERFAX_PASSWORD=env_password');
42 |
43 | $client = new Client(['username' => 'override_username', 'password' => 'override_password']);
44 | $this->assertEquals('override_username', $client->username);
45 | $this->assertEquals('override_password', $client->password);
46 |
47 | putenv('INTERFAX_USERNAME=' . $current_username);
48 | putenv('INTERFAX_PASSWORD=' . $current_password);
49 | }
50 |
51 | public function test_constructing_without_variables_uses_env()
52 | {
53 | $current_username = getenv('INTERFAX_USERNAME');
54 | $current_password = getenv('INTERFAX_PASSWORD');
55 | putenv('INTERFAX_USERNAME=env_username');
56 | putenv('INTERFAX_PASSWORD=env_password');
57 |
58 | $client = new Client();
59 | $this->assertEquals('env_username', $client->username);
60 | $this->assertEquals('env_password', $client->password);
61 |
62 | putenv('INTERFAX_USERNAME=' . $current_username);
63 | putenv('INTERFAX_PASSWORD=' . $current_password);
64 | }
65 |
66 | public function test_construction_should_fail_without_credentials()
67 | {
68 | $this->expectException('InvalidArgumentException');
69 | $client = new Client();
70 | }
71 |
72 | public function test_post_success()
73 | {
74 | $mock = new MockHandler([
75 | new Response(201, ['Location' => 'http://myfax.resource.uri'], '')
76 | ]);
77 | $stack = HandlerStack::create($mock);
78 |
79 | $container = [];
80 | $history = Middleware::history($container);
81 |
82 | $stack->push($history);
83 |
84 | $guzzle = new GuzzleClient(['handler' => $stack]);
85 |
86 | $client = $this->getClientWithFactory([$guzzle]);
87 |
88 | $response = $client->post('test/uri', ['query' => ['foo' => 'bar']], [['name' => 'doc1', 'headers' => ['X-Bar' => 'FOO'], 'contents' => 'testString']]);
89 |
90 | $this->assertEquals('http://myfax.resource.uri', $response);
91 | $this->assertCount(1, $container);
92 | $transaction = $container[0];
93 | $this->assertEquals('POST', $transaction['request']->getMethod());
94 | $this->assertNotNull($transaction['options']['auth']);
95 | $this->assertEquals('foo=bar', $transaction['request']->getUri()->getQuery());
96 | $this->assertEquals('test/uri', $transaction['request']->getUri()->getPath());
97 | $this->assertEquals(1, preg_match('/testString/', $transaction['request']->getBody()));
98 | $this->assertEquals(1, preg_match('/InterFAX PHP/', $transaction['request']->getHeaderLine('User-Agent')));
99 | }
100 |
101 | public function test_get_success()
102 | {
103 | $mock = new MockHandler([
104 | new Response(200, ['Content-Type' => 'text/json'], '{"id":279415116,"uri":"https://rest.interfax.net/outbound/faxes/279415116","status":0}')
105 | ]);
106 | $stack = HandlerStack::create($mock);
107 |
108 | $container = [];
109 | $history = Middleware::history($container);
110 |
111 | $stack->push($history);
112 |
113 | $guzzle = new GuzzleClient(['handler' => $stack]);
114 |
115 | $client = $this->getClientWithFactory([$guzzle]);
116 |
117 | $response = $client->get('test/uri', ['query' => ['foo' => 'bar']]);
118 | $this->assertTrue(is_array($response));
119 |
120 | $this->assertCount(1, $container);
121 | $transaction = $container[0];
122 | $this->assertEquals('GET', $transaction['request']->getMethod());
123 | $this->assertNotNull($transaction['options']['auth']);
124 | $this->assertEquals('foo=bar', $transaction['request']->getUri()->getQuery());
125 | $this->assertEquals('test/uri', $transaction['request']->getUri()->getPath());
126 | $this->assertEquals(1, preg_match('/InterFAX PHP/', $transaction['request']->getHeaderLine('User-Agent')));
127 | }
128 |
129 | public function test_delete_success()
130 | {
131 | $container = [];
132 | $client = $this->getClientWithResponses(
133 | $container,
134 | [
135 | new Response(200)
136 | ]
137 | );
138 |
139 | $response = $client->delete('test/uri');
140 | $this->assertEquals(200, $response);
141 | $transaction = $container[0];
142 | $this->assertEquals('DELETE', $transaction['request']->getMethod());
143 | $this->assertNotNull($transaction['options']['auth']);
144 | $this->assertEquals(1, preg_match('/InterFAX PHP/', $transaction['request']->getHeaderLine('User-Agent')));
145 | }
146 |
147 | public function test_deliver_user_delivery_class_to_send_fax()
148 | {
149 | $delivery = $this->getMockBuilder('Interfax\Outbound\Delivery')
150 | ->disableOriginalConstructor()
151 | ->setMethods(array('send'))
152 | ->getMock();
153 |
154 | $fake_return = 'test';
155 | $delivery->expects($this->once())
156 | ->method('send')
157 | ->will($this->returnValue($fake_return));
158 |
159 | $client = $this->getClientWithFactory([$delivery]);
160 |
161 | $params = ['foo' => 'bar'];
162 |
163 | $this->assertEquals($fake_return, $client->deliver($params));
164 | }
165 |
166 | public function test_get_balance()
167 | {
168 | $client = $this->getMockBuilder('Interfax\Client')
169 | ->disableOriginalConstructor()
170 | ->setMethods(['get'])
171 | ->getMock();
172 |
173 | $client->expects($this->once())
174 | ->method('get')
175 | ->with('/accounts/self/ppcards/balance')
176 | ->will($this->returnValue('4.35'));
177 |
178 | $this->assertEquals('4.35', $client->getBalance());
179 | }
180 |
181 | public function test_outbound_property_returns_outbound_instance()
182 | {
183 | $outbound = $this->getMockBuilder('Interfax\Outbound')
184 | ->disableOriginalConstructor()
185 | ->getMock();
186 |
187 | $client = $this->getClientWithFactory([$outbound]);
188 |
189 | $this->assertEquals($outbound, $client->outbound);
190 | }
191 |
192 | public function test_inbound_property()
193 | {
194 | $client = $this->getClient();
195 |
196 | $this->assertInstanceOf('Interfax\Inbound', $client->inbound);
197 | }
198 |
199 | public function test_documents_property()
200 | {
201 | $client = $this->getClient();
202 |
203 | $this->assertInstanceOf('Interfax\Documents', $client->documents);
204 | }
205 |
206 | public function test_boolean_parsing_for_query_string()
207 | {
208 | $mock = new MockHandler([
209 | new Response(201, ['Location' => 'http://myfax.resource.uri'], '')
210 | ]);
211 | $stack = HandlerStack::create($mock);
212 |
213 | $container = [];
214 | $history = Middleware::history($container);
215 |
216 | $stack->push($history);
217 |
218 | $guzzle = new GuzzleClient(['handler' => $stack]);
219 |
220 | $client = $this->getClientWithFactory([$guzzle]);
221 |
222 | $response = $client->get('test/uri', ['query' => ['foo' => true, 'bar' => false]]);
223 |
224 | $this->assertEquals('http://myfax.resource.uri', $response);
225 | $this->assertEquals(1, count($container));
226 | $transaction = $container[0];
227 | $this->assertEquals('GET', $transaction['request']->getMethod());
228 | $this->assertEquals('foo=TRUE&bar=FALSE', $transaction['request']->getUri()->getQuery());
229 | $this->assertEquals('test/uri', $transaction['request']->getUri()->getPath());
230 | }
231 |
232 | public function test_getBaseUri()
233 | {
234 | $guzzle = new GuzzleClient(['base_uri' => 'http://test.foo.bar.com']);
235 | $client = $this->getClientWithFactory([$guzzle]);
236 | $this->assertEquals('http://test.foo.bar.com', $client->getBaseUri());
237 | }
238 |
239 | public function test_prevents_trailing_slash()
240 | {
241 | $client = new Client(['base_uri' => 'http://test.foo.com/', 'username' => 'foo', 'password' => 'bar']);
242 |
243 | $this->assertEquals('http://test.foo.com', $client->getBaseUri());
244 | }
245 |
246 | /**
247 | * Accept any 2xx status codes, throw an exception otherwise
248 | */
249 | public function test_response_status_parsing()
250 | {
251 | for ($i = 0; $i < 10; $i++) {
252 | $container = [];
253 | $client = $this->getClientWithResponses(
254 | $container,
255 | [
256 | new Response(rand(200, 299), [], 'foo')
257 | ]
258 | );
259 |
260 | $response = $client->get('test/uri', ['query' => ['foo' => true, 'bar' => false]]);
261 |
262 | $this->assertEquals('foo', $response);
263 | }
264 |
265 | for ($i = 0; $i < 10; $i++) {
266 | $status_code = rand(100, 550);
267 | if ($status_code >= 200 && $status_code <= 299) {
268 | $status_code += 100;
269 | }
270 |
271 | $container = [];
272 | $client = $this->getClientWithResponses(
273 | $container,
274 | [
275 | new Response($status_code, ['Content-type' => 'text/json'], 'foo')
276 | ]
277 | );
278 |
279 | $this->expectException('Interfax\Exception\RequestException');
280 |
281 | $response = $client->get('test/uri', ['query' => ['foo' => true, 'bar' => false]]);
282 | }
283 | }
284 | }
285 |
--------------------------------------------------------------------------------
/tests/Interfax/DocumentTest.php:
--------------------------------------------------------------------------------
1 |
10 | * @author Mike Smith
11 | * @copyright Copyright (c) 2016, InterFAX
12 | * @license MIT
13 | */
14 |
15 | namespace Test\Interfax;
16 |
17 | use GuzzleHttp\Psr7\Response;
18 | use Interfax\Document;
19 |
20 | class DocumentTest extends BaseTest
21 | {
22 | public function test_upload()
23 | {
24 | $container = [];
25 | $client = $this->getClientWithResponses(
26 | $container,
27 | [
28 | new Response(202, [], '')
29 | ]
30 | );
31 |
32 | $document = new Document($client, 42, ['id' => 42]);
33 |
34 | $this->assertEquals($document, $document->upload(0, 300, 'the quick brown fox'));
35 | $transaction = $container[0];
36 | $this->assertEquals('POST', $transaction['request']->getMethod());
37 | $this->assertEquals('/outbound/documents/42', $transaction['request']->getUri()->getPath());
38 | $this->assertEquals('', $transaction['request']->getUri()->getQuery());
39 | $this->assertEquals('bytes=0-300', $transaction['request']->getHeaderLine('Range'));
40 | }
41 |
42 | public function test_refresh()
43 | {
44 | $response = [
45 | 'userId' => 'nadya',
46 | 'fileName' => 'sampledoc.pdf',
47 | 'fileSize' => 82318,
48 | 'uploaded' => 0,
49 | 'uri' => 'https:/rest.interfax.net/outbound/documents/89a48657279d45429c646029bd9227e6',
50 | 'creationTime' => '2012-06-23T17:49:25',
51 | 'lastusageTime' => '2012-06-23T17:49:25',
52 | 'status' => 'Created',
53 | 'disposition' => 'SingleUse',
54 | 'sharing' => 'Private'
55 | ];
56 |
57 | $container = [];
58 | $client = $this->getClientWithResponses(
59 | $container,
60 | [
61 | new Response(200, ['Content-Type' => 'text/json'], json_encode($response))
62 | ]
63 | );
64 |
65 | $document = new Document($client, '89a48657279d45429c646029bd9227e6');
66 | $this->assertNull($document->status);
67 | $this->assertCount(0, $container);
68 | $this->assertInstanceOf('Interfax\Document', $document->refresh());
69 | $this->assertCount(1, $container);
70 | $transaction = $container[0];
71 | $this->assertEquals('GET', $transaction['request']->getMethod());
72 | $this->assertEquals('/outbound/documents/89a48657279d45429c646029bd9227e6', $transaction['request']->getUri()->getPath());
73 | $this->assertEquals('', $transaction['request']->getUri()->getQuery());
74 | $this->assertEquals($response, $document->attributes());
75 | }
76 |
77 | public function test_cancel()
78 | {
79 | $struct = $response = [
80 | 'userId' => 'nadya',
81 | 'fileName' => 'sampledoc.pdf',
82 | 'fileSize' => 82318,
83 | 'uploaded' => 0,
84 | 'uri' => 'https:/rest.interfax.net/outbound/documents/123124124',
85 | 'creationTime' => '2012-06-23T17:49:25',
86 | 'lastusageTime' => '2012-06-23T17:49:25',
87 | 'status' => 'Created',
88 | 'disposition' => 'SingleUse',
89 | 'sharing' => 'Private'
90 | ];
91 | $container = [];
92 | $client = $this->getClientWithResponses(
93 | $container,
94 | [
95 | new Response(200, [], '')
96 | ]
97 | );
98 |
99 | $document = new Document($client, '123124124', $struct);
100 | $this->assertEquals($document, $document->cancel());
101 | $this->assertCount(0, $document->attributes());
102 | $transaction = $container[0];
103 | $this->assertEquals('DELETE', $transaction['request']->getMethod());
104 | $this->assertEquals('/outbound/documents/123124124', $transaction['request']->getUri()->getPath());
105 | $this->assertEquals('', $transaction['request']->getUri()->getQuery());
106 | }
107 | }
108 |
--------------------------------------------------------------------------------
/tests/Interfax/DocumentsTest.php:
--------------------------------------------------------------------------------
1 |
10 | * @author Mike Smith
11 | * @copyright Copyright (c) 2016, InterFAX
12 | * @license MIT
13 | */
14 |
15 | namespace Test\Interfax;
16 |
17 | use GuzzleHttp\Psr7\Response;
18 | use Interfax\Documents;
19 |
20 | class DocumentsTest extends BaseTest
21 | {
22 | public function test_available()
23 | {
24 | // sample taken from docs
25 | $response = [
26 | [
27 | 'userId' => 'nadya',
28 | 'fileName' => 'sampledoc.pdf',
29 | 'fileSize' => 82318,
30 | 'uploaded' => 0,
31 | 'uri' => 'https://rest.interfax.net/outbound/documents/89a48657279d45429c646029bd9227e6',
32 | 'creationTime' => '2012-06-23T17:49:25',
33 | 'lastusageTime' => '2012-06-23T17:49:25',
34 | 'status' => 'Created'
35 | ],
36 | [
37 | 'userId' => 'nadya',
38 | 'fileName' => 'sampledoc.pdf',
39 | 'fileSize' => 82318,
40 | 'uploaded' => 0,
41 | 'uri' => 'https://rest.interfax.net/outbound/documents/89a48657279d45429c646029bd9227e6',
42 | 'creationTime' => '2012-06-23T17:49:25',
43 | 'lastusageTime' => '2012-06-23T17:49:25',
44 | 'status' => 'Created'
45 | ]
46 | ];
47 | $container = [];
48 | $client = $this->getClientWithResponses(
49 | $container,
50 | [
51 | new Response(200, ['Content-Type' => 'text/json'], json_encode($response))
52 | ]
53 | );
54 |
55 | $factory_returns = [
56 | $this->getMockBuilder('Interfax\Document')->disableOriginalConstructor()->getMock(), $this->getMockBuilder('Interfax\Document')->disableOriginalConstructor()->getMock()];
57 | $factory = $this->getFactory($factory_returns);
58 |
59 | $documents = new Documents($client, $factory);
60 |
61 | $this->assertEquals($factory_returns, $documents->available());
62 | $transaction = $container[0];
63 | $this->assertEquals('GET', $transaction['request']->getMethod());
64 | $this->assertEquals('/outbound/documents', $transaction['request']->getUri()->getPath());
65 | $this->assertEquals('', $transaction['request']->getUri()->getQuery());
66 | }
67 |
68 | public function test_available_with_params()
69 | {
70 | $container = [];
71 | $client = $this->getClientWithResponses(
72 | $container,
73 | [
74 | new Response(200, ['Content-Type' => 'text/json'], '[]')
75 | ]
76 | );
77 |
78 | $documents = new Documents($client);
79 |
80 | $this->assertEquals([], $documents->available(['limit' => 20, 'foo' => 'bar']));
81 | $transaction = $container[0];
82 | $this->assertEquals('GET', $transaction['request']->getMethod());
83 | $this->assertEquals('/outbound/documents', $transaction['request']->getUri()->getPath());
84 | $this->assertEquals('limit=20&foo=bar', $transaction['request']->getUri()->getQuery());
85 | }
86 |
87 | public function test_create_no_params()
88 | {
89 | $container = [];
90 | $client = $this->getClientWithResponses(
91 | $container,
92 | [
93 | new Response(201, ['Location' => 'http://mydoc.resource.uri/outbound/documents/21'], '')
94 | ]
95 | );
96 |
97 | $document = $this->getMockBuilder('Interfax\Document')
98 | ->disableOriginalConstructor()
99 | ->getMock();
100 |
101 | $factory = $this->getFactory([[$document, [$client, 21, ['id' => 21, 'size' => '200', 'name' => 'test.pdf']]]]);
102 |
103 | $documents = new Documents($client, $factory);
104 |
105 | $this->assertEquals($document, $documents->create('test.pdf', 200));
106 | $transaction = $container[0];
107 | $this->assertEquals('POST', $transaction['request']->getMethod());
108 | $this->assertEquals('/outbound/documents', $transaction['request']->getUri()->getPath());
109 | $this->assertEquals('name=test.pdf&size=200', $transaction['request']->getUri()->getQuery());
110 | }
111 |
112 | public function test_create_with_params()
113 | {
114 | $container = [];
115 | $client = $this->getClientWithResponses(
116 | $container,
117 | [
118 | new Response(201, ['Location' => 'http://mydoc.resource.uri/outbound/documents/21'], '')
119 | ]
120 | );
121 |
122 | $document = $this->getMockBuilder('Interfax\Document')
123 | ->disableOriginalConstructor()
124 | ->getMock();
125 |
126 | $factory = $this->getFactory([[$document, [$client, 21, ['id' => 21, 'size' => '200', 'name' => 'test.pdf', 'foo' => 'bar']]]]);
127 |
128 | $documents = new Documents($client, $factory);
129 |
130 | $this->assertEquals($document, $documents->create('test.pdf', 200, ['foo' => 'bar']));
131 | $transaction = $container[0];
132 | $this->assertEquals('POST', $transaction['request']->getMethod());
133 | $this->assertEquals('/outbound/documents', $transaction['request']->getUri()->getPath());
134 | $this->assertEquals('foo=bar&name=test.pdf&size=200', $transaction['request']->getUri()->getQuery());
135 | }
136 | }
137 |
--------------------------------------------------------------------------------
/tests/Interfax/FileTest.php:
--------------------------------------------------------------------------------
1 |
10 | * @copyright Copyright (c) 2016, InterFAX
11 | * @license MIT
12 | */
13 |
14 | namespace Test\Interfax;
15 |
16 | use GuzzleHttp\Psr7\Response;
17 | use Interfax\Documents;
18 | use Interfax\File;
19 |
20 | class FileTest extends BaseTest
21 | {
22 | public static function tearDownAfterClass(): void
23 | {
24 | if (file_exists(__DIR__ . '/fail.txt')) {
25 | unlink(__DIR__ . '/fail.txt');
26 | }
27 |
28 | parent::tearDownAfterClass();
29 | }
30 |
31 | public function test_it_errors_for_invalid_path()
32 | {
33 | $i = 1;
34 | $missing_file_path = "/tmp/missing{$i}.txt";
35 | while (file_exists($missing_file_path)) {
36 | $i++;
37 | $missing_file_path = "/tmp/missing{$i}.txt";
38 | }
39 |
40 | $this->expectException('InvalidArgumentException');
41 | new File($this->getClientWithFactory(), $missing_file_path);
42 | }
43 |
44 | public function test_it_sets_values_from_valid_file()
45 | {
46 | $file = new File($this->getClientWithFactory(), __DIR__ . '/test.pdf');
47 | $header = $file->getHeader();
48 | $this->assertArrayHasKey('Content-Type', $header);
49 | $this->assertEquals('application/pdf', $header['Content-Type']);
50 | $this->assertEquals('test.pdf', $file->getName());
51 | }
52 |
53 | public function test_it_automatically_creates_document_for_large_files()
54 | {
55 | $container = [];
56 |
57 | $documents_client = $this->getClientWithResponses(
58 | $container,
59 | [
60 | new Response(200, ['Location' => 'http://test.com/foo/3425'], ''),
61 | new Response(202),
62 | new Response(200)
63 | ]
64 | );
65 |
66 | $file_client = $this->getClientWithFactory([
67 | new Documents($documents_client)
68 | ]);
69 |
70 | $file = new File($file_client, __DIR__ . '/test.pdf', ['chunk_size' => 5000]);
71 | // no base uri on guzzle client
72 | $this->assertEquals(['Content-Location' => '/outbound/documents/3425'], $file->getHeader());
73 | }
74 |
75 | public function test_attribute_overrides()
76 | {
77 | // this is not a real world use case, but the principle here is to allow both attributes to be set by
78 | // the method call to ensure erroneous details can be altered correctly
79 | $file = new File($this->getClientWithFactory(), __DIR__ . '/test.pdf', ['mime_type' => 'text/html', 'name' => 'foobar.html']);
80 | $header = $file->getHeader();
81 | $this->assertArrayHasKey('Content-Type', $header);
82 | $this->assertEquals('text/html', $header['Content-Type']);
83 | $this->assertEquals('foobar.html', $file->getName());
84 | }
85 |
86 | public function test_initialise_from_uri()
87 | {
88 | $file = new File($this->getClientWithFactory(), 'https://foo.com/bar.pdf');
89 | $header = $file->getHeader();
90 | $this->assertArrayHasKey('Content-Location', $header);
91 | $this->assertEquals('https://foo.com/bar.pdf', $header['Content-Location']);
92 | }
93 |
94 | public function test_initialise_with_invalid_stream()
95 | {
96 | $stream = fopen(__DIR__ . '/fail.txt', 'w');
97 | $this->expectException('InvalidArgumentException');
98 | new File($this->getClientWithFactory(), $stream);
99 | }
100 |
101 | public function test_initialise_with_readable_stream_and_missing_args()
102 | {
103 | $stream = fopen(__DIR__ . '/test.pdf', 'rb');
104 | $this->expectException('InvalidArgumentException');
105 | new File($this->getClientWithFactory(), $stream);
106 | }
107 |
108 | public function test_initialise_with_readable_stream_and_valid_args()
109 | {
110 | $stream = fopen(__DIR__ . '/test.pdf', 'rb');
111 |
112 | $file = new File($this->getClientWithFactory(), $stream, ['name' => 'test.pdf', 'mime_type' => 'application/pdf']);
113 | $this->assertInstanceOf('Interfax\File', $file);
114 | $header = $file->getHeader();
115 | $this->assertArrayHasKey('Content-Type', $header);
116 | $this->assertEquals('application/pdf', $header['Content-Type']);
117 | fclose($stream);
118 | }
119 |
120 | public function test_large_stream_converted_to_document()
121 | {
122 | $container = [];
123 |
124 | $documents_client = $this->getClientWithResponses(
125 | $container,
126 | [
127 | new Response(200, ['Location' => 'http://test.com/foo/3425'], ''),
128 | new Response(202),
129 | new Response(200)
130 | ]
131 | );
132 |
133 | $file_client = $this->getClientWithFactory([
134 | new Documents($documents_client)
135 | ]);
136 |
137 | $stream = fopen(__DIR__ . '/test.pdf', 'rb');
138 |
139 | $file = new File($file_client, $stream, ['size' => 9147, 'name' => 'test.pdf', 'mime_type' => 'application/pdf', 'chunk_size' => 5000]);
140 | // no base uri on guzzle client
141 | $this->assertEquals(['Content-Location' => '/outbound/documents/3425'], $file->getHeader());
142 | }
143 | }
144 |
--------------------------------------------------------------------------------
/tests/Interfax/ImageTest.php:
--------------------------------------------------------------------------------
1 |
10 | * @author Mike Smith
11 | * @copyright Copyright (c) 2016, InterFAX
12 | * @license MIT
13 | */
14 |
15 | namespace Test\Interfax;
16 |
17 | use Interfax\Image;
18 | use org\bovigo\vfs\vfsStream;
19 |
20 | class ImageTest extends BaseTest
21 | {
22 | public function test_save()
23 | {
24 | $stream = $this->getMockBuilder('GuzzleHttp\Psr7\Stream')->disableOriginalConstructor()->getMock();
25 |
26 | $stream->method('eof')
27 | ->willReturnOnConsecutiveCalls(false, true);
28 | $stream->expects($this->once())
29 | ->method('read')
30 | ->will($this->returnValue('abc'));
31 |
32 | $image = new Image($stream);
33 |
34 | $directory = vfsStream::setup('test_location');
35 | $this->assertFalse($directory->hasChild('save_test.txt'));
36 | $this->assertTrue($image->save(vfsStream::url('test_location/save_test.txt')));
37 | $this->assertTrue($directory->hasChild('save_test.txt'));
38 | $this->assertEquals('abc', $directory->getChild('save_test.txt')->getContent());
39 | }
40 | }
41 |
--------------------------------------------------------------------------------
/tests/Interfax/Inbound/FaxTest.php:
--------------------------------------------------------------------------------
1 |
10 | * @author Mike Smith
11 | * @copyright Copyright (c) 2016, InterFAX
12 | * @license MIT
13 | */
14 |
15 | namespace Test\Interfax\Inbound;
16 |
17 | use Interfax\Inbound\Fax;
18 | use Test\Interfax\BaseTest;
19 | use GuzzleHttp\Psr7\Response;
20 |
21 | class FaxTest extends BaseTest
22 | {
23 | public function test_successful_construction()
24 | {
25 | $client = $this->getMockBuilder('Interfax\Client')
26 | ->disableOriginalConstructor()
27 | ->getMock();
28 |
29 | $fax = new Fax($client, 854759652);
30 |
31 | $this->assertInstanceOf('Interfax\Inbound\Fax', $fax);
32 | $this->assertNotNull($fax->id);
33 | $this->assertEquals(854759652, $fax->id);
34 | }
35 |
36 | public function test_markRead()
37 | {
38 | $client = $this->getMockBuilder('Interfax\Client')
39 | ->disableOriginalConstructor()
40 | ->setMethods(array('post'))
41 | ->getMock();
42 |
43 | $client->expects($this->once())
44 | ->method('post')
45 | ->with('/inbound/faxes/854759652/mark', ['query' => ['unread' => false]])
46 | ->will($this->returnValue(''));
47 |
48 | $fax = new Fax($client, 854759652);
49 |
50 | $this->assertEquals($fax, $fax->markRead());
51 | }
52 |
53 | public function test_markUnread()
54 | {
55 | $client = $this->getMockBuilder('Interfax\Client')
56 | ->disableOriginalConstructor()
57 | ->setMethods(array('post'))
58 | ->getMock();
59 |
60 | $client->expects($this->once())
61 | ->method('post')
62 | ->with('/inbound/faxes/854759652/mark', ['query' => ['unread' => true]])
63 | ->will($this->returnValue(''));
64 |
65 | $fax = new Fax($client, 854759652);
66 |
67 | $this->assertEquals($fax, $fax->markUnread());
68 | }
69 |
70 | public function test_resend()
71 | {
72 | $client = $this->getMockBuilder('Interfax\Client')
73 | ->disableOriginalConstructor()
74 | ->setMethods(array('post'))
75 | ->getMock();
76 |
77 | $client->expects($this->once())
78 | ->method('post')
79 | ->with('/inbound/faxes/854759652/resend')
80 | ->will($this->returnValue(''));
81 |
82 | $fax = new Fax($client, 854759652);
83 |
84 | $this->assertEquals($fax, $fax->resend());
85 | }
86 |
87 | public function test_resend_with_email()
88 | {
89 | $client = $this->getMockBuilder('Interfax\Client')
90 | ->disableOriginalConstructor()
91 | ->setMethods(array('post'))
92 | ->getMock();
93 |
94 | $client->expects($this->once())
95 | ->method('post')
96 | ->with('/inbound/faxes/854759652/resend', ['query' => ['email' => 'foo@bar.com']])
97 | ->will($this->returnValue(''));
98 |
99 | $fax = new Fax($client, 854759652);
100 |
101 | $this->assertEquals($fax, $fax->resend('foo@bar.com'));
102 | }
103 |
104 | public function test_image()
105 | {
106 | $container = [];
107 | $resp_resource = fopen(__DIR__ . '/../test.pdf', 'r');
108 | $stream = \GuzzleHttp\Psr7\Utils::streamFor($resp_resource);
109 | $client = $this->getClientWithResponses(
110 | $container,
111 | [
112 | new Response(200, [], $stream),
113 | ]
114 | );
115 |
116 | $result_image = $this->getMockBuilder('Interfax\Image')->disableOriginalConstructor()->getMock();
117 | $factory = $this->getFactory([
118 | // $result_image
119 | [$result_image, [$stream]],
120 | ]);
121 |
122 | $fax = new Fax($client, 854759652, [], $factory);
123 | //$image = $fax->image();
124 | $this->assertEquals($result_image, $fax->image());
125 | $transaction = $container[0];
126 | $this->assertEquals('GET', $transaction['request']->getMethod());
127 | $this->assertEquals('/inbound/faxes/854759652/image', $transaction['request']->getUri()->getPath());
128 |
129 | fclose($resp_resource);
130 | }
131 |
132 | public function test_emails()
133 | {
134 | $client = $this->getMockBuilder('Interfax\Client')
135 | ->disableOriginalConstructor()
136 | ->setMethods(array('get'))
137 | ->getMock();
138 |
139 | $response = [
140 | [
141 | 'emailAddress' => 'username@interfax.net',
142 | 'messageStatus' => 0,
143 | 'completionTime' => '2012-0623T17:24:11',
144 | ],
145 | [
146 | 'emailAddress' => 'username2@interfax.net',
147 | 'messageStatus' => 0,
148 | 'completionTime' => '2012-0623T17:25:11',
149 | ],
150 | ];
151 |
152 | $client->expects($this->once())
153 | ->method('get')
154 | ->with('/inbound/faxes/854759652/emails')
155 | ->will($this->returnValue($response));
156 |
157 | $fax = new Fax($client, 854759652);
158 | $this->assertEquals($response, $fax->emails());
159 | }
160 | }
161 |
--------------------------------------------------------------------------------
/tests/Interfax/InboundTest.php:
--------------------------------------------------------------------------------
1 |
10 | * @author Mike Smith
11 | * @copyright Copyright (c) 2016, InterFAX
12 | * @license MIT
13 | */
14 |
15 | namespace Test\Interfax;
16 |
17 | use GuzzleHttp\Psr7\Response;
18 | use Interfax\Inbound;
19 |
20 | class InboundTest extends BaseTest
21 | {
22 | public function test_incoming()
23 | {
24 | $response = [['messageId' => 12, 'phoneNumber' => '111'],['messageId' => 14, 'phoneNumber' => '2222']];
25 | $container = [];
26 | $client = $this->getClientWithResponses(
27 | $container,
28 | [
29 | new Response('200', ['Content-type' => 'text/json'], json_encode($response))
30 | ]
31 | );
32 |
33 | // 2 inbound faxes will be crated for the 2 response structs
34 | $factory = $this->getFactory(
35 | [
36 | [new Inbound\Fax($client, 12), [$client, 12, $response[0]]],
37 | [new Inbound\Fax($client, 40), [$client, 14, $response[1]]]
38 | ]
39 | );
40 |
41 | $inbound = new Inbound($client, $factory);
42 |
43 | $faxes = $inbound->incoming(['unreadOnly' => false]);
44 |
45 | $this->assertCount(2, $faxes);
46 | $transaction = $container[0];
47 | $this->assertEquals('GET', $transaction['request']->getMethod());
48 | $this->assertEquals('/inbound/faxes', $transaction['request']->getUri()->getPath());
49 | $this->assertEquals('unreadOnly=FALSE', $transaction['request']->getUri()->getQuery());
50 | }
51 |
52 | public function test_find()
53 | {
54 | $response = ['messageId' => 12, 'phoneNumber' => '111'];
55 | $container = [];
56 | $client = $this->getClientWithResponses(
57 | $container,
58 | [
59 | new Response('200', ['Content-type' => 'text/json'], json_encode($response))
60 | ]
61 | );
62 |
63 | $fax = new Inbound\Fax($client, 12);
64 | $factory = $this->getFactory(
65 | [
66 | [$fax, [$client, 12, $response]],
67 | ]
68 | );
69 |
70 | $inbound = new Inbound($client, $factory);
71 |
72 | $this->assertEquals($fax, $inbound->find(12));
73 | $transaction = $container[0];
74 | $this->assertEquals('GET', $transaction['request']->getMethod());
75 | $this->assertEquals('/inbound/faxes/12', $transaction['request']->getUri()->getPath());
76 | $this->assertEquals('', $transaction['request']->getUri()->getQuery());
77 | }
78 | }
79 |
--------------------------------------------------------------------------------
/tests/Interfax/Outbound/DeliveryTest.php:
--------------------------------------------------------------------------------
1 |
10 | * @author Mike Smith
11 | * @copyright Copyright (c) 2016, InterFAX
12 | * @license MIT
13 | */
14 |
15 | namespace Test\Interfax\Outbound;
16 |
17 | use Interfax\Outbound\Delivery;
18 | use PHPUnit\Framework\MockObject\MockObject;
19 | use Test\Interfax\BaseTest;
20 | use Interfax\Client;
21 | use GuzzleHttp\Psr7\Response;
22 | use Interfax\File;
23 |
24 | class DeliveryTest extends BaseTest
25 | {
26 | protected $client;
27 |
28 | public function setUp(): void
29 | {
30 | $this->client = new Client(['username' => 'test_user', 'password' => 'test_password']);
31 | }
32 |
33 | public function test_it_cant_be_constructed_without_params()
34 | {
35 | $this->expectException('InvalidArgumentException');
36 |
37 | $delivery = new Delivery($this->client);
38 | }
39 |
40 | public function test_it_cant_be_constructed_without_a_file()
41 | {
42 |
43 | $this->expectException('InvalidArgumentException');
44 |
45 | $delivery2 = new Delivery($this->client, ['faxNumber' => '12345']);
46 | }
47 |
48 | public function test_it_can_be_constructed_with_a_file_path()
49 | {
50 | $file = $this->getMockBuilder('Interfax\File')->disableOriginalConstructor()->getMock();
51 |
52 | $factory = $this->getFactory(
53 | [
54 | [$file, [$this->client, '/fake/file']],
55 | [$file, [$this->client, '/fake/file2']]
56 | ]
57 | );
58 |
59 | $this->assertInstanceOf('Interfax\Outbound\Delivery', new Delivery($this->client, ['faxNumber' => '12345', 'file' => '/fake/file'], $factory));
60 | $this->assertInstanceOf('Interfax\Outbound\Delivery', new Delivery($this->client, ['faxNumber' => '12345', 'files' => ['/fake/file2']], $factory));
61 | }
62 |
63 | public function test_it_can_be_constructed_with_a_stream()
64 | {
65 | $stream = fopen(__DIR__ . '/../test.pdf', 'rb');
66 | $file = $this->getMockBuilder('Interfax\File')->disableOriginalConstructor()->getMock();
67 | $params = ['name' => 'test.pdf', 'mime_type' => 'application/pdf'];
68 |
69 | $factory = $this->getFactory([
70 | [$file, [$this->client, $stream, $params]]
71 | ]);
72 |
73 | $this->assertInstanceOf('Interfax\Outbound\Delivery', new Delivery($this->client, ['faxNumber' => '12345', 'file' => [$stream, $params]], $factory));
74 | }
75 |
76 | public function test_it_can_be_constructed_with_a_uri()
77 | {
78 | $this->assertInstanceOf('Interfax\Outbound\Delivery', new Delivery($this->client, ['faxNumber' => '12345', 'file' => 'https://test.com/foo/bar']));
79 | }
80 |
81 | public function test_it_can_be_constructed_with_an_Interfax_File()
82 | {
83 | $client = $this->client;
84 | $file = new File($client, __DIR__ . '/../test.pdf');
85 | $delivery = new Delivery($this->client, ['faxNumber' => '12345', 'file' => $file]);
86 | $this->assertInstanceOf('Interfax\Outbound\Delivery', $delivery);
87 | $r = new \ReflectionClass($delivery);
88 | $rp = $r->getProperty('files');
89 | $rp->setAccessible(true);
90 | $this->assertEquals([$file], $rp->getValue($delivery));
91 | }
92 |
93 | public function test_it_can_be_constructed_with_an_Interfax_Document()
94 | {
95 | $file = $this->getMockBuilder('Interfax\File')->disableOriginalConstructor()->getMock();
96 | $factory = $this->getFactory([
97 | [$file, [$this->client, 'http://test.com/foo']]
98 | ]);
99 |
100 | $document = $this->getMockBuilder('Interfax\Document')
101 | ->disableOriginalConstructor()
102 | ->setMethods(['getHeaderLocation'])
103 | ->getMock();
104 |
105 | $document->expects($this->once())
106 | ->method('getHeaderLocation')
107 | ->will($this->returnValue('http://test.com/foo'));
108 |
109 | $delivery = new Delivery($this->client, ['faxNumber' => '12345', 'file' => $document], $factory);
110 | $this->assertInstanceOf('Interfax\Outbound\Delivery', $delivery);
111 | }
112 |
113 | public function test_it_stores_provided_params_for_the_query_string()
114 | {
115 | $params = [];
116 | for ($i = 0; $i < 5; $i++) {
117 | $params[substr(md5(mt_rand()), 0, 7)] = substr(md5(mt_rand()), 0, 7);
118 | }
119 | $params['faxNumber'] = '12345';
120 | $params['file'] = __DIR__ . '/../test.pdf';
121 |
122 | $delivery = new Delivery($this->client, $params);
123 | $r = new \ReflectionClass('Interfax\Outbound\Delivery');
124 | $r_qp = $r->getProperty('query_params');
125 | $r_qp->setAccessible(true);
126 | $qp = $r_qp->getValue($delivery);
127 |
128 | // file is not a query param
129 | unset($params['file']);
130 | $this->assertEquals(count($params), count($qp));
131 | foreach ($params as $k => $v) {
132 | $this->assertArrayHasKey($k, $qp);
133 | $this->assertEquals($v, $qp[$k]);
134 | }
135 | }
136 |
137 | public function test_it_uses_the_client_to_post_a_delivery_and_returns_fax()
138 | {
139 | $container = [];
140 | $client = $this->getClientWithResponses(
141 | $container,
142 | [
143 | new Response(201, ['Location' => 'http://myfax.resource.uri/outbound/faxes/21'], '')
144 | ]
145 | );
146 |
147 | // construct fake file to ensure it affects the request contents correctly
148 | $file = $this->getMockBuilder('Interfax\File')
149 | ->disableOriginalConstructor()
150 | ->setMethods(['getHeader', 'getBody'])
151 | ->getMock();
152 |
153 | $file->expects($this->any())
154 | ->method('getHeader')
155 | ->will($this->returnValue(['Content-Type' => 'app/foo']));
156 |
157 | $file->expects($this->any())
158 | ->method('getBody')
159 | ->will($this->returnValue('foo bar car'));
160 |
161 | // fake fax to be returned
162 | $fax = $this->getMockBuilder('Interfax\Outbound\Fax')
163 | ->disableOriginalConstructor()
164 | ->getMock();
165 |
166 | $factory = $this->getFactory(
167 | [
168 | [$file, [$client, 'fake/file']],
169 | [$fax, [$client, 21]]
170 | ]
171 | );
172 |
173 | $delivery = new Delivery($client, ['faxNumber' => 12345, 'bar' => 'foo', 'file' => 'fake/file'], $factory);
174 |
175 | $this->assertEquals($fax, $delivery->send());
176 | $transaction = $container[0];
177 | $this->assertEquals('POST', $transaction['request']->getMethod());
178 | $this->assertEquals('/outbound/faxes', $transaction['request']->getUri()->getPath());
179 | $this->assertEquals('faxNumber=12345&bar=foo', $transaction['request']->getUri()->getQuery());
180 | $this->assertEquals('app/foo', $transaction['request']->getHeaderLine('Content-Type'));
181 | $body = $transaction['request']->getBody();
182 | //$this->assertInstanceOf('GuzzleHttp\Psr7\MultipartStream', $body);
183 | $contents = (string) $body;
184 |
185 | $this->assertEquals(1, preg_match('/foo bar car/', $contents));
186 | }
187 |
188 | /**
189 | * Helper function to generate a mock Interfax\File
190 | *
191 | * @param $headers
192 | * @param $body
193 | * @return MockObject
194 | */
195 | protected function getFakeFile($headers, $body, $name = 'fakeFaxFile')
196 | {
197 | // construct fake file to ensure it affects the request contents correctly
198 | $file = $this->getMockBuilder('Interfax\File')
199 | ->disableOriginalConstructor()
200 | ->onlyMethods(['getHeader', 'getBody', 'getName'])
201 | ->getMock();
202 |
203 | $file->expects($this->any())
204 | ->method('getHeader')
205 | ->will($this->returnValue($headers));
206 |
207 | $file->expects($this->any())
208 | ->method('getBody')
209 | ->will($this->returnValue($body));
210 |
211 | $file->expects($this->any())
212 | ->method('getName')
213 | ->will($this->returnValue($name));
214 |
215 | return $file;
216 | }
217 |
218 | public function test_it_supports_multiple_file_delivery()
219 | {
220 | $container = [];
221 | $client = $this->getClientWithResponses(
222 | $container,
223 | [
224 | new Response(201, ['Location' => 'http://myfax.resource.uri/outbound/faxes/21'], '')
225 | ]
226 | );
227 |
228 | $file1 = $this->getFakeFile(['Content-Type' => 'app/foo'], 'foo bar car');
229 | $file2 = $this->getFakeFile(['Content-Type' => 'app/bar'], 'test content');
230 |
231 | // fake fax to be returned
232 | $fax = $this->getMockBuilder('Interfax\Outbound\Fax')
233 | ->disableOriginalConstructor()
234 | ->getMock();
235 |
236 | $factory = $this->getFactory([
237 | [$file1, [$client, 'fake/file1']],
238 | [$file2, [$client, 'fake/file2']],
239 | [$fax, [$client, 21]]
240 | ]);
241 |
242 | $delivery = new Delivery($client, ['faxNumber' => 12345, 'bar' => 'foo', 'files' => ['fake/file1', 'fake/file2']], $factory);
243 |
244 | $this->assertEquals($fax, $delivery->send());
245 | $transaction = $container[0];
246 | $this->assertEquals('POST', $transaction['request']->getMethod());
247 | $this->assertEquals('/outbound/faxes', $transaction['request']->getUri()->getPath());
248 | $this->assertEquals('faxNumber=12345&bar=foo', $transaction['request']->getUri()->getQuery());
249 | $body = $transaction['request']->getBody();
250 | $this->assertInstanceOf('GuzzleHttp\Psr7\MultipartStream', $body);
251 | $contents = (string) $body;
252 | $this->assertEquals(1, preg_match('/Content-Type: app\/foo/', $contents));
253 | $this->assertEquals(1, preg_match('/foo bar car/', $contents));
254 | $this->assertEquals(1, preg_match('/Content-Type: app\/bar/', $contents));
255 | $this->assertEquals(1, preg_match('/test content/', $contents));
256 | }
257 | }
258 |
--------------------------------------------------------------------------------
/tests/Interfax/Outbound/FaxTest.php:
--------------------------------------------------------------------------------
1 |
10 | * @author Mike Smith
11 | * @copyright Copyright (c) 2016, InterFAX
12 | * @license MIT
13 | */
14 |
15 | namespace Test\Interfax\Outbound;
16 |
17 | use GuzzleHttp\Psr7\Response;
18 | use Interfax\Outbound\Fax;
19 | use Test\Interfax\BaseTest;
20 |
21 | class FaxTest extends BaseTest
22 | {
23 | public function test_successful_construction()
24 | {
25 | $client = $this->getMockBuilder('Interfax\Client')
26 | ->disableOriginalConstructor()
27 | ->getMock();
28 |
29 | $fax = new Fax($client, 854759652);
30 |
31 | $this->assertInstanceOf('Interfax\Outbound\Fax', $fax);
32 | $this->assertNotNull($fax->id);
33 | $this->assertEquals(854759652, $fax->id);
34 | }
35 |
36 | public function test_refresh()
37 | {
38 | $client = $this->getMockBuilder('Interfax\Client')
39 | ->disableOriginalConstructor()
40 | ->setMethods(array('get'))
41 | ->getMock();
42 |
43 | $reload_response = ['id' => 854759652,'uri' => 'https://rest.interfax.net/outbound/faxes/279415116','status' => 0];
44 |
45 | $client->expects($this->once())
46 | ->method('get')
47 | ->with('/outbound/faxes/854759652')
48 | ->will($this->returnValue($reload_response));
49 |
50 | $fax = new Fax($client, 854759652);
51 |
52 | $this->assertNull($fax->status);
53 | $this->assertEquals($fax, $fax->refresh());
54 | $this->assertEquals(0, $fax->status);
55 | }
56 |
57 | public function test_getter_method_for_record_details()
58 | {
59 | $client = $this->getMockBuilder('Interfax\Client')
60 | ->disableOriginalConstructor()
61 | ->setMethods(array('get'))
62 | ->getMock();
63 |
64 | $response = [];
65 | for ($i = 0; $i < 5; $i++) {
66 | $response[substr(md5(mt_rand()), 0, 7)] = substr(md5(mt_rand()), 0, 7);
67 | }
68 | $response['id'] = 82342453;
69 | $response['status'] = -2;
70 |
71 | $client->expects($this->once())
72 | ->method('get')
73 | ->with('/outbound/faxes/82342453')
74 | ->will($this->returnValue($response));
75 |
76 | $fax = new Fax($client, 82342453);
77 | $this->assertNull($fax->status);
78 | foreach ($response as $k => $v) {
79 | if ($k != 'id') {
80 | $this->assertNull($fax->$k);
81 | }
82 | }
83 |
84 | $this->assertInstanceOf('Interfax\Outbound\Fax', $fax->refresh());
85 |
86 | foreach ($response as $k => $v) {
87 | $this->assertEquals($v, $fax->$k);
88 | }
89 |
90 | $this->assertNull($fax->undefined_property);
91 | }
92 |
93 | public function test_resend()
94 | {
95 | $container = [];
96 |
97 | $client = $this->getClientWithResponses(
98 | $container,
99 | [
100 | new Response(201, ['Location' => 'http://myfax.resource.uri/outbound/faxes/21'], '')
101 | ]
102 | );
103 |
104 | $resent_fax = $this->getMockBuilder('Interfax\Outbound\Fax')
105 | ->disableOriginalConstructor()
106 | ->getMock();
107 |
108 | $factory = $this->getFactory([[$resent_fax, [$client, 21]]]);
109 |
110 | $fax = new Fax($client, 45, [], $factory);
111 |
112 | $this->assertEquals($resent_fax, $fax->resend());
113 | $transaction = $container[0];
114 | $this->assertEquals('POST', $transaction['request']->getMethod());
115 | $this->assertEquals('/outbound/faxes/45/resend', $transaction['request']->getUri()->getPath());
116 | }
117 |
118 | public function test_resend_with_param()
119 | {
120 | $container = [];
121 |
122 | $client = $this->getClientWithResponses(
123 | $container,
124 | [
125 | new Response(201, ['Location' => 'http://myfax.resource.uri/outbound/faxes/21'], '')
126 | ]
127 | );
128 |
129 | $resent_fax = $this->getMockBuilder('Interfax\Outbound\Fax')
130 | ->disableOriginalConstructor()
131 | ->getMock();
132 |
133 | $factory = $this->getFactory([[$resent_fax, [$client, 21]]]);
134 |
135 | $fax = new Fax($client, 45, [], $factory);
136 |
137 | $resend_number = '+1111111111';
138 |
139 | $this->assertEquals($resent_fax, $fax->resend($resend_number));
140 | $transaction = $container[0];
141 | $this->assertEquals('POST', $transaction['request']->getMethod());
142 | $this->assertEquals('/outbound/faxes/45/resend', $transaction['request']->getUri()->getPath());
143 | $this->assertEquals('faxNumber=' . urlencode($resend_number), $transaction['request']->getUri()->getQuery());
144 | }
145 |
146 | public function test_attributes()
147 | {
148 | $client = $this->getMockBuilder('Interfax\Client')->disableOriginalConstructor()->getMock();
149 |
150 | $definition = [
151 | 'submitTime' => '2012-06-20T06:08:18',
152 | 'contact' => '',
153 | 'destinationFax' => '0081287282867',
154 | 'replyEmail' => 'nadya@interfax.net',
155 | 'subject' => 'test',
156 | 'pagesSubmitted' => 1,
157 | 'senderCSID' => 'INTERFAX',
158 | 'attemptsToPerform' => 4,
159 | 'pageSize' => 'A4',
160 | 'resolution' => 'Portrait',
161 | 'pageResolution' => 'Fine',
162 | 'pageOrientation' => 'Portrait',
163 | 'rendering' => 'Fine',
164 | 'pageHeade' => '0',
165 | 'userId' => 'nadya',
166 | 'pagesSent' => 1,
167 | 'completionTime' => '2012-06-20T06:09:08',
168 | 'remoteCSID' => '81287282867',
169 | 'duration' => 37,
170 | 'priority' => 2,
171 | 'units' => 1.00,
172 | 'costPerUnit' => 0.9500,
173 | 'attemptsMade' => 1,
174 | 'id' => 279415116,
175 | 'uri' => 'https://rest.interfax.net/outbound/faxes/279415116',
176 | 'status' => 0
177 | ];
178 |
179 | $fax = new Fax($client, 279415116, $definition);
180 |
181 | $this->assertEquals($definition, $fax->attributes());
182 | }
183 |
184 | public function test_cancel()
185 | {
186 | $container = [];
187 | $client = $this->getClientWithResponses(
188 | $container,
189 | [
190 | new Response(200, [], '')
191 | ]
192 | );
193 |
194 | $fax = new Fax($client, 21);
195 |
196 | $this->assertEquals($fax, $fax->cancel());
197 |
198 | $transaction = $container[0];
199 | $this->assertEquals('POST', $transaction['request']->getMethod());
200 | $this->assertEquals('/outbound/faxes/21/cancel', $transaction['request']->getUri()->getPath());
201 | }
202 |
203 | public function test_hide()
204 | {
205 | $container = [];
206 | $client = $this->getClientWithResponses(
207 | $container,
208 | [
209 | new Response(200, [], '')
210 | ]
211 | );
212 |
213 | $fax = new Fax($client, 21);
214 |
215 | $this->assertEquals($fax, $fax->hide());
216 | $transaction = $container[0];
217 | $this->assertEquals('POST', $transaction['request']->getMethod());
218 | $this->assertEquals('/outbound/faxes/21/hide', $transaction['request']->getUri()->getPath());
219 | }
220 |
221 | public function test_image()
222 | {
223 | $container = [];
224 | $resp_resource = fopen(__DIR__ . '/../test.pdf', 'r');
225 | $stream = \GuzzleHttp\Psr7\Utils::streamFor($resp_resource);
226 | $client = $this->getClientWithResponses(
227 | $container,
228 | [
229 | new Response(200, [], $stream)
230 | ]
231 | );
232 |
233 | $result_image = $this->getMockBuilder('Interfax\Image')->disableOriginalConstructor()->getMock();
234 | $factory = $this->getFactory([
235 | [$result_image, [$stream]]
236 | ]);
237 |
238 | $fax = new Fax($client, 42, [], $factory);
239 |
240 | $this->assertEquals($result_image, $fax->image());
241 | $transaction = $container[0];
242 | $this->assertEquals('GET', $transaction['request']->getMethod());
243 | $this->assertEquals('/outbound/faxes/42/image', $transaction['request']->getUri()->getPath());
244 |
245 | fclose($resp_resource);
246 | }
247 | }
248 |
--------------------------------------------------------------------------------
/tests/Interfax/OutboundTest.php:
--------------------------------------------------------------------------------
1 |
10 | * @author Mike Smith
11 | * @copyright Copyright (c) 2016, InterFAX
12 | * @license MIT
13 | */
14 |
15 | namespace Test\Interfax;
16 |
17 | use GuzzleHttp\Psr7\Response;
18 | use Interfax\Outbound;
19 |
20 | class OutboundTest extends BaseTest
21 | {
22 | public function test_completed()
23 | {
24 | $response = [['id' => 12, 'senderCSID' => 'Interfax'],['id' => 14, 'senderCSID' => 'Interfax']];
25 | $container = [];
26 | $client = $this->getClientWithResponses(
27 | $container,
28 | [
29 | new Response('200', ['Content-type' => 'text/json'], json_encode($response))
30 | ]
31 | );
32 |
33 | $fax1 = $this->getMockBuilder('Interfax\Outbound\Fax')->disableOriginalConstructor()->getMock();
34 | $fax2 = $this->getMockBuilder('Interfax\Outbound\Fax')->disableOriginalConstructor()->getMock();
35 | $factory = $this->getFactory([
36 | [$fax1, [$client, 12, $response[0]]],
37 | [$fax2, [$client, 14, $response[1]]]
38 | ]);
39 |
40 | $outbound = new Outbound($client, $factory);
41 |
42 | $res = $outbound->completed(['12', '14']);
43 |
44 | $this->assertEquals([$fax1, $fax2], $res);
45 | $transaction = $container[0];
46 | $this->assertEquals('GET', $transaction['request']->getMethod());
47 | $this->assertEquals('/outbound/faxes/completed', $transaction['request']->getUri()->getPath());
48 | $this->assertEquals('ids=' . urlencode('12,14'), $transaction['request']->getUri()->getQuery());
49 | }
50 |
51 | public function test_recent()
52 | {
53 | $response = [['id' => 21]];
54 | $container = [];
55 | $client = $this->getClientWithResponses(
56 | $container,
57 | [
58 | new Response('200', ['Content-type' => 'text/json'], json_encode($response))
59 | ]
60 | );
61 |
62 | $fax = $this->getMockBuilder('Interfax\Outbound\Fax')->disableOriginalConstructor()->getMock();
63 |
64 | $factory = $this->getFactory([[$fax, [$client, 21, $response[0]]]]);
65 |
66 | $outbound = new Outbound($client, $factory);
67 |
68 | $res = $outbound->recent(['limit' => 5]);
69 |
70 | $this->assertEquals([$fax], $res);
71 | $transaction = $container[0];
72 | $this->assertEquals('GET', $transaction['request']->getMethod());
73 | $this->assertEquals('/outbound/faxes', $transaction['request']->getUri()->getPath());
74 | $this->assertEquals('limit=5', $transaction['request']->getUri()->getQuery());
75 | }
76 |
77 | public function test_resend_uses_outbound_fax()
78 | {
79 | $fax = $this->getMockBuilder('Interfax\Outbound\Fax')
80 | ->disableOriginalConstructor()
81 | ->setMethods(['resend'])
82 | ->getMock();
83 |
84 | $resent_fax = $this->getMockBuilder('Interfax\Outbound\Fax')->disableOriginalConstructor()->getMock();
85 |
86 | $fax->expects($this->once())
87 | ->method('resend')
88 | ->will($this->returnValue($resent_fax));
89 |
90 | $factory = $this->getFactory([$fax]);
91 |
92 | $client = $this->getMockBuilder('Interfax\Client')->disableOriginalConstructor()->getMock();
93 |
94 | $outbound = new Outbound($client, $factory);
95 |
96 | $this->assertEquals($resent_fax, $outbound->resend(34552));
97 | }
98 |
99 | public function test_resend_with_new_number_uses_outbound_fax()
100 | {
101 | $fax = $this->getMockBuilder('Interfax\Outbound\Fax')
102 | ->disableOriginalConstructor()
103 | ->setMethods(['resend'])
104 | ->getMock();
105 |
106 | $fax_number = '+112122323';
107 |
108 | $resent_fax = $this->getMockBuilder('Interfax\Outbound\Fax')->disableOriginalConstructor()->getMock();
109 |
110 | $fax->expects($this->once())
111 | ->method('resend')
112 | ->with($fax_number)
113 | ->will($this->returnValue($resent_fax));
114 |
115 | $factory = $this->getFactory([$fax]);
116 |
117 | $client = $this->getMockBuilder('Interfax\Client')->disableOriginalConstructor()->getMock();
118 |
119 | $outbound = new Outbound($client, $factory);
120 |
121 | $this->assertEquals($resent_fax, $outbound->resend(34552, $fax_number));
122 | }
123 |
124 | public function test_search()
125 | {
126 | $container = [];
127 |
128 | $search_results = [
129 | ['id' => 5, 'status' => -32],
130 | ['id' => 9, 'status' => 40],
131 | ];
132 |
133 | $client = $this->getClientWithResponses(
134 | $container,
135 | [
136 | new Response(200, ['Content-Type' => 'text/json'], json_encode($search_results))
137 | ]
138 | );
139 |
140 | $test_params = ['status' => 'Inprocess'];
141 |
142 | $factory = $this->getFactory([
143 | [new Outbound\Fax($client, 5),[$client, 5, $search_results[0]] ],
144 | [new Outbound\Fax($client, 9),[$client, 9, $search_results[1]] ]
145 | ]);
146 |
147 | $outbound = new Outbound($client, $factory);
148 |
149 | $this->assertCount(2, $outbound->search($test_params));
150 | $transaction = $container[0];
151 | $this->assertEquals('GET', $transaction['request']->getMethod());
152 | $this->assertEquals('/outbound/search', $transaction['request']->getUri()->getPath());
153 | $this->assertEquals('status=Inprocess', $transaction['request']->getUri()->getQuery());
154 | }
155 |
156 | public function test_find()
157 | {
158 | $response = ['id' => 42, 'status' => 0, 'duration' => 4];
159 | $container = [];
160 | $client = $this->getClientWithResponses(
161 | $container,
162 | [
163 | new Response('200', ['Content-type' => 'text/json'], json_encode($response))
164 | ]
165 | );
166 |
167 | $fax = new Outbound\Fax($client, 42, $response);
168 | $factory = $this->getFactory(
169 | [
170 | [$fax, [$client, 42, $response]],
171 | ]
172 | );
173 |
174 | $outbound = new Outbound($client, $factory);
175 |
176 | $this->assertEquals($fax, $outbound->find(12));
177 | $transaction = $container[0];
178 | $this->assertEquals('GET', $transaction['request']->getMethod());
179 | $this->assertEquals('/outbound/faxes/12', $transaction['request']->getUri()->getPath());
180 | $this->assertEquals('', $transaction['request']->getUri()->getQuery());
181 | }
182 | }
183 |
--------------------------------------------------------------------------------
/tests/Interfax/test.pdf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/interfax/interfax-php/de0ebc06471c140935e54d7e642fb4149f858a63/tests/Interfax/test.pdf
--------------------------------------------------------------------------------