PageRenderTime 189ms CodeModel.GetById 21ms RepoModel.GetById 2ms app.codeStats 0ms

/wp-content/themes/selah2018/jsp_inc/vendor/mikehaertl/phpwkhtmltopdf/src/Pdf.php

https://gitlab.com/code26/selah
PHP | 315 lines | 157 code | 32 blank | 126 comment | 30 complexity | 95405b0a731b2e9de8f059debb97ba08 MD5 | raw file
  1. <?php
  2. namespace mikehaertl\wkhtmlto;
  3. use mikehaertl\tmp\File;
  4. /**
  5. * Pdf
  6. *
  7. * This class is a slim wrapper around wkhtmltopdf.
  8. *
  9. * @author Michael Härtl <haertl.mike@gmail.com>
  10. * @version 2.2.0
  11. * @license http://www.opensource.org/licenses/MIT
  12. */
  13. class Pdf
  14. {
  15. // Type hints for `addPage()` and `addCover()`
  16. const TYPE_HTML = 'html';
  17. const TYPE_XML = 'xml';
  18. // Regular expression to detect HTML strings
  19. const REGEX_HTML = '/<(?:!doctype )?html/i';
  20. // Regular expression to detect XML strings
  21. const REGEX_XML = '/<\??xml/i';
  22. // prefix for tmp files
  23. const TMP_PREFIX = 'tmp_wkhtmlto_pdf_';
  24. /**
  25. * @var string the name of the `wkhtmltopdf` binary. Default is `wkhtmltopdf`. You can also
  26. * configure a full path here.
  27. */
  28. public $binary = 'wkhtmltopdf';
  29. /**
  30. * @var array options to pass to the Command constructor. Default is none.
  31. */
  32. public $commandOptions = array();
  33. /**
  34. * @var string|null the directory to use for temporary files. If null (default) the dir is autodetected.
  35. */
  36. public $tmpDir;
  37. /**
  38. * @var bool whether to ignore any errors if some PDF file was still created. Default is false.
  39. */
  40. public $ignoreWarnings = false;
  41. /**
  42. * @var bool whether the old version 9 of wkhtmltopdf is used (slightly different syntax). Default is false.
  43. */
  44. public $version9 = false;
  45. /**
  46. * @var bool whether the PDF was created
  47. */
  48. protected $_isCreated = false;
  49. /**
  50. * @var array global options for wkhtmltopdf as array('--opt1', '--opt2'=>'val', ...)
  51. */
  52. protected $_options = array();
  53. /**
  54. * @var array list of wkhtmltopdf objects as arrays
  55. */
  56. protected $_objects = array();
  57. /**
  58. * @var \mikehaertl\tmp\File the temporary PDF file
  59. */
  60. protected $_tmpPdfFile;
  61. /**
  62. * @var array list of tmp file objects. This is here to keep a reference to File and thus avoid
  63. * too early call of File::__destruct() if the file is not referenced anymore.
  64. */
  65. protected $_tmpFiles = array();
  66. /**
  67. * @var Command the command instance that executes wkhtmltopdf
  68. */
  69. protected $_command;
  70. /**
  71. * @var string the detailed error message. Empty string if none.
  72. */
  73. protected $_error = '';
  74. /**
  75. * @param array|string $options global options for wkhtmltopdf or page URL, HTML or PDF/HTML filename
  76. */
  77. public function __construct($options=null)
  78. {
  79. if (is_array($options)) {
  80. $this->setOptions($options);
  81. } elseif (is_string($options)) {
  82. $this->addPage($options);
  83. }
  84. }
  85. /**
  86. * Add a page object to the output
  87. *
  88. * @param string $input either a URL, a HTML string or a PDF/HTML filename
  89. * @param array $options optional options for this page
  90. * @param string|null $type a type hint if the input is a string of known type. This can either be
  91. * `TYPE_HTML` or `TYPE_XML`. If `null` (default) the type is auto detected from the string content.
  92. * @return static the Pdf instance for method chaining
  93. */
  94. public function addPage($input, $options=array(), $type=null)
  95. {
  96. $options = $this->processOptions($options);
  97. $options['inputArg'] = $this->processInput($input, $type);
  98. $this->_objects[] = $options;
  99. return $this;
  100. }
  101. /**
  102. * Add a cover page object to the output
  103. *
  104. * @param string $input either a URL, a HTML string or a PDF/HTML filename
  105. * @param array $options optional options for the cover page
  106. * @param string|null $type a type hint if the input is a string of known type. This can either be
  107. * `TYPE_HTML` or `TYPE_XML`. If `null` (default) the type is auto detected from the string content.
  108. * @return static the Pdf instance for method chaining
  109. */
  110. public function addCover($input, $options=array(), $type=null)
  111. {
  112. $options['input'] = ($this->version9 ? '--' : '').'cover';
  113. $options['inputArg'] = $this->processInput($input, $type);
  114. $this->_objects[] = $options;
  115. return $this;
  116. }
  117. /**
  118. * Add a TOC object to the output
  119. *
  120. * @param array $options optional options for the table of contents
  121. * @return static the Pdf instance for method chaining
  122. */
  123. public function addToc($options=array())
  124. {
  125. $options['input'] = ($this->version9 ? '--' : '')."toc";
  126. $this->_objects[] = $options;
  127. return $this;
  128. }
  129. /**
  130. * Save the PDF to given filename (triggers PDF creation)
  131. *
  132. * @param string $filename to save PDF as
  133. * @return bool whether PDF was created successfully
  134. */
  135. public function saveAs($filename)
  136. {
  137. if (!$this->_isCreated && !$this->createPdf()) {
  138. return false;
  139. }
  140. if (!$this->_tmpPdfFile->saveAs($filename)) {
  141. $this->_error = "Could not save PDF as '$filename'";
  142. return false;
  143. }
  144. return true;
  145. }
  146. /**
  147. * Send PDF to client, either inline or as download (triggers PDF creation)
  148. *
  149. * @param string|null $filename the filename to send. If empty, the PDF is streamed inline.
  150. * @param bool $inline whether to force inline display of the PDF, even if filename is present.
  151. * @return bool whether PDF was created successfully
  152. */
  153. public function send($filename=null,$inline=false)
  154. {
  155. if (!$this->_isCreated && !$this->createPdf()) {
  156. return false;
  157. }
  158. $this->_tmpPdfFile->send($filename, 'application/pdf', $inline);
  159. return true;
  160. }
  161. /**
  162. * Get the raw PDF contents (triggers PDF creation).
  163. * @return string|bool The PDF content as a string or `false` if the PDF wasn't created successfully.
  164. */
  165. public function toString()
  166. {
  167. if (!$this->_isCreated && !$this->createPdf()) {
  168. return false;
  169. }
  170. return file_get_contents($this->_tmpPdfFile->getFileName());
  171. }
  172. /**
  173. * Set global option(s)
  174. *
  175. * @param array $options list of global PDF options to set as name/value pairs
  176. * @return static the Pdf instance for method chaining
  177. */
  178. public function setOptions($options=array())
  179. {
  180. $options = $this->processOptions($options);
  181. foreach ($options as $key=>$val) {
  182. if (is_int($key)) {
  183. $this->_options[] = $val;
  184. } elseif ($key[0]!=='_' && property_exists($this, $key)) {
  185. $this->$key = $val;
  186. } else {
  187. $this->_options[$key] = $val;
  188. }
  189. }
  190. return $this;
  191. }
  192. /**
  193. * @return Command the command instance that executes wkhtmltopdf
  194. */
  195. public function getCommand()
  196. {
  197. if ($this->_command===null) {
  198. $options = $this->commandOptions;
  199. if (!isset($options['command'])) {
  200. $options['command'] = $this->binary;
  201. }
  202. $this->_command = new Command($options);
  203. }
  204. return $this->_command;
  205. }
  206. /**
  207. * @return string the detailed error message. Empty string if none.
  208. */
  209. public function getError()
  210. {
  211. return $this->_error;
  212. }
  213. /**
  214. * @return string the filename of the temporary PDF file
  215. */
  216. public function getPdfFilename()
  217. {
  218. if ($this->_tmpPdfFile===null) {
  219. $this->_tmpPdfFile = new File('', '.pdf', self::TMP_PREFIX, $this->tmpDir);
  220. }
  221. return $this->_tmpPdfFile->getFileName();
  222. }
  223. /**
  224. * Run the Command to create the tmp PDF file
  225. *
  226. * @return bool whether creation was successful
  227. */
  228. protected function createPdf()
  229. {
  230. if ($this->_isCreated) {
  231. return false;
  232. }
  233. $command = $this->getCommand();
  234. $fileName = $this->getPdfFilename();
  235. $command->addArgs($this->_options);
  236. foreach ($this->_objects as $object) {
  237. $command->addArgs($object);
  238. }
  239. $command->addArg($fileName, null, true); // Always escape filename
  240. if (!$command->execute()) {
  241. $this->_error = $command->getError();
  242. if (!(file_exists($fileName) && filesize($fileName)!==0 && $this->ignoreWarnings)) {
  243. return false;
  244. }
  245. }
  246. $this->_isCreated = true;
  247. return true;
  248. }
  249. /**
  250. * @param string $input
  251. * @param string|null $type a type hint if the input is a string of known type. This can either be
  252. * `TYPE_HTML` or `TYPE_XML`. If `null` (default) the type is auto detected from the string content.
  253. * @return \mikehaertl\tmp\File|string a File object if the input is a HTML or XML string. The unchanged input otherwhise.
  254. */
  255. protected function processInput($input, $type=null)
  256. {
  257. if ($type===self::TYPE_HTML || $type===null && preg_match(self::REGEX_HTML, $input)) {
  258. return $this->_tmpFiles[] = new File($input, '.html', self::TMP_PREFIX, $this->tmpDir);
  259. } elseif ($type===self::TYPE_XML || preg_match(self::REGEX_XML, $input)) {
  260. return $this->_tmpFiles[] = new File($input, '.xml', self::TMP_PREFIX, $this->tmpDir);
  261. } else {
  262. return $input;
  263. }
  264. }
  265. /**
  266. * @param array $options list of options as name/value pairs
  267. * @return array options with raw content converted to tmp files where neccessary
  268. */
  269. protected function processOptions($options=array())
  270. {
  271. foreach ($options as $key=>$val) {
  272. // header-/footer-html expect a URL or a file name, so we need to create a tmp file for HTML content
  273. if (is_string($val) && preg_match('/^(header|footer)-html$/', $key)) {
  274. defined('PHP_MAXPATHLEN') || define('PHP_MAXPATHLEN', 255);
  275. $isFile = (strlen($val) <= PHP_MAXPATHLEN) ? is_file($val) : false;
  276. if (!($isFile || preg_match('/^(https?:)?\/\//i',$val) || $val===strip_tags($val))) {
  277. $options[$key] = new File($val, '.html', self::TMP_PREFIX, $this->tmpDir);
  278. }
  279. }
  280. }
  281. return $options;
  282. }
  283. }