]> BookStack Code Mirror - bookstack/blob - app/Services/ExportService.php
Merge branch 'master' of https://github.com/BookStackApp/BookStack
[bookstack] / app / Services / ExportService.php
1 <?php namespace BookStack\Services;
2
3 use BookStack\Page;
4 use BookStack\Repos\EntityRepo;
5
6 class ExportService
7 {
8
9     protected $entityRepo;
10
11     /**
12      * ExportService constructor.
13      * @param $entityRepo
14      */
15     public function __construct(EntityRepo $entityRepo)
16     {
17         $this->entityRepo = $entityRepo;
18     }
19
20     /**
21      * Convert a page to a self-contained HTML file.
22      * Includes required CSS & image content. Images are base64 encoded into the HTML.
23      * @param Page $page
24      * @return mixed|string
25      */
26     public function pageToContainedHtml(Page $page)
27     {
28         $cssContent = file_get_contents(public_path('/css/export-styles.css'));
29         $pageHtml = view('pages/export', ['page' => $page, 'pageContent' => $this->entityRepo->renderPage($page), 'css' => $cssContent])->render();
30         return $this->containHtml($pageHtml);
31     }
32
33     /**
34      * Convert a page to a pdf file.
35      * @param Page $page
36      * @return mixed|string
37      */
38     public function pageToPdf(Page $page)
39     {
40         $cssContent = file_get_contents(public_path('/css/export-styles.css'));
41         $pageHtml = view('pages/pdf', ['page' => $page, 'pageContent' => $this->entityRepo->renderPage($page), 'css' => $cssContent])->render();
42 //        return $pageHtml;
43         $useWKHTML = config('snappy.pdf.binary') !== false;
44         $containedHtml = $this->containHtml($pageHtml);
45         if ($useWKHTML) {
46             $pdf = \SnappyPDF::loadHTML($containedHtml);
47         } else {
48             $pdf = \PDF::loadHTML($containedHtml);
49         }
50         return $pdf->output();
51     }
52
53     /**
54      * Bundle of the contents of a html file to be self-contained.
55      * @param $htmlContent
56      * @return mixed|string
57      */
58     protected function containHtml($htmlContent)
59     {
60         $imageTagsOutput = [];
61         preg_match_all("/\<img.*src\=(\'|\")(.*?)(\'|\").*?\>/i", $htmlContent, $imageTagsOutput);
62
63         // Replace image src with base64 encoded image strings
64         if (isset($imageTagsOutput[0]) && count($imageTagsOutput[0]) > 0) {
65             foreach ($imageTagsOutput[0] as $index => $imgMatch) {
66                 $oldImgString = $imgMatch;
67                 $srcString = $imageTagsOutput[2][$index];
68                 $isLocal = strpos(trim($srcString), 'http') !== 0;
69                 if ($isLocal) {
70                     $pathString = public_path(trim($srcString, '/'));
71                 } else {
72                     $pathString = $srcString;
73                 }
74                 if ($isLocal && !file_exists($pathString)) continue;
75                 try {
76                     $imageContent = file_get_contents($pathString);
77                     $imageEncoded = 'data:image/' . pathinfo($pathString, PATHINFO_EXTENSION) . ';base64,' . base64_encode($imageContent);
78                     $newImageString = str_replace($srcString, $imageEncoded, $oldImgString);
79                 } catch (\ErrorException $e) {
80                     $newImageString = '';
81                 }
82                 $htmlContent = str_replace($oldImgString, $newImageString, $htmlContent);
83             }
84         }
85
86         $linksOutput = [];
87         preg_match_all("/\<a.*href\=(\'|\")(.*?)(\'|\").*?\>/i", $htmlContent, $linksOutput);
88
89         // Replace image src with base64 encoded image strings
90         if (isset($linksOutput[0]) && count($linksOutput[0]) > 0) {
91             foreach ($linksOutput[0] as $index => $linkMatch) {
92                 $oldLinkString = $linkMatch;
93                 $srcString = $linksOutput[2][$index];
94                 if (strpos(trim($srcString), 'http') !== 0) {
95                     $newSrcString = url($srcString);
96                     $newLinkString = str_replace($srcString, $newSrcString, $oldLinkString);
97                     $htmlContent = str_replace($oldLinkString, $newLinkString, $htmlContent);
98                 }
99             }
100         }
101
102         // Replace any relative links with system domain
103         return $htmlContent;
104     }
105
106     /**
107      * Converts the page contents into simple plain text.
108      * This method filters any bad looking content to provide a nice final output.
109      * @param Page $page
110      * @return mixed
111      */
112     public function pageToPlainText(Page $page)
113     {
114         $html = $this->entityRepo->renderPage($page);
115         $text = strip_tags($html);
116         // Replace multiple spaces with single spaces
117         $text = preg_replace('/\ {2,}/', ' ', $text);
118         // Reduce multiple horrid whitespace characters.
119         $text = preg_replace('/(\x0A|\xA0|\x0A|\r|\n){2,}/su', "\n\n", $text);
120         $text = html_entity_decode($text);
121         // Add title
122         $text = $page->name . "\n\n" . $text;
123         return $text;
124     }
125
126 }
127
128
129
130
131
132
133
134
135
136
137
138