x Sorry, these patches are not available anymore due to data migration. Please run a fresh inspection.
Completed
Push — develop ( 6b469b...d09f40 )
by Barry
02:12
created

Pdfcrowd::setOutputDestination()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 2

Importance

Changes 0
Metric Value
dl 0
loc 4
ccs 0
cts 4
cp 0
rs 10
c 0
b 0
f 0
cc 1
eloc 2
nc 1
nop 1
crap 2
1
<?php
2
3
declare(strict_types=1);
4
5
namespace Swis\PdfcrowdClient;
6
7
use Swis\PdfcrowdClient\Exceptions\PdfcrowdException;
8
use Swis\PdfcrowdClient\Http\FactoryInterface;
9
use Swis\PdfcrowdClient\Http\RequestFactory;
10
use Swis\PdfcrowdClient\Http\RequestInterface;
11
12
class Pdfcrowd
13
{
14
    /** @var array */
15
    private $requestBody;
16
17
    /** @var string */
18
    private $scheme;
19
20
    /** @var int */
21
    private $port;
22
23
    /** @var string */
24
    private $api_prefix;
25
26
    /** @var int */
27
    private $curlopt_timeout;
28
29
    /** @var string */
30
    private $hostname;
31
32
    /** @var string */
33
    private $user_agent;
34
35
    /** @var int */
36
    private $num_tokens_before = false;
37
38
    /** @var int */
39
    private $http_code;
40
41
    /** @var FactoryInterface */
42
    protected $requestFactory;
43
44
    /* @var RequestInterface */
45
    private $request;
46
47
    /** @var bool  */
48
    private $track_tokens = false;
49
50
    protected $output_destination;
51
52
    public static $client_version = '2.7';
53
    public static $http_port = 80;
54
    public static $https_port = 443;
55
    public static $api_host = 'pdfcrowd.com';
56
57
    private $proxy_name;
58
    private $proxy_port;
59
    private $proxy_username = '';
60
    private $proxy_password = '';
61
62
    const SINGLE_PAGE = 1;
63
    const CONTINUOUS = 2;
64
    const CONTINUOUS_FACING = 3;
65
66
    const NONE_VISIBLE = 1;
67
    const THUMBNAILS_VISIBLE = 2;
68
    const FULLSCREEN = 3;
69
70
    const FIT_WIDTH = 1;
71
    const FIT_HEIGHT = 2;
72
    const FIT_PAGE = 3;
73
74
    /**
75
     * Pdfcrowd constructor.
76
     *
77
     * @param string $username
78
     * @param string $key
79
     */
80
    public function __construct(string $username, string $key)
81
    {
82
        $this->hostname = self::$api_host;
83
84
        $this->useSSL(true);
85
86
        $this->requestBody = [
87
            'username' => $username,
88
            'key' => $key,
89
            'pdf_scaling_factor' => 1,
90
            'html_zoom' => 200,
91
        ];
92
93
        $this->user_agent = 'pdfcrowd_php_client_'.self::$client_version.'_(http://pdfcrowd.com)';
94
95
        $this->requestFactory = new RequestFactory();
96
    }
97
98
    /**
99
     * This method allows you to override the default CurlRequest object. Added for testing purposes.
100
     *
101
     * @param \Swis\PdfcrowdClient\Http\FactoryInterface $requestFactory
102
     */
103
    public function setRequestFactory(FactoryInterface $requestFactory)
104
    {
105
        $this->requestFactory = $requestFactory;
106
    }
107
108
    /**
109
     * Each httpPost-call uses a clean request object.
110
     *
111
     * @return \Swis\PdfcrowdClient\Http\RequestInterface
112
     * @throws \Swis\PdfcrowdClient\Exceptions\PdfcrowdException
113
     */
114
    protected function getNewRequestObject(): RequestInterface
115
    {
116
        $request = $this->requestFactory->create();
117
118
        return $request;
119
    }
120
121
    /**
122
     * Converts an in-memory html document.
123
     *
124
     * @param string $src       a string containing a html document
125
     *
126
     * @return mixed
127
     * @throws \Swis\PdfcrowdClient\Exceptions\PdfcrowdException
128
     */
129
    public function convertHtml($src)
130
    {
131
        if (!$src) {
132
            throw new PdfcrowdException('convertHTML(): the src parameter must not be empty');
133
        }
134
135
        $this->requestBody['src'] = $src;
136
137
        // todo: create uri from prefix + constant value
138
        $uri = $this->api_prefix.'/pdf/convert/html/';
139
140
        if ($this->track_tokens) {
141
            $this->num_tokens_before = $this->availableTokens();
142
        }
143
144
        return $this->httpPost($uri, $this->requestBody);
145
    }
146
147
    /**
148
     * Converts a web page.
149
     *
150
     * @param string $src       a web page URL
151
     *
152
     * @return mixed
153
     * @throws \Swis\PdfcrowdClient\Exceptions\PdfcrowdException
154
     */
155
    public function convertURI(string $src)
156
    {
157
        $src = trim($src);
158
        if (!preg_match("/^https?:\/\/.*/i", $src)) {
159
            throw new PdfcrowdException("convertURI(): the URL must start with http:// or https:// (got '$src')");
160
        }
161
162
        $this->requestBody['src'] = $src;
163
        $uri = $this->api_prefix.'/pdf/convert/uri/';
164
165
        if ($this->track_tokens) {
166
            $this->num_tokens_before = $this->availableTokens();
167
        }
168
169
        return $this->httpPost($uri, $this->requestBody);
170
    }
171
172
    /**
173
     * Returns the number of available conversion tokens.
174
     *
175
     * @return int
176
     */
177
    public function availableTokens(): int
178
    {
179
        $username = $this->requestBody['username'];
180
        $uri = $this->api_prefix."/user/{$username}/tokens/";
181
        $arr = [
182
            'username' => $this->requestBody['username'],
183
            'key' => $this->requestBody['key'],
184
        ];
185
186
        $ntokens = $this->httpPost($uri, $arr);
187
188
        $response = (string) $ntokens;
189
190
        return (int) $response;
191
    }
192
193
    /**
194
     * Get the number of tokens used in the last conversion.
195
     * This is only possible if you enable tracking tokens using trackTokens(true).
196
     *
197
     * @see trackTokens()
198
     *
199
     * @return int
200
     * @throws \Swis\PdfcrowdClient\Exceptions\PdfcrowdException
201
     */
202
    public function getUsedTokens(): int
203
    {
204
        if (!$this->track_tokens) {
205
            throw new PdfcrowdException(
206
                'getUsedTokens() only works if you enable tracking tokens with trackTokens(true)'
207
            );
208
        }
209
210
        if ($this->num_tokens_before === false) {
211
            throw new PdfcrowdException(
212
                'getUsedTokens() should not be called on its own, call a convert call first.'
213
            );
214
        }
215
216
        $num_tokens_after = $this->availableTokens();
217
218
        return (int) $this->num_tokens_before - $num_tokens_after;
219
    }
220
221
    /**
222
     * Track how many tokens are available before each request.
223
     * After a request you can ask the number of used tokens with getUsedTokens.
224
     *
225
     * @see getUsedTokens()
226
     *
227
     * @param bool $trackTokens
228
     */
229
    public function trackTokens(bool $trackTokens = true)
230
    {
231
        $this->track_tokens = $trackTokens;
232
    }
233
234
    /**
235
     * Save the pdf to the given output destination. The variable $file_handle will serve as input to
236
     * the sink-option of Guzzle.
237
     *
238
     * @see http://docs.guzzlephp.org/en/stable/request-options.html#sink
239
     *
240
     * @example $pdfcrowd->setOutputDestination(fopen('/path/to/output.pdf', 'w');
241
     *
242
     * @param $file_handle
243
     */
244
    public function setOutputDestination($file_handle)
245
    {
246
        $this->output_destination = $file_handle;
247
    }
248
249
    /**
250
     * Turn SSL on or off.
251
     *
252
     * @param bool $use_ssl
253
     */
254
    public function useSSL(bool $use_ssl)
255
    {
256
        if ($use_ssl) {
257
            $this->port = self::$https_port;
258
            $this->scheme = 'https';
259
        } else {
260
            $this->port = self::$http_port;
261
            $this->scheme = 'http';
262
        }
263
264
        $this->api_prefix = "{$this->scheme}://{$this->hostname}/api";
265
    }
266
267
    public function setPageWidth($value)
268
    {
269
        $this->requestBody['width'] = $value;
270
    }
271
272
    public function setPageHeight($value)
273
    {
274
        $this->requestBody['height'] = $value;
275
    }
276
277
    public function setHorizontalMargin($value)
278
    {
279
        $this->requestBody['margin_right'] = $this->requestBody['margin_left'] = $value;
280
    }
281
282
    public function setVerticalMargin($value)
283
    {
284
        $this->requestBody['margin_top'] = $this->requestBody['margin_bottom'] = $value;
285
    }
286
287
    public function setBottomMargin($value)
288
    {
289
        $this->requestBody['margin_bottom'] = $value;
290
    }
291
292
    public function setPageMargins($top, $right, $bottom, $left)
293
    {
294
        $this->requestBody['margin_top'] = $top;
295
        $this->requestBody['margin_right'] = $right;
296
        $this->requestBody['margin_bottom'] = $bottom;
297
        $this->requestBody['margin_left'] = $left;
298
    }
299
300
    /**
301
     * If value is set to True then the PDF is encrypted. This prevents search engines from indexing the document.
302
     * The default is False.
303
     *
304
     * @param bool $val
305
     */
306
    public function setEncrypted(bool $val = true)
307
    {
308
        $this->setOrUnset($val, 'encrypted');
309
    }
310
311
    /**
312
     * Protects the PDF with a user password. When a PDF has a user password, it must be supplied in order to view the
313
     * document and to perform operations allowed by the access permissions. At most 32 characters.
314
     *
315
     * @param string $pwd
316
     */
317
    public function setUserPassword(string $pwd)
318
    {
319
        $this->setOrUnset($pwd, 'user_pwd');
320
    }
321
322
    /**
323
     * Protects the PDF with an owner password. Supplying an owner password grants unlimited access to the PDF
324
     * including changing the passwords and access permissions. At most 32 characters.
325
     *
326
     * @param string $pwd
327
     */
328
    public function setOwnerPassword(string $pwd)
329
    {
330
        $this->setOrUnset($pwd, 'owner_pwd');
331
    }
332
333
    /**
334
     * Set value to True disables printing the generated PDF. The default is False.
335
     *
336
     * @param bool $val
337
     */
338
    public function setNoPrint(bool $val = true)
339
    {
340
        $this->setOrUnset($val, 'no_print');
341
    }
342
343
    /**
344
     * Set value to True to disable modifying the PDF. The default is False.
345
     *
346
     * @param bool $val
347
     */
348
    public function setNoModify(bool $val = true)
349
    {
350
        $this->setOrUnset($val, 'no_modify');
351
    }
352
353
    /**
354
     * Set value to True to disable extracting text and graphics from the PDF. The default is False.
355
     *
356
     * @param bool $val
357
     */
358
    public function setNoCopy(bool $val = true)
359
    {
360
        $this->setOrUnset($val, 'no_copy');
361
    }
362
363
    /**
364
     * Specifies the initial page layout when the PDF is opened in a viewer.
365
     *
366
     * Possible values:
367
     *   \Swis\PdfcrowdClient\Pdfcrowd::SINGLE_PAGE
368
     *   \Swis\PdfcrowdClient\Pdfcrowd::CONTINUOUS
369
     *   \Swis\PdfcrowdClient\Pdfcrowd::CONTINUOUS_FACING
370
     *
371
     * @param int $value
372
     */
373
    public function setPageLayout(int $value)
374
    {
375
        assert($value > 0 && $value <= 3);
376
        $this->requestBody['page_layout'] = $value;
377
    }
378
379
    /**
380
     * Specifies the appearance of the PDF when opened.
381
     *
382
     * Possible values:
383
     *   \Swis\PdfcrowdClient\Pdfcrowd::NONE_VISIBLE
384
     *   \Swis\PdfcrowdClient\Pdfcrowd::THUMBNAILS_VISIBLE
385
     *   \Swis\PdfcrowdClient\Pdfcrowd::FULLSCREEN
386
     *
387
     * @param int $value
388
     */
389
    public function setPageMode(int $value)
390
    {
391
        assert($value > 0 && $value <= 3);
392
        $this->requestBody['page_mode'] = $value;
393
    }
394
395
    /**
396
     * @param string $value
397
     */
398
    public function setFooterText(string $value)
399
    {
400
        $this->setOrUnset($value, 'footer_text');
401
    }
402
403
    /**
404
     * Set value to False to disable printing images to the PDF. The default is True.
405
     *
406
     * @param bool $value
407
     */
408
    public function enableImages(bool $value = true)
409
    {
410
        $this->setOrUnset(!$value, 'no_images');
411
    }
412
413
    /**
414
     * Set value to False to disable printing backgrounds to the PDF. The default is True.
415
     *
416
     * @param bool $value
417
     */
418
    public function enableBackgrounds(bool $value = true)
419
    {
420
        $this->setOrUnset(!$value, 'no_backgrounds');
421
    }
422
423
    /**
424
     * Set HTML zoom in percents. It determines the precision used for rendering of the HTML content. Despite its name,
425
     * it does not zoom the HTML content. Higher values can improve glyph positioning and can lead to overall better
426
     * visual appearance of generated PDF .The default value is 200.
427
     *
428
     * @see setPdfScalingFactor
429
     *
430
     * @param int $value
431
     */
432
    public function setHtmlZoom(int $value)
433
    {
434
        $this->setOrUnset($value, 'html_zoom');
435
    }
436
437
    /**
438
     * Set value to False to disable JavaScript in web pages. The default is True.
439
     *
440
     * @param bool $value
441
     */
442
    public function enableJavaScript(bool $value = true)
443
    {
444
        $this->setOrUnset(!$value, 'no_javascript');
445
    }
446
447
    /**
448
     * Set value to False to disable hyperlinks in the PDF. The default is True.
449
     *
450
     * @param bool $value
451
     */
452
    public function enableHyperlinks(bool $value = true)
453
    {
454
        $this->setOrUnset(!$value, 'no_hyperlinks');
455
    }
456
457
    /**
458
     * Value is the text encoding used when none is specified in a web page. The default is utf-8.
459
     *
460
     * @param string $value
461
     */
462
    public function setDefaultTextEncoding(string $value)
463
    {
464
        $this->setOrUnset($value, 'text_encoding');
465
    }
466
467
    /**
468
     * If value is True then the print CSS media type is used (if available).
469
     *
470
     * @param bool $value
471
     */
472
    public function usePrintMedia(bool $value = true)
473
    {
474
        $this->setOrUnset($value, 'use_print_media');
475
    }
476
477
    /**
478
     * Prints at most npages pages.
479
     *
480
     * @param int $value
481
     */
482
    public function setMaxPages(int $value)
483
    {
484
        $this->requestBody['max_pages'] = $value;
485
    }
486
487
    /**
488
     * @param bool $value
489
     */
490
    public function enablePdfcrowdLogo(bool $value = true)
491
    {
492
        $this->setOrUnset($value, 'pdfcrowd_logo');
493
    }
494
495
    /**
496
     * value specifies the appearance of the PDF when opened.
497
     *
498
     * Possible values:
499
     *   \Swis\Pdfcrowd\Pdfcrowd::FIT_WIDTH
500
     *   \Swis\Pdfcrowd\Pdfcrowd::FIT_HEIGHT
501
     *   \Swis\Pdfcrowd\Pdfcrowd::FIT_PAGE
502
     *
503
     * @param int $value
504
     */
505
    public function setInitialPdfZoomType(int $value)
506
    {
507
        assert($value > 0 && $value <= 3);
508
        $this->requestBody['initial_pdf_zoom_type'] = $value;
509
    }
510
511
    /**
512
     * value specifies the initial page zoom of the PDF when opened.
513
     *
514
     * @param $value
515
     */
516
    public function setInitialPdfExactZoom($value)
517
    {
518
        $this->requestBody['initial_pdf_zoom_type'] = 4;
519
        $this->requestBody['initial_pdf_zoom'] = $value;
520
    }
521
522
    /**
523
     * The scaling factor used to convert between HTML and PDF. The default value is 1.0.
524
     *
525
     * @param float $value
526
     */
527
    public function setPdfScalingFactor(float $value)
528
    {
529
        $this->requestBody['pdf_scaling_factor'] = $value;
530
    }
531
532
    /**
533
     * Sets the author field in the created PDF.
534
     *
535
     * @param string $value
536
     */
537
    public function setAuthor(string $value)
538
    {
539
        $this->requestBody['author'] = $value;
540
    }
541
542
    /**
543
     * If value is True then the conversion will fail when the source URI returns 4xx or 5xx HTTP status code. The
544
     * default is False.
545
     *
546
     * @param bool $value
547
     */
548
    public function setFailOnNon200(bool $value)
549
    {
550
        $this->requestBody['fail_on_non200'] = $value;
551
    }
552
553
    /**
554
     * Places the specified html code inside the page footer. The following variables are expanded:
555
     *   %u - URL to convert.
556
     *   %p - The current page number.
557
     *   %n - Total number of pages.
558
     *
559
     * @param string $value
560
     */
561
    public function setFooterHtml(string $value)
562
    {
563
        $this->requestBody['footer_html'] = $value;
564
    }
565
566
    /**
567
     * Loads HTML code from the specified url and places it inside the page footer. See setFooterHtml for the list of
568
     * variables that are expanded.
569
     *
570
     * @see setFooterHtml
571
     *
572
     * @param string $value
573
     */
574
    public function setFooterUrl(string $value)
575
    {
576
        $this->requestBody['footer_url'] = $value;
577
    }
578
579
    /**
580
     * Places the specified html code inside the page header. See setFooterHtml for the list of variables that are
581
     * expanded.
582
     *
583
     * @see setFooterHtml
584
     *
585
     * @param string $value
586
     */
587
    public function setHeaderHtml(string $value)
588
    {
589
        $this->requestBody['header_html'] = $value;
590
    }
591
592
    /**
593
     * Loads HTML code from the specified url and places it inside the page header. See setFooterHtml for the list of
594
     * variables that are expanded.
595
     *
596
     * @see setFooterHtml
597
     *
598
     * @param string $value
599
     */
600
    public function setHeaderUrl(string $value)
601
    {
602
        $this->requestBody['header_url'] = $value;
603
    }
604
605
    /**
606
     * The page background color in RRGGBB hexadecimal format.
607
     *
608
     * @param string $value
609
     */
610
    public function setPageBackgroundColor(string $value)
611
    {
612
        $this->requestBody['page_background_color'] = $value;
613
    }
614
615
    /**
616
     * Does not print the body background. Requires the following CSS rule to be declared:
617
     *   body {background-color:rgba(255,255,255,0.0);}
618
     *
619
     * @param bool $value
620
     */
621
    public function setTransparentBackground(bool $value = true)
622
    {
623
        $this->setOrUnset($value, 'transparent_background');
624
    }
625
626
    /**
627
     * An offset between physical and logical page numbers. The default value is 0.
628
     *
629
     * @example if set to "1" then the page numbering will start with 1 on the second page.
630
     *
631
     * @param int $value
632
     */
633
    public function setPageNumberingOffset(int $value)
634
    {
635
        $this->requestBody['page_numbering_offset'] = $value;
636
    }
637
638
    /**
639
     * Value is a comma seperated list of physical page numbers on which the header a footer are not printed. Negative
640
     * numbers count backwards from the last page: -1 is the last page, -2 is the last but one page, and so on.
641
     *
642
     * @example "1,-1" will not print the header and footer on the first and the last page.
643
     *
644
     * @param string $value
645
     */
646
    public function setHeaderFooterPageExcludeList(string $value)
647
    {
648
        $this->requestBody['header_footer_page_exclude_list'] = $value;
649
    }
650
651
    /**
652
     * url is a public absolute URL of the watermark image (must start either with http:// or https://). The supported
653
     * formats are PNG and JPEG. offset_x and offset_y is the watermark offset in units. The default offset is (0,0).
654
     *
655
     * @param string $url
656
     * @param int    $offset_x
657
     * @param int    $offset_y
658
     */
659
    public function setWatermark(string $url, $offset_x = 0, $offset_y = 0)
660
    {
661
        $this->requestBody['watermark_url'] = $url;
662
        $this->requestBody['watermark_offset_x'] = $offset_x;
663
        $this->requestBody['watermark_offset_y'] = $offset_y;
664
    }
665
666
    /**
667
     * Rotates the watermark by angle degrees.
668
     *
669
     * @param int $angle
670
     */
671
    public function setWatermarkRotationsetWatermarkRotation(int $angle)
672
    {
673
        $this->requestBody['watermark_rotation'] = $angle;
674
    }
675
676
    /**
677
     * When value is set to True then the watermark is be placed in the background. By default, the watermark is
678
     * placed in the foreground.
679
     *
680
     * @param bool $val
681
     */
682
    public function setWatermarkInBackground(bool $val = true)
683
    {
684
        $this->setOrUnset($val, 'watermark_in_background');
685
    }
686
687
    /**
688
     * @param string $proxyname
689
     * @param int    $port
690
     * @param string $username
691
     * @param string $password
692
     */
693
    public function setProxy(string $proxyname, int $port, string $username = '', string $password = '')
694
    {
695
        $this->proxy_name = $proxyname;
696
        $this->proxy_port = $port;
697
        $this->proxy_username = $username;
698
        $this->proxy_password = $password;
699
    }
700
701
    /**
702
     * @param string $user_agent
703
     */
704
    public function setUserAgent(string $user_agent)
705
    {
706
        $this->user_agent = $user_agent;
707
    }
708
709
    /**
710
     * @param int $timeout
711
     */
712
    public function setTimeout(int $timeout)
713
    {
714
        if (is_int($timeout) && $timeout > 0) {
715
            $this->curlopt_timeout = $timeout;
716
        }
717
    }
718
719
    /**
720
     * @param string $url
721
     * @param array  $requestBody
722
     *
723
     * @return mixed
724
     * @throws \Swis\PdfcrowdClient\Exceptions\PdfcrowdException
725
     */
726
    private function httpPost(string $url, array $requestBody)
727
    {
728
        $this->request = $this->buildRequest($url, $requestBody);
729
730
        try {
731
            $response = $this->request->execute();
732
733
            $this->http_code = $this->request->getHttpStatusCode();
734
        } catch (\Exception $e) {
735
            throw new PdfcrowdException("Unknown error during request to Pdfcrowd", 0, $e);
736
        }
737
738
        if ($this->http_code !== 200) {
739
            throw new PdfcrowdException((string) $response, $this->http_code);
740
        }
741
742
        return $response;
743
    }
744
745
    protected function buildRequest(string $url, array $requestBody): RequestInterface
746
    {
747
        $request = $this->getNewRequestObject();
748
749
        $request->setUserAgent($this->user_agent);
750
751
        if (isset($this->curlopt_timeout)) {
752
            $request->setTimeout($this->curlopt_timeout);
753
        }
754
755
        if ($this->scheme == 'https' && self::$api_host == 'pdfcrowd.com') {
756
            $request->setVerifySsl(true);
757
        } else {
758
            $request->setVerifySsl(false);
759
        }
760
761
        if ($this->proxy_name) {
762
            $request->setProxy($this->proxy_name, $this->proxy_port);
763
            if ($this->proxy_username) {
764
                $request->setProxyAuth($this->proxy_username, $this->proxy_password);
765
            }
766
        }
767
768
        $request->setUrl($url);
769
770
        $request->setPort($this->port);
771
772
        $request->setBody($requestBody);
773
774
        if (isset($this->output_destination)) {
775
            $request->setOutputDestination($this->output_destination);
776
        }
777
778
        return $request;
779
    }
780
781
    /**
782
     * Set or unset a parameter that will be sent with the request to the pdfcrowd API.
783
     *
784
     * @param mixed $val
785
     * @param string $field
786
     */
787
    private function setOrUnset($val, string $field)
788
    {
789
        if ($val) {
790
            $this->requestBody[$field] = $val;
791
        } else {
792
            unset($this->requestBody[$field]);
793
        }
794
    }
795
}
796