-
Notifications
You must be signed in to change notification settings - Fork 1
/
BaseConverter.php
154 lines (138 loc) · 4.57 KB
/
BaseConverter.php
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
<?php
namespace boundstate\htmlconverter;
use yii\base\Component;
use yii\base\Exception;
use yii\helpers\FileHelper;
use Yii;
/**
* BaseConverter is the base class for converting HTML to PDF or images using wkhtmtox.
* @link http://wkhtmltopdf.org/
*
* @author Bound State Software <info@boundstatesoftware.com>
*/
abstract class BaseConverter extends Component
{
/**
* @var string path to the binary
*/
public $bin;
/**
* @var array default command line options
*/
public $options = [];
/**
* @var string the directory to store temporary files during conversion. You may use path alias here.
* If not set, it will use the "htmlconverter" subdirectory under the application runtime path.
*/
public $tempPath = '@runtime/htmlconverter';
/**
* @var integer the permission to be set for newly created cache files.
* This value will be used by PHP chmod() function. No umask will be applied.
* If not set, the permission will be determined by the current environment.
*/
public $fileMode;
/**
* @var integer the permission to be set for newly created directories.
* This value will be used by PHP chmod() function. No umask will be applied.
* Defaults to 0775, meaning the directory is read-writable by owner and group,
* but read-only for other users.
*/
public $dirMode = 0775;
/**
* Initializes the converter and ensures the temp path exists.
*/
public function init()
{
parent::init();
$this->tempPath = Yii::getAlias($this->tempPath);
if (!is_dir($this->tempPath)) {
FileHelper::createDirectory($this->tempPath, $this->dirMode, true);
}
}
/**
* Converts the HTML to the destination format.
* @param string $html HTML
* @param array $options
* @return mixed
*/
public abstract function convert($html, $options = []);
/**
* Creates a temporary HTML file.
* @param string $html
* @param string $htmlFilename filename
* @return bool
*/
protected function createHtmlFile($html, $htmlFilename)
{
if (@file_put_contents($htmlFilename, $html, LOCK_EX) !== false) {
if ($this->fileMode !== null) {
@chmod($htmlFilename, $this->fileMode);
}
return true;
} else {
return false;
}
}
/**
* Runs the command.
* @param string $htmlFilename HTML filename
* @param string $destFilename destination filename
* @param array $options
* @throws Exception
*/
protected function runCommand($htmlFilename, $destFilename, $options = [])
{
$command = $this->getCommand($htmlFilename, $destFilename, $options);
Yii::trace("Running command: $command", __METHOD__);
// Using proc_open with pipes can cause issues on Windows (https://bugs.php.net/bug.php?id=51800)
// Write STDOUT and STDERR to files instead
$stdout = $this->getTempFilename('log');
$stderr = $this->getTempFilename('log');
$process = proc_open($command, [1 => ['file', $stdout, 'a'], 2 => ['file', $stderr, 'a']], $pipes);
if (!is_resource($process))
throw new Exception("Could not run command $command");
$result = proc_close($process);
// Clean up
$output = trim(file_get_contents($stdout) . file_get_contents($stderr));
@unlink($stdout);
@unlink($stderr);
if ($result === 0) {
Yii::info($output, __METHOD__);
} else {
Yii::error($output, __METHOD__);
}
}
/**
* Returns the command to run.
* @param string $htmlFilename
* @param string $destFilename
* @param array $options
* @return string
*/
protected function getCommand($htmlFilename, $destFilename, $options = [])
{
return $this->bin . ' ' . $this->getCommandOptions($options) . ' ' . $htmlFilename . ' ' . $destFilename;
}
/**
* Returns options string for the command.
* @param array $options
* @return string
*/
protected function getCommandOptions($options)
{
$out = '';
foreach ($options as $key => $val) {
$out .= is_numeric($key) ? " --$val" : " --$key $val";
}
return $out;
}
/**
* Returns a temporary filename.
* @param string $extension file extension
* @return string
*/
protected function getTempFilename($extension)
{
return $this->tempPath . DIRECTORY_SEPARATOR . uniqid('', true) . '.' . $extension;
}
}