PageRenderTime 42ms CodeModel.GetById 6ms RepoModel.GetById 0ms app.codeStats 1ms

/modules/sale/general/pdf.php

https://gitlab.com/alexprowars/bitrix
PHP | 453 lines | 383 code | 62 blank | 8 comment | 46 complexity | 6f88ed6b0e062ca3f62f9e1e4057ec40 MD5 | raw file
  1. <?
  2. define('FPDF_FONTPATH', $_SERVER["DOCUMENT_ROOT"]."/bitrix/fonts/");
  3. require($_SERVER["DOCUMENT_ROOT"]."/bitrix/modules/sale/general/tfpdf/tfpdf.php");
  4. class CSaleTfpdf extends tFPDF
  5. {
  6. private $background;
  7. public function SetBackground($image, $bgHeight = 0, $bgWidth = 0, $style = 'none')
  8. {
  9. if (!in_array($style, array('none', 'tile', 'stretch')))
  10. $style = 'none';
  11. if ($image && $bgHeight && $bgWidth)
  12. {
  13. $this->background = array(
  14. 'image' => $image,
  15. 'height' => $bgHeight,
  16. 'width' => $bgWidth,
  17. 'style' => $style
  18. );
  19. }
  20. }
  21. public function Image($file, $x = null, $y = null, $w = 0, $h = 0, $type = '', $link = '')
  22. {
  23. try
  24. {
  25. return parent::Image($file, $x, $y, $w, $h, $type, $link);
  26. }
  27. catch (Exception $e)
  28. {
  29. }
  30. }
  31. public function Header()
  32. {
  33. if (!empty($this->background))
  34. {
  35. switch ($this->background['style'])
  36. {
  37. case 'none':
  38. $this->Image($this->background['image'], 0, 0);
  39. break;
  40. case 'tile':
  41. $y = 0;
  42. while ($y <= $this->GetPageHeight())
  43. {
  44. $x = 0;
  45. while ($x <= $this->GetPageWidth())
  46. {
  47. $this->Image($this->background['image'], $x, $y);
  48. $x += $this->background['width'];
  49. }
  50. $y += $this->background['height'];
  51. }
  52. break;
  53. case 'stretch':
  54. $this->Image(
  55. $this->background['image'],
  56. 0, 0,
  57. $this->GetPageWidth(), $this->GetPageHeight()
  58. );
  59. break;
  60. }
  61. }
  62. }
  63. public function GetPageWidth()
  64. {
  65. return $this->w;
  66. }
  67. public function GetPageHeight()
  68. {
  69. return $this->h;
  70. }
  71. public function Output($name = '', $dest = '', $utfName = '')
  72. {
  73. // invalid symbols: "%*:<>?| and \x00-\x1F\x7F and \x80-\xFF
  74. $name = preg_replace('/[\x00-\x1F\x22\x25\x2A\x3A\x3C\x3E\x3F\x7C\x7F-\xFF]+/', '', $name);
  75. $name = str_replace('\\', '/', $name);
  76. if (in_array($dest, array('I', 'D')))
  77. $name = basename($name);
  78. return parent::Output($name, $dest, $utfName);
  79. }
  80. function _parsebmp($file)
  81. {
  82. // Extract info from a BMP file (via PNG conversion)
  83. if(!function_exists('imagepng'))
  84. $this->Error('GD extension is required for BMP support');
  85. $im = CFile::ImageCreateFromBMP($file);
  86. if(!$im)
  87. $this->Error('Missing or incorrect image file: '.$file);
  88. imageinterlace($im,0);
  89. $f = @fopen('php://temp','rb+');
  90. if($f)
  91. {
  92. // Perform conversion in memory
  93. ob_start();
  94. imagepng($im);
  95. $data = ob_get_clean();
  96. imagedestroy($im);
  97. fwrite($f,$data);
  98. rewind($f);
  99. $info = $this->_parsepngstream($f,$file);
  100. fclose($f);
  101. }
  102. else
  103. {
  104. // Use temporary file
  105. $tmp = tempnam('.','gif');
  106. if(!$tmp)
  107. $this->Error('Unable to create a temporary file');
  108. if(!imagepng($im,$tmp))
  109. $this->Error('Error while saving to temporary file');
  110. imagedestroy($im);
  111. $info = $this->_parsepng($tmp);
  112. unlink($tmp);
  113. }
  114. return $info;
  115. }
  116. public function calculateRowsWidth($cols, $cells, $countItems, $docWidth, $margin = null)
  117. {
  118. $eps = 1E-05;
  119. $arRowsWidth = array();
  120. $arRowsContentWidth = array();
  121. if ($margin === null || $margin < 0)
  122. {
  123. $margin = 5;
  124. }
  125. else
  126. {
  127. $margin = (int)$margin;
  128. }
  129. // last columns always digital
  130. end($cols);
  131. $lastColumn = key($cols);
  132. $cols[$lastColumn]['IS_DIGIT'] = true;
  133. $digitColumns = [];
  134. $digitWidth = 0;
  135. $digitColumnFullWidth = [];
  136. foreach ($cols as $columnId => $column)
  137. {
  138. $max = $this->GetStringWidth($this->getMaximumWord($column['NAME']) . " ");
  139. foreach ($cells as $i => $cell)
  140. {
  141. $maxLengthWord = $cell[$columnId];
  142. if ($cols[$columnId]['IS_DIGIT'] !== true)
  143. {
  144. $maxLengthWord = $this->getMaximumWord($cell[$columnId]) . " ";
  145. }
  146. if ($i <= $countItems || $lastColumn === $columnId)
  147. {
  148. $max = max($max, $this->GetStringWidth($maxLengthWord));
  149. }
  150. }
  151. $arRowsWidth[$columnId] = $max + $margin * 2;
  152. $arRowsContentWidth[$columnId] = $max;
  153. if ($cols[$columnId]['IS_DIGIT'] === true)
  154. {
  155. $digitWidth += $arRowsWidth[$columnId];
  156. $digitColumns[] = $columnId;
  157. $columnWith = $this->GetStringWidth($column['NAME']);
  158. $digitColumnFullWidth[$columnId] = ($columnWith > $arRowsWidth[$columnId]) ? $columnWith : $arRowsWidth[$columnId];
  159. }
  160. }
  161. $noDigitWidth = array_sum($arRowsWidth) - $digitWidth;
  162. $requiredWidth = $docWidth - $digitWidth;
  163. if ($noDigitWidth - $requiredWidth > $eps)
  164. {
  165. $colNameTitle = $this->GetStringWidth($cols['NAME']['NAME']);
  166. if ($colNameTitle < $requiredWidth)
  167. {
  168. $arRowsWidth['NAME'] = $requiredWidth;
  169. $arRowsContentWidth['NAME'] = $requiredWidth - $margin * 2;
  170. }
  171. $noDigitWidth = array_sum($arRowsWidth) - $digitWidth;
  172. if ($noDigitWidth - $requiredWidth > $eps)
  173. {
  174. if (!in_array($lastColumn, $digitColumns))
  175. {
  176. $digitColumns[] = $lastColumn;
  177. }
  178. $digitWidth = 0;
  179. foreach ($digitColumns as $columnId)
  180. {
  181. if (!isset($cols[$columnId]))
  182. continue;
  183. $max = $this->GetStringWidth($this->getMaximumWord($cols[$columnId]['NAME']) . " ");
  184. foreach ($cells as $i => $cell)
  185. {
  186. if ($i <= $countItems || $lastColumn === $columnId)
  187. {
  188. $max = max($max, $this->GetStringWidth($cell[$columnId]));
  189. }
  190. }
  191. $arRowsWidth[$columnId] = $max + $margin * 2;
  192. $arRowsContentWidth[$columnId] = $max;
  193. $digitWidth += $arRowsWidth[$columnId];
  194. }
  195. $requiredWidth = $docWidth - $digitWidth;
  196. }
  197. }
  198. $additionalWidth = $requiredWidth / count($digitColumns);
  199. reset($cols);
  200. $firstColumnKey = key($cols);
  201. $digitWidth = 0;
  202. $onlyDigit = true;
  203. foreach ($arRowsWidth as $columnId => $rowWidth)
  204. {
  205. if ($columnId === $firstColumnKey
  206. && $cols[$columnId]['IS_DIGIT']
  207. )
  208. {
  209. $digitWidth += $arRowsWidth[$columnId];
  210. continue;
  211. }
  212. if (isset($digitColumnFullWidth[$columnId]))
  213. {
  214. $width = $arRowsWidth[$columnId] + $additionalWidth;
  215. if ($width > ($digitColumnFullWidth[$columnId] + $margin * 2))
  216. {
  217. $arRowsWidth[$columnId] = $digitColumnFullWidth[$columnId] + $margin * 2;
  218. }
  219. else
  220. {
  221. $arRowsWidth[$columnId] = $width + $margin * 2;
  222. }
  223. }
  224. if ($cols[$columnId]['IS_DIGIT'] === true)
  225. {
  226. $digitWidth += $arRowsWidth[$columnId];
  227. }
  228. else
  229. {
  230. $onlyDigit = false;
  231. }
  232. }
  233. $requiredWidth = $docWidth - $digitWidth;
  234. if ($requiredWidth > 0)
  235. {
  236. foreach ($arRowsWidth as $columnId => $rowWidth)
  237. {
  238. if ($onlyDigit)
  239. {
  240. $arRowsWidth[$columnId] += $requiredWidth / count($digitColumns);
  241. $arRowsContentWidth[$columnId] += $requiredWidth / count($digitColumns);
  242. }
  243. elseif ($cols[$columnId]['IS_DIGIT'] !== true)
  244. {
  245. $ratio = $requiredWidth / $noDigitWidth;
  246. $arRowsWidth[$columnId] *= $ratio;
  247. $arRowsContentWidth[$columnId] *= $ratio;
  248. }
  249. }
  250. }
  251. return array(
  252. 'ROWS_WIDTH' => $arRowsWidth,
  253. 'ROWS_CONTENT_WIDTH' => $arRowsContentWidth
  254. );
  255. }
  256. /**
  257. * @param $str
  258. * @return mixed
  259. */
  260. protected function getMaximumWord($str)
  261. {
  262. $wordList = explode(" ", $str);
  263. $maxWord = "";
  264. foreach ($wordList as $word)
  265. {
  266. if (mb_strlen($word, 'UTF-8') > mb_strlen($maxWord, 'UTF-8'))
  267. {
  268. $maxWord = $word;
  269. }
  270. }
  271. return $maxWord;
  272. }
  273. }
  274. class CSalePdf
  275. {
  276. protected $generator;
  277. public static function isPdfAvailable()
  278. {
  279. if (!extension_loaded("mbstring"))
  280. return false;
  281. if (!file_exists(FPDF_FONTPATH.'/pt_serif-regular.ttf') || !file_exists(FPDF_FONTPATH.'/pt_serif-bold.ttf'))
  282. return false;
  283. return true;
  284. }
  285. public static function prepareToPdf($string)
  286. {
  287. $string = htmlspecialcharsback($string);
  288. $string = CharsetConverter::ConvertCharset($string, SITE_CHARSET, 'UTF-8');
  289. $string = html_entity_decode($string, ENT_QUOTES, 'UTF-8');
  290. return $string;
  291. }
  292. public function splitString($text, $width)
  293. {
  294. if ($width <= 0 || $this->generator->GetStringWidth($text) <= $width)
  295. {
  296. return array($text, '');
  297. }
  298. else
  299. {
  300. $string = $text;
  301. while ($this->generator->GetStringWidth($string) > $width)
  302. {
  303. $l = floor(mb_strlen($string, 'UTF-8') * $width/$this->generator->GetStringWidth($string));
  304. $p = mb_strrpos($string, ' ', $l-mb_strlen($string, 'UTF-8'), 'UTF-8') ?: $l;
  305. $string = mb_substr($string, 0, $p, 'UTF-8');
  306. }
  307. if ($p == 0)
  308. $p++;
  309. return array(
  310. $string,
  311. trim(mb_substr($text, $p, mb_strlen($text, 'UTF-8'), 'UTF-8'))
  312. );
  313. }
  314. }
  315. public function __construct($orientation = 'P', $unit = 'mm', $size = 'A4')
  316. {
  317. $this->generator = new CSaleTfpdf($orientation, $unit, $size);
  318. }
  319. public function __call($name, $arguments)
  320. {
  321. return call_user_func_array(array($this->generator, $name), $arguments);
  322. }
  323. public function SetBackground($image, $style)
  324. {
  325. list($bgHeight, $bgWidth) = $this->GetImageSize($image);
  326. $this->generator->SetBackground($this->GetImagePath($image), $bgHeight, $bgWidth, $style);
  327. }
  328. public function GetImageSize($file)
  329. {
  330. $height = 0;
  331. $width = 0;
  332. if (intval($file) > 0)
  333. {
  334. $arFile = CFile::GetFileArray($file);
  335. if ($arFile)
  336. {
  337. $height = $arFile['HEIGHT'] * 0.75;
  338. $width = $arFile['WIDTH'] * 0.75;
  339. }
  340. }
  341. else
  342. {
  343. $arFile = CFile::GetImageSize($this->GetImagePath($file), true);
  344. if ($arFile)
  345. {
  346. $height = $arFile[1] * 0.75;
  347. $width = $arFile[0] * 0.75;
  348. }
  349. }
  350. return array(0 => $height, 1 => $width);
  351. }
  352. public function GetImagePath($file)
  353. {
  354. $path = false;
  355. if (intval($file) > 0)
  356. {
  357. $arFile = CFile::MakeFileArray($file);
  358. if ($arFile)
  359. $path = $arFile['tmp_name'];
  360. }
  361. elseif ($file)
  362. {
  363. $path = mb_strpos($file, $_SERVER['DOCUMENT_ROOT']) === 0
  364. ? $file
  365. : $_SERVER['DOCUMENT_ROOT'] . $file;
  366. }
  367. return $path;
  368. }
  369. public function Image($file, $x = null, $y = null, $w = 0, $h = 0, $type = '', $link = '')
  370. {
  371. return $this->generator->Image($this->GetImagePath($file), $x, $y, $w, $h, $type, $link);
  372. }
  373. public static function CheckImage(array $file)
  374. {
  375. $pdf = new \tFPDF();
  376. $pos = mb_strrpos($file['name'],'.',0,'8bit');
  377. $type = mb_substr($file['name'],$pos+1,mb_strlen($file['name'],'8bit'),'8bit');
  378. try
  379. {
  380. $pdf->Image($file['tmp_name'], null, null, 0, 0, $type);
  381. }
  382. catch (Exception $e)
  383. {
  384. return $e->getMessage();
  385. }
  386. return null;
  387. }
  388. }