WkhtmlToPdfRenderer::buildCommand()   F
last analyzed

Complexity

Conditions 14
Paths 540

Size

Total Lines 60
Code Lines 40

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 33
CRAP Score 14.2475

Importance

Changes 0
Metric Value
eloc 40
dl 0
loc 60
ccs 33
cts 37
cp 0.8919
rs 2.7388
c 0
b 0
f 0
cc 14
nc 540
nop 1
crap 14.2475

How to fix   Long Method    Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php
2
declare(strict_types = 1);
3
4
namespace Phauthentic\Presentation\Renderer;
5
6
use InvalidArgumentException;
7
use Phauthentic\Presentation\View\PdfViewInterface;
8
use Phauthentic\Presentation\View\ViewInterface;
9
use RuntimeException;
10
11
/**
12
 * WkhtmlToPdf Renderer
13
 */
14
class WkhtmlToPdfRenderer
15
{
16
    /**
17
     * Binary
18
     *
19
     * @var string
20
     */
21
    protected $binary = '/usr/bin/wkhtmltopdf';
22
23
    /**
24
     * Is it running on windows
25
     *
26
     * @var bool
27
     */
28
    protected $isWindowsEnvironment = false;
29
30
    /**
31
     * Cwd for phps proc_open fourth argument
32
     *
33
     * @var string|null
34
     */
35
    protected $cwd = null;
36
37
    /**
38
     * Sets the path for the wkhtmltopdf binary
39
     *
40
     * @return $this
41
     */
42
    public function setBinary(string $binary): self
43
    {
44
        if (!file_exists($binary)) {
45
            throw new InvalidArgumentException(sprintf('Binary %s does not exist', $binary));
46
        }
47
48
        if (!is_executable($binary)) {
49
            throw new RuntimeException(sprintf('%s not a binary or can not be executed', $binary));
50
        }
51
52
        $this->binary = $binary;
53
54
        return $this;
55
    }
56
57
    /**
58
     * Constructor
59
     *
60
     * @param array $options Options
61
     */
62 1
    public function __construct(array $options = [])
63
    {
64 1
        $this->options = $options;
0 ignored issues
show
Bug Best Practice introduced by
The property options does not exist. Although not strictly required by PHP, it is generally a best practice to declare properties explicitly.
Loading history...
65 1
        $this->cwd = sys_get_temp_dir();
66 1
        $this->isWindowsEnvironment = strtoupper(substr(PHP_OS, 0, 3)) === 'WIN';
67
68 1
        if ($this->isWindowsEnvironment) {
69
            $this->setBinary('C:/Progra~1/wkhtmltopdf/bin/wkhtmltopdf.exe');
70
        }
71 1
    }
72
73
    /**
74
     * Generates Pdf from html
75
     *
76
     * @return string Raw PDF data
77
     * @throws \Exception If no output is generated to stdout by wkhtmltopdf.
78
     */
79 1
    public function render(PdfViewInterface $view): string
80
    {
81 1
        $command = $this->buildCommand($view);
82 1
        $content = $this->exec($command, $view->getHtml());
0 ignored issues
show
Bug introduced by
The method getHtml() does not exist on Phauthentic\Presentation\View\PdfViewInterface. Since it exists in all sub-types, consider adding an abstract or default implementation to Phauthentic\Presentation\View\PdfViewInterface. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

82
        $content = $this->exec($command, $view->/** @scrutinizer ignore-call */ getHtml());
Loading history...
83
84 1
        if (!empty($content['stdout'])) {
85 1
            return $content['stdout'];
86
        }
87
88
        if (!empty($content['stderr'])) {
89
            throw new RuntimeException(sprintf(
90
                'System error "%s" when executing command "%s". ' .
91
                'Try using the binary provided on http://wkhtmltopdf.org/downloads.html',
92
                $content['stderr'],
93
                $command
94
            ));
95
        }
96
97
        throw new RuntimeException("WKHTMLTOPDF didn't return any data");
98
    }
99
100
    /**
101
     * Execute the WkHtmlToPdf commands for rendering pdfs
102
     *
103
     * @param string $cmd the command to execute
104
     * @param string $input Html to pass to wkhtmltopdf
105
     * @return array the result of running the command to generate the pdf
106
     */
107 1
    protected function exec($cmd, $input)
108
    {
109 1
        $result = ['stdout' => '', 'stderr' => '', 'return' => ''];
110
111 1
        $proc = proc_open($cmd, [0 => ['pipe', 'r'], 1 => ['pipe', 'w'], 2 => ['pipe', 'w']], $pipes, $this->cwd);
112 1
        fwrite($pipes[0], $input);
113 1
        fclose($pipes[0]);
114
115 1
        $result['stdout'] = stream_get_contents($pipes[1]);
116 1
        fclose($pipes[1]);
117
118 1
        $result['stderr'] = stream_get_contents($pipes[2]);
119 1
        fclose($pipes[2]);
120
121 1
        $result['return'] = proc_close($proc);
0 ignored issues
show
Bug introduced by
It seems like $proc can also be of type false; however, parameter $process of proc_close() does only seem to accept resource, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

121
        $result['return'] = proc_close(/** @scrutinizer ignore-type */ $proc);
Loading history...
122
123 1
        return $result;
124
    }
125
126
    /**
127
     * Get the command to render a pdf
128
     *
129
     *
130
     * @return string the command for generating the pdf
131
     */
132 1
    protected function buildCommand(PdfViewInterface $pdfView): string
133
    {
134
        $options = [
135 1
            'quiet' => true,
136
            'print-media-type' => true,
137 1
            'orientation' => $pdfView->getOrientation(),
138 1
            'page-size' => $pdfView->getPageSize(),
139 1
            'encoding' => $pdfView->getEncoding(),
140 1
            'title' => $pdfView->getTitle(),
0 ignored issues
show
Bug introduced by
The method getTitle() does not exist on Phauthentic\Presentation\View\PdfViewInterface. Since it exists in all sub-types, consider adding an abstract or default implementation to Phauthentic\Presentation\View\PdfViewInterface. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

140
            'title' => $pdfView->/** @scrutinizer ignore-call */ getTitle(),
Loading history...
141 1
            'javascript-delay' => $pdfView->getJsDelay(),
0 ignored issues
show
Bug introduced by
The method getJsDelay() does not exist on Phauthentic\Presentation\View\PdfViewInterface. Since it exists in all sub-types, consider adding an abstract or default implementation to Phauthentic\Presentation\View\PdfViewInterface. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

141
            'javascript-delay' => $pdfView->/** @scrutinizer ignore-call */ getJsDelay(),
Loading history...
142 1
            'window-status' => $pdfView->getWindowStatus(),
0 ignored issues
show
Bug introduced by
The method getWindowStatus() does not exist on Phauthentic\Presentation\View\PdfViewInterface. Since it exists in all sub-types, consider adding an abstract or default implementation to Phauthentic\Presentation\View\PdfViewInterface. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

142
            'window-status' => $pdfView->/** @scrutinizer ignore-call */ getWindowStatus(),
Loading history...
143
        ];
144
145 1
        $margin = $pdfView->getMargin();
0 ignored issues
show
Bug introduced by
The method getMargin() does not exist on Phauthentic\Presentation\View\PdfViewInterface. Since it exists in all sub-types, consider adding an abstract or default implementation to Phauthentic\Presentation\View\PdfViewInterface. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

145
        /** @scrutinizer ignore-call */ 
146
        $margin = $pdfView->getMargin();
Loading history...
146 1
        foreach ($margin as $key => $value) {
147 1
            if ($value !== null) {
148 1
                $options['margin-' . $key] = $value . 'mm';
149
            }
150
        }
151 1
        $options = array_merge($options, (array)$this->options);
152
153 1
        if ($this->isWindowsEnvironment) {
154
            $command = '"' . $this->binary . '"';
155
        } else {
156 1
            $command = $this->binary;
157
        }
158
159 1
        foreach ($options as $key => $value) {
160 1
            if (empty($value)) {
161 1
                continue;
162 1
            } elseif (is_array($value)) {
163
                foreach ($value as $k => $v) {
164
                    $command .= sprintf(' --%s %s %s', $key, escapeshellarg($k), escapeshellarg($v));
165
                }
166 1
            } elseif ($value === true) {
167 1
                $command .= ' --' . $key;
168
            } else {
169 1
                $command .= sprintf(' --%s %s', $key, escapeshellarg($value));
170
            }
171
        }
172 1
        $footer = $pdfView->footer();
0 ignored issues
show
Bug introduced by
The method footer() does not exist on Phauthentic\Presentation\View\PdfViewInterface. Since it exists in all sub-types, consider adding an abstract or default implementation to Phauthentic\Presentation\View\PdfViewInterface. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

172
        /** @scrutinizer ignore-call */ 
173
        $footer = $pdfView->footer();
Loading history...
173 1
        foreach ($footer as $location => $text) {
174 1
            if ($text !== null) {
175 1
                $command .= " --footer-$location \"" . addslashes($text) . "\"";
176
            }
177
        }
178
179 1
        $header = $pdfView->header();
0 ignored issues
show
Bug introduced by
The method header() does not exist on Phauthentic\Presentation\View\PdfViewInterface. Since it exists in all sub-types, consider adding an abstract or default implementation to Phauthentic\Presentation\View\PdfViewInterface. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

179
        /** @scrutinizer ignore-call */ 
180
        $header = $pdfView->header();
Loading history...
180 1
        foreach ($header as $location => $text) {
181 1
            if ($text !== null) {
182 1
                $command .= " --header-$location \"" . addslashes($text) . "\"";
183
            }
184
        }
185 1
        $command .= " - -";
186
187 1
        if ($this->isWindowsEnvironment) {
188
            $command = '"' . $command . '"';
189
        }
190
191 1
        return $command;
192
    }
193
}
194