aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/Wallabag/CoreBundle/Helper/EntriesExport.php
diff options
context:
space:
mode:
authorJeremy Benoist <jeremy.benoist@gmail.com>2015-10-16 10:51:53 +0200
committerNicolas LÅ“uillet <nicolas.loeuillet@smile.fr>2015-11-09 16:32:48 +0100
commitadd597bad95b30dbecab3aecc8362a1ccd427976 (patch)
tree1e4976f41fb043bea41c4db4544b42458eee3500 /src/Wallabag/CoreBundle/Helper/EntriesExport.php
parent03690d138792dde6405e3d2eb3c53f6572eb3c43 (diff)
downloadwallabag-add597bad95b30dbecab3aecc8362a1ccd427976.tar.gz
wallabag-add597bad95b30dbecab3aecc8362a1ccd427976.tar.zst
wallabag-add597bad95b30dbecab3aecc8362a1ccd427976.zip
Rework on export
- all export now return a `HttpFoundation\Response` - return a 404 on unsupported format - add tests
Diffstat (limited to 'src/Wallabag/CoreBundle/Helper/EntriesExport.php')
-rw-r--r--src/Wallabag/CoreBundle/Helper/EntriesExport.php258
1 files changed, 167 insertions, 91 deletions
diff --git a/src/Wallabag/CoreBundle/Helper/EntriesExport.php b/src/Wallabag/CoreBundle/Helper/EntriesExport.php
index fad0bb97..806319b1 100644
--- a/src/Wallabag/CoreBundle/Helper/EntriesExport.php
+++ b/src/Wallabag/CoreBundle/Helper/EntriesExport.php
@@ -4,27 +4,51 @@ namespace Wallabag\CoreBundle\Helper;
4 4
5use PHPePub\Core\EPub; 5use PHPePub\Core\EPub;
6use PHPePub\Core\Structure\OPF\DublinCore; 6use PHPePub\Core\Structure\OPF\DublinCore;
7use Symfony\Component\HttpFoundation\Response;
7 8
8class EntriesExport 9class EntriesExport
9{ 10{
10 private $format; 11 private $wallabagUrl;
11 private $method; 12 private $logoPath;
12 private $title; 13 private $title = '';
13 private $entries; 14 private $entries = array();
14 private $authors = array('wallabag'); 15 private $authors = array('wallabag');
15 private $language; 16 private $language = '';
16 private $tags; 17 private $tags = array();
18 private $footerTemplate = '<div style="text-align:center;">
19 <p>Produced by wallabag with %EXPORT_METHOD%</p>
20 <p>Please open <a href="https://github.com/wallabag/wallabag/issues">an issue</a> if you have trouble with the display of this E-Book on your device.</p>
21 </div';
17 22
18 public function __construct($entries) 23 /**
24 * @param string $wallabagUrl Wallabag instance url
25 * @param string $logoPath Path to the logo FROM THE BUNDLE SCOPE
26 */
27 public function __construct($wallabagUrl, $logoPath)
19 { 28 {
29 $this->wallabagUrl = $wallabagUrl;
30 $this->logoPath = $logoPath;
31 }
32
33 /**
34 * Define entries.
35 *
36 * @param array|Entry $entries An array of entries or one entry
37 */
38 public function setEntries($entries)
39 {
40 if (!is_array($entries)) {
41 $this->language = $entries->getLanguage();
42 $entries = array($entries);
43 }
44
20 $this->entries = $entries; 45 $this->entries = $entries;
21 46
22 foreach ($entries as $entry) { 47 foreach ($entries as $entry) {
23 $this->tags[] = $entry->getTags(); 48 $this->tags[] = $entry->getTags();
24 } 49 }
25 if (count($entries) === 1) { 50
26 $this->language = $entries[0]->getLanguage(); 51 return $this;
27 }
28 } 52 }
29 53
30 /** 54 /**
@@ -32,29 +56,15 @@ class EntriesExport
32 * 56 *
33 * @param string $method Method to get articles 57 * @param string $method Method to get articles
34 */ 58 */
35 public function setMethod($method) 59 public function updateTitle($method)
36 { 60 {
37 $this->method = $method; 61 $this->title = $method.' articles';
38 62
39 switch ($this->method) { 63 if ('entry' === $method) {
40 case 'All': 64 $this->title = $this->entries[0]->getTitle();
41 $this->title = 'All Articles';
42 break;
43 case 'Unread':
44 $this->title = 'Unread articles';
45 break;
46 case 'Starred':
47 $this->title = 'Starred articles';
48 break;
49 case 'Archive':
50 $this->title = 'Archived articles';
51 break;
52 case 'entry':
53 $this->title = $this->entries[0]->getTitle();
54 break;
55 default:
56 break;
57 } 65 }
66
67 return $this;
58 } 68 }
59 69
60 /** 70 /**
@@ -64,30 +74,26 @@ class EntriesExport
64 */ 74 */
65 public function exportAs($format) 75 public function exportAs($format)
66 { 76 {
67 $this->format = $format; 77 switch ($format) {
68
69 switch ($this->format) {
70 case 'epub': 78 case 'epub':
71 $this->produceEpub(); 79 return $this->produceEpub();
72 break;
73 80
74 case 'mobi': 81 case 'mobi':
75 $this->produceMobi(); 82 return $this->produceMobi();
76 break;
77 83
78 case 'pdf': 84 case 'pdf':
79 $this->producePDF(); 85 return $this->producePDF();
80 break;
81 86
82 case 'csv': 87 case 'csv':
83 $this->produceCSV(); 88 return $this->produceCSV();
84 break;
85
86 default:
87 break;
88 } 89 }
90
91 throw new \InvalidArgumentException(sprintf('The format "%s" is not yet supported.', $format));
89 } 92 }
90 93
94 /**
95 * Use PHPePub to dump a .epub file.
96 */
91 private function produceEpub() 97 private function produceEpub()
92 { 98 {
93 /* 99 /*
@@ -98,7 +104,7 @@ class EntriesExport
98 ."<html xmlns=\"http://www.w3.org/1999/xhtml\" xmlns:epub=\"http://www.idpf.org/2007/ops\">\n" 104 ."<html xmlns=\"http://www.w3.org/1999/xhtml\" xmlns:epub=\"http://www.idpf.org/2007/ops\">\n"
99 .'<head>' 105 .'<head>'
100 ."<meta http-equiv=\"Default-Style\" content=\"text/html; charset=utf-8\" />\n" 106 ."<meta http-equiv=\"Default-Style\" content=\"text/html; charset=utf-8\" />\n"
101 .'<title>'._('wallabag articles book')."</title>\n" 107 ."<title>wallabag articles book</title>\n"
102 ."</head>\n" 108 ."</head>\n"
103 ."<body>\n"; 109 ."<body>\n";
104 110
@@ -111,17 +117,21 @@ class EntriesExport
111 */ 117 */
112 118
113 $book->setTitle($this->title); 119 $book->setTitle($this->title);
114 $book->setIdentifier($this->title, EPub::IDENTIFIER_URI); // Could also be the ISBN number, prefered for published books, or a UUID. 120 // Could also be the ISBN number, prefered for published books, or a UUID.
115 $book->setLanguage($this->language); // Not needed, but included for the example, Language is mandatory, but EPub defaults to "en". Use RFC3066 Language codes, such as "en", "da", "fr" etc. 121 $book->setIdentifier($this->title, EPub::IDENTIFIER_URI);
116 $book->setDescription(_('Some articles saved on my wallabag')); 122 // Not needed, but included for the example, Language is mandatory, but EPub defaults to "en". Use RFC3066 Language codes, such as "en", "da", "fr" etc.
123 $book->setLanguage($this->language);
124 $book->setDescription('Some articles saved on my wallabag');
117 125
118 foreach ($this->authors as $author) { 126 foreach ($this->authors as $author) {
119 $book->setAuthor($author, $author); 127 $book->setAuthor($author, $author);
120 } 128 }
121 129
122 $book->setPublisher('wallabag', 'wallabag'); // I hope this is a non existant address :) 130 // I hope this is a non existant address :)
123 $book->setDate(time()); // Strictly not needed as the book date defaults to time(). 131 $book->setPublisher('wallabag', 'wallabag');
124 $book->setSourceURL("http://$_SERVER[HTTP_HOST]"); 132 // Strictly not needed as the book date defaults to time().
133 $book->setDate(time());
134 $book->setSourceURL($this->wallabagUrl);
125 135
126 $book->addDublinCoreMetadata(DublinCore::CONTRIBUTOR, 'PHP'); 136 $book->addDublinCoreMetadata(DublinCore::CONTRIBUTOR, 'PHP');
127 $book->addDublinCoreMetadata(DublinCore::CONTRIBUTOR, 'wallabag'); 137 $book->addDublinCoreMetadata(DublinCore::CONTRIBUTOR, 'wallabag');
@@ -129,12 +139,11 @@ class EntriesExport
129 /* 139 /*
130 * Front page 140 * Front page
131 */ 141 */
142 if (file_exists($this->logoPath)) {
143 $book->setCoverImage('Cover.png', file_get_contents($this->logoPath), 'image/png');
144 }
132 145
133 $book->setCoverImage('Cover.png', file_get_contents('themes/_global/img/appicon/apple-touch-icon-152.png'), 'image/png'); 146 $book->addChapter('Notices', 'Cover2.html', $content_start.$this->getExportInformation('PHPePub').$bookEnd);
134
135 $cover = $content_start.'<div style="text-align:center;"><p>'._('Produced by wallabag with PHPePub').'</p><p>'._('Please open <a href="https://github.com/wallabag/wallabag/issues" >an issue</a> if you have trouble with the display of this E-Book on your device.').'</p></div>'.$bookEnd;
136
137 $book->addChapter('Notices', 'Cover2.html', $cover);
138 147
139 $book->buildTOC(); 148 $book->buildTOC();
140 149
@@ -142,18 +151,31 @@ class EntriesExport
142 * Adding actual entries 151 * Adding actual entries
143 */ 152 */
144 153
145 foreach ($this->entries as $entry) { //set tags as subjects 154 // set tags as subjects
146 foreach ($this->tags as $tag) { 155 foreach ($this->entries as $entry) {
147 $book->setSubject($tag['value']); 156 foreach ($this->tags as $tag) {
148 } 157 $book->setSubject($tag['value']);
158 }
149 159
150 $chapter = $content_start.$entry->getContent().$bookEnd; 160 $chapter = $content_start.$entry->getContent().$bookEnd;
151 $book->addChapter($entry->getTitle(), htmlspecialchars($entry->getTitle()).'.html', $chapter, true, EPub::EXTERNAL_REF_ADD); 161 $book->addChapter($entry->getTitle(), htmlspecialchars($entry->getTitle()).'.html', $chapter, true, EPub::EXTERNAL_REF_ADD);
152 } 162 }
153 $book->finalize(); 163
154 $book->sendBook($this->title); 164 return Response::create(
165 $book->getBook(),
166 200,
167 array(
168 'Content-Description' => 'File Transfer',
169 'Content-type' => 'application/epub+zip',
170 'Content-Disposition' => 'attachment; filename="'.$this->title.'.epub"',
171 'Content-Transfer-Encoding' => 'binary',
172 )
173 )->send();
155 } 174 }
156 175
176 /**
177 * Use PHPMobi to dump a .mobi file.
178 */
157 private function produceMobi() 179 private function produceMobi()
158 { 180 {
159 $mobi = new \MOBI(); 181 $mobi = new \MOBI();
@@ -162,7 +184,6 @@ class EntriesExport
162 /* 184 /*
163 * Book metadata 185 * Book metadata
164 */ 186 */
165
166 $content->set('title', $this->title); 187 $content->set('title', $this->title);
167 $content->set('author', implode($this->authors)); 188 $content->set('author', implode($this->authors));
168 $content->set('subject', $this->title); 189 $content->set('subject', $this->title);
@@ -170,15 +191,15 @@ class EntriesExport
170 /* 191 /*
171 * Front page 192 * Front page
172 */ 193 */
173 194 $content->appendParagraph($this->getExportInformation('PHPMobi'));
174 $content->appendParagraph('<div style="text-align:center;" ><p>'._('Produced by wallabag with PHPMobi').'</p><p>'._('Please open <a href="https://github.com/wallabag/wallabag/issues" >an issue</a> if you have trouble with the display of this E-Book on your device.').'</p></div>'); 195 if (file_exists($this->logoPath)) {
175 $content->appendImage(imagecreatefrompng('themes/_global/img/appicon/apple-touch-icon-152.png')); 196 $content->appendImage(imagecreatefrompng($this->logoPath));
197 }
176 $content->appendPageBreak(); 198 $content->appendPageBreak();
177 199
178 /* 200 /*
179 * Adding actual entries 201 * Adding actual entries
180 */ 202 */
181
182 foreach ($this->entries as $entry) { 203 foreach ($this->entries as $entry) {
183 $content->appendChapterTitle($entry->getTitle()); 204 $content->appendChapterTitle($entry->getTitle());
184 $content->appendParagraph($entry->getContent()); 205 $content->appendParagraph($entry->getContent());
@@ -189,10 +210,22 @@ class EntriesExport
189 // the browser inside Kindle Devices doesn't likes special caracters either, we limit to A-z/0-9 210 // the browser inside Kindle Devices doesn't likes special caracters either, we limit to A-z/0-9
190 $this->title = preg_replace('/[^A-Za-z0-9\-]/', '', $this->title); 211 $this->title = preg_replace('/[^A-Za-z0-9\-]/', '', $this->title);
191 212
192 // we offer file to download 213 return Response::create(
193 $mobi->download($this->title.'.mobi'); 214 $mobi->toString(),
215 200,
216 array(
217 'Accept-Ranges' => 'bytes',
218 'Content-Description' => 'File Transfer',
219 'Content-type' => 'application/x-mobipocket-ebook',
220 'Content-Disposition' => 'attachment; filename="'.$this->title.'.mobi"',
221 'Content-Transfer-Encoding' => 'binary',
222 )
223 )->send();
194 } 224 }
195 225
226 /**
227 * Use TCPDF to dump a .pdf file.
228 */
196 private function producePDF() 229 private function producePDF()
197 { 230 {
198 $pdf = new \TCPDF(PDF_PAGE_ORIENTATION, PDF_UNIT, PDF_PAGE_FORMAT, true, 'UTF-8', false); 231 $pdf = new \TCPDF(PDF_PAGE_ORIENTATION, PDF_UNIT, PDF_PAGE_FORMAT, true, 'UTF-8', false);
@@ -200,7 +233,6 @@ class EntriesExport
200 /* 233 /*
201 * Book metadata 234 * Book metadata
202 */ 235 */
203
204 $pdf->SetCreator(PDF_CREATOR); 236 $pdf->SetCreator(PDF_CREATOR);
205 $pdf->SetAuthor('wallabag'); 237 $pdf->SetAuthor('wallabag');
206 $pdf->SetTitle($this->title); 238 $pdf->SetTitle($this->title);
@@ -210,19 +242,14 @@ class EntriesExport
210 /* 242 /*
211 * Front page 243 * Front page
212 */ 244 */
213
214 $pdf->AddPage(); 245 $pdf->AddPage();
215 $intro = '<h1>'.$this->title.'</h1><div style="text-align:center;" > 246 $intro = '<h1>'.$this->title.'</h1>'.$this->getExportInformation('tcpdf');
216 <p>'._('Produced by wallabag with tcpdf').'</p>
217 <p>'._('Please open <a href="https://github.com/wallabag/wallabag/issues" >an issue</a> if you have trouble with the display of this E-Book on your device.').'</p>
218 <img src="themes/_global/img/appicon/apple-touch-icon-152.png" /></div>';
219 247
220 $pdf->writeHTMLCell(0, 0, '', '', $intro, 0, 1, 0, true, '', true); 248 $pdf->writeHTMLCell(0, 0, '', '', $intro, 0, 1, 0, true, '', true);
221 249
222 /* 250 /*
223 * Adding actual entries 251 * Adding actual entries
224 */ 252 */
225
226 foreach ($this->entries as $entry) { 253 foreach ($this->entries as $entry) {
227 foreach ($this->tags as $tag) { 254 foreach ($this->tags as $tag) {
228 $pdf->SetKeywords($tag['value']); 255 $pdf->SetKeywords($tag['value']);
@@ -231,33 +258,82 @@ class EntriesExport
231 $pdf->AddPage(); 258 $pdf->AddPage();
232 $html = '<h1>'.$entry->getTitle().'</h1>'; 259 $html = '<h1>'.$entry->getTitle().'</h1>';
233 $html .= $entry->getContent(); 260 $html .= $entry->getContent();
261
234 $pdf->writeHTMLCell(0, 0, '', '', $html, 0, 1, 0, true, '', true); 262 $pdf->writeHTMLCell(0, 0, '', '', $html, 0, 1, 0, true, '', true);
235 } 263 }
236 264
237 // set image scale factor 265 // set image scale factor
238 $pdf->setImageScale(PDF_IMAGE_SCALE_RATIO); 266 $pdf->setImageScale(PDF_IMAGE_SCALE_RATIO);
239 267
240 $pdf->Output($this->title.'.pdf', 'D'); 268 return Response::create(
269 $pdf->Output('', 'S'),
270 200,
271 array(
272 'Content-Description' => 'File Transfer',
273 'Content-type' => 'application/pdf',
274 'Content-Disposition' => 'attachment; filename="'.$this->title.'.pdf"',
275 'Content-Transfer-Encoding' => 'binary',
276 )
277 )->send();
241 } 278 }
242 279
280 /**
281 * Inspired from CsvFileDumper.
282 */
243 private function produceCSV() 283 private function produceCSV()
244 { 284 {
245 header('Content-type: application/csv'); 285 $delimiter = ';';
246 header('Content-Disposition: attachment; filename="'.$this->title.'.csv"'); 286 $enclosure = '"';
247 header('Content-Transfer-Encoding: UTF-8'); 287 $handle = fopen('php://memory', 'rb+');
248 288
249 $output = fopen('php://output', 'a'); 289 fputcsv($handle, array('Title', 'URL', 'Content', 'Tags', 'MIME Type', 'Language'), $delimiter, $enclosure);
250 290
251 fputcsv($output, array('Title', 'URL', 'Content', 'Tags', 'MIME Type', 'Language'));
252 foreach ($this->entries as $entry) { 291 foreach ($this->entries as $entry) {
253 fputcsv($output, array($entry->getTitle(), 292 fputcsv(
254 $entry->getURL(), 293 $handle,
255 $entry->getContent(), 294 array(
256 implode(', ', $entry->getTags()->toArray()), 295 $entry->getTitle(),
257 $entry->getMimetype(), 296 $entry->getURL(),
258 $entry->getLanguage(), )); 297 $entry->getContent(),
298 implode(', ', $entry->getTags()->toArray()),
299 $entry->getMimetype(),
300 $entry->getLanguage(),
301 ),
302 $delimiter,
303 $enclosure
304 );
305 }
306
307 rewind($handle);
308 $output = stream_get_contents($handle);
309 fclose($handle);
310
311 return Response::create(
312 $output,
313 200,
314 array(
315 'Content-type' => 'application/csv',
316 'Content-Disposition' => 'attachment; filename="'.$this->title.'.csv"',
317 'Content-Transfer-Encoding' => 'UTF-8',
318 )
319 )->send();
320 }
321
322 /**
323 * Return a kind of footer / information for the epub.
324 *
325 * @param string $type Generator of the export, can be: tdpdf, PHPePub, PHPMobi
326 *
327 * @return string
328 */
329 private function getExportInformation($type)
330 {
331 $info = str_replace('%EXPORT_METHOD%', $type, $this->footerTemplate);
332
333 if ('tcpdf' === $type) {
334 return str_replace('%IMAGE%', '<img src="'.$this->logoPath.'" />', $info);
259 } 335 }
260 fclose($output); 336
261 exit(); 337 return str_replace('%IMAGE%', '', $info);
262 } 338 }
263} 339}