PluginProbe ʕ •ᴥ•ʔ
Matomo Analytics – Powerful, Privacy-First Insights for WordPress / 1.3.1
Matomo Analytics – Powerful, Privacy-First Insights for WordPress v1.3.1
5.11.1 5.11.0 5.10.2 5.10.1 trunk 1.0.2 1.0.3 1.0.4 1.0.5 1.0.6 1.1.0 1.1.1 1.1.2 1.1.3 1.2.0 1.3.0 1.3.1 1.3.2 4.0.0 4.0.1 4.0.2 4.0.3 4.0.4 4.1.0 4.1.1 4.1.2 4.1.3 4.10.0 4.11.0 4.12.0 4.13.0 4.13.2 4.13.3 4.13.4 4.13.5 4.14.0 4.14.1 4.14.2 4.15.0 4.15.1 4.15.2 4.15.3 4.2.0 4.3.0 4.3.1 4.4.1 4.4.2 4.5.0 4.6.0 5.0.1 5.0.2 5.0.3 5.0.4 5.0.5 5.0.6 5.0.7 5.0.8 5.1.0 5.1.1 5.1.2 5.1.3 5.1.4 5.1.5 5.1.6 5.1.7 5.10.0 5.2.0 5.2.1 5.2.2 5.3.0 5.3.1 5.3.2 5.3.3 5.6.0 5.6.1 5.7.0 5.7.1 5.8.0 5.8.1 5.8.2
matomo / app / core / ReportRenderer / Pdf.php
matomo / app / core / ReportRenderer Last commit date
Csv.php 6 years ago Html.php 6 years ago Pdf.php 6 years ago
Pdf.php
557 lines
1 <?php
2 /**
3 * Piwik - free/libre analytics platform
4 *
5 * @link https://matomo.org
6 * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later
7 *
8 */
9 namespace Piwik\ReportRenderer;
10
11 use Piwik\Common;
12 use Piwik\Filesystem;
13 use Piwik\NumberFormatter;
14 use Piwik\Piwik;
15 use Piwik\Plugins\API\API;
16 use Piwik\ReportRenderer;
17 use Piwik\TCPDF;
18
19 /**
20 * @see libs/tcpdf
21 */
22 require_once PIWIK_INCLUDE_PATH . '/plugins/ScheduledReports/config/tcpdf_config.php';
23
24 /**
25 * PDF report renderer
26 */
27 class Pdf extends ReportRenderer
28 {
29 const IMAGE_GRAPH_WIDTH_LANDSCAPE = 1050;
30 const IMAGE_GRAPH_WIDTH_PORTRAIT = 760;
31 const IMAGE_GRAPH_HEIGHT = 220;
32
33 const LANDSCAPE = 'L';
34 const PORTRAIT = 'P';
35
36 const MAX_ROW_COUNT = 28;
37 const TABLE_HEADER_ROW_COUNT = 6;
38 const NO_DATA_ROW_COUNT = 6;
39 const MAX_GRAPH_REPORTS = 3;
40 const MAX_2COL_TABLE_REPORTS = 2;
41
42 const PDF_CONTENT_TYPE = 'pdf';
43
44 private $reportFontStyle = '';
45 private $reportSimpleFontSize = 9;
46 private $reportHeaderFontSize = 16;
47 private $cellHeight = 6;
48 private $bottomMargin = 17;
49 private $reportWidthPortrait = 195;
50 private $reportWidthLandscape = 270;
51 private $minWidthLabelCell = 100;
52 private $maxColumnCountPortraitOrientation = 6;
53 private $logoWidth = 16;
54 private $logoHeight = 16;
55 private $totalWidth;
56 private $cellWidth;
57 private $labelCellWidth;
58 private $truncateAfter = 55;
59 private $leftSpacesBeforeLogo = 7;
60 private $logoImagePosition = array(10, 40);
61 private $headerTextColor;
62 private $reportTextColor;
63 private $tableHeaderBackgroundColor;
64 private $tableHeaderTextColor;
65 private $tableCellBorderColor;
66 private $tableBackgroundColor;
67 private $rowTopBottomBorder = array(231, 231, 231);
68 private $reportMetadata;
69 private $displayGraph;
70 private $evolutionGraph;
71 private $displayTable;
72 private $segment;
73 private $reportColumns;
74 private $reportRowsMetadata;
75 private $currentPage = 0;
76 private $reportFont = ReportRenderer::DEFAULT_REPORT_FONT_FAMILY;
77 private $TCPDF;
78 private $orientation = self::PORTRAIT;
79
80 public function __construct()
81 {
82 $this->TCPDF = new TCPDF();
83 $this->headerTextColor = preg_split("/,/", ReportRenderer::REPORT_TITLE_TEXT_COLOR);
84 $this->reportTextColor = preg_split("/,/", ReportRenderer::REPORT_TEXT_COLOR);
85 $this->tableHeaderBackgroundColor = preg_split("/,/", ReportRenderer::TABLE_HEADER_BG_COLOR);
86 $this->tableHeaderTextColor = preg_split("/,/", ReportRenderer::TABLE_HEADER_TEXT_COLOR);
87 $this->tableCellBorderColor = preg_split("/,/", ReportRenderer::TABLE_CELL_BORDER_COLOR);
88 $this->tableBackgroundColor = preg_split("/,/", ReportRenderer::TABLE_BG_COLOR);
89 }
90
91 public function setLocale($locale)
92 {
93 // WARNING
94 // To make Piwik release smaller, we're deleting some fonts from the Piwik build package.
95 // If you change this code below, make sure that the fonts are NOT deleted from the Piwik package:
96 // https://github.com/piwik/piwik-package/blob/master/scripts/build-package.sh
97 switch ($locale) {
98 case 'bn':
99 case 'hi':
100 $reportFont = 'freesans';
101 break;
102
103 case 'zh-tw':
104 $reportFont = 'msungstdlight';
105 break;
106
107 case 'ja':
108 $reportFont = 'kozgopromedium';
109 break;
110
111 case 'zh-cn':
112 $reportFont = 'stsongstdlight';
113 break;
114
115 case 'ko':
116 $reportFont = 'hysmyeongjostdmedium';
117 break;
118
119 case 'ar':
120 $reportFont = 'aealarabiya';
121 break;
122
123 case 'am':
124 case 'ta':
125 case 'th':
126 $reportFont = 'freeserif';
127 break;
128
129 case 'te':
130 // not working with bundled fonts
131 case 'en':
132 default:
133 $reportFont = ReportRenderer::DEFAULT_REPORT_FONT_FAMILY;
134 break;
135 }
136 // WARNING: Did you read the warning above?
137
138 $this->reportFont = $reportFont;
139 }
140
141 public function sendToDisk($filename)
142 {
143 $filename = ReportRenderer::makeFilenameWithExtension($filename, self::PDF_CONTENT_TYPE);
144 $outputFilename = ReportRenderer::getOutputPath($filename);
145
146 $this->TCPDF->Output($outputFilename, 'F');
147
148 return $outputFilename;
149 }
150
151 public function sendToBrowserDownload($filename)
152 {
153 $filename = ReportRenderer::makeFilenameWithExtension($filename, self::PDF_CONTENT_TYPE);
154 $this->TCPDF->Output($filename, 'D');
155 }
156
157 public function sendToBrowserInline($filename)
158 {
159 $filename = ReportRenderer::makeFilenameWithExtension($filename, self::PDF_CONTENT_TYPE);
160 $this->TCPDF->Output($filename, 'I');
161 }
162
163 public function getRenderedReport()
164 {
165 return $this->TCPDF->Output(null, 'S');
166 }
167
168 public function renderFrontPage($reportTitle, $prettyDate, $description, $reportMetadata, $segment)
169 {
170 $reportTitle = $this->formatText($reportTitle);
171 $dateRange = $this->formatText(Piwik::translate('General_DateRange') . " " . $prettyDate);
172
173 // footer
174 $this->TCPDF->SetFooterFont(array($this->reportFont, $this->reportFontStyle, $this->reportSimpleFontSize));
175 $this->TCPDF->SetFooterContent($reportTitle . " | " . $dateRange . " | ");
176
177 // add first page
178 $this->TCPDF->setPrintHeader(false);
179 $this->TCPDF->AddPage(self::PORTRAIT);
180 $this->TCPDF->AddFont($this->reportFont, '', '', false);
181 $this->TCPDF->SetFont($this->reportFont, $this->reportFontStyle, $this->reportSimpleFontSize);
182 $this->TCPDF->Bookmark(Piwik::translate('ScheduledReports_FrontPage'));
183
184 // logo
185 $this->TCPDF->Image(API::getInstance()->getLogoUrl(true), $this->logoImagePosition[0], $this->logoImagePosition[1], 180 / $factor = 2, 0, $type = '', $link = '', $align = '', $resize = false, $dpi = 300);
186 $this->TCPDF->Ln(8);
187
188 // report title
189 $this->TCPDF->SetFont($this->reportFont, '', $this->reportHeaderFontSize + 5);
190 $this->TCPDF->SetTextColor($this->headerTextColor[0], $this->headerTextColor[1], $this->headerTextColor[2]);
191 $this->TCPDF->Cell(40, 210, $reportTitle);
192 $this->TCPDF->Ln(8 * 4);
193
194 // date and period
195 $this->TCPDF->SetFont($this->reportFont, '', $this->reportHeaderFontSize);
196 $this->TCPDF->SetTextColor($this->reportTextColor[0], $this->reportTextColor[1], $this->reportTextColor[2]);
197 $this->TCPDF->Cell(40, 210, $dateRange);
198 $this->TCPDF->Ln(8 * 20);
199
200 // description
201 $this->TCPDF->Write(1, $this->formatText($description));
202
203 // segment
204 if ($segment != null) {
205 $this->TCPDF->Ln();
206 $this->TCPDF->Ln();
207 $this->TCPDF->SetFont($this->reportFont, '', $this->reportHeaderFontSize - 2);
208 $this->TCPDF->SetTextColor($this->headerTextColor[0], $this->headerTextColor[1], $this->headerTextColor[2]);
209 $this->TCPDF->Write(1, $this->formatText(Piwik::translate('ScheduledReports_CustomVisitorSegment') . ' ' . $segment['name']));
210 }
211
212 $this->TCPDF->Ln(8);
213 $this->TCPDF->SetFont($this->reportFont, '', $this->reportHeaderFontSize);
214 $this->TCPDF->Ln();
215 }
216
217 /**
218 * Generate a header of page.
219 */
220 private function paintReportHeader()
221 {
222 $isAggregateReport = !empty($this->reportMetadata['dimension']);
223
224 // Graph-only report
225 static $graphOnlyReportCount = 0;
226 $graphOnlyReport = $isAggregateReport && $this->displayGraph && !$this->displayTable;
227
228 // Table-only report
229 $tableOnlyReport = $isAggregateReport
230 && !$this->displayGraph
231 && $this->displayTable;
232
233 $columnCount = count($this->reportColumns);
234
235 // Table-only 2-column report
236 static $tableOnly2ColumnReportCount = 0;
237 $tableOnly2ColumnReport = $tableOnlyReport
238 && $columnCount == 2;
239
240 // Table-only report with more than 2 columns
241 static $tableOnlyManyColumnReportRowCount = 0;
242 $tableOnlyManyColumnReport = $tableOnlyReport
243 && $columnCount > 3;
244
245 $reportHasData = $this->reportHasData();
246
247 $rowCount = $reportHasData ? $this->report->getRowsCount() + self::TABLE_HEADER_ROW_COUNT : self::NO_DATA_ROW_COUNT;
248
249 // Only a page break before if the current report has some data
250 if ($reportHasData &&
251 // and
252 (
253 // it is the first report
254 $this->currentPage == 0
255 // or, it is a graph-only report and it is the first of a series of self::MAX_GRAPH_REPORTS
256 || ($graphOnlyReport && $graphOnlyReportCount == 0)
257 // or, it is a table-only 2-column report and it is the first of a series of self::MAX_2COL_TABLE_REPORTS
258 || ($tableOnly2ColumnReport && $tableOnly2ColumnReportCount == 0)
259 // or it is a table-only report with more than 2 columns and it is the first of its series or there isn't enough space left on the page
260 || ($tableOnlyManyColumnReport && ($tableOnlyManyColumnReportRowCount == 0 || $tableOnlyManyColumnReportRowCount + $rowCount >= self::MAX_ROW_COUNT))
261 // or it is a report with both a table and a graph
262 || !$graphOnlyReport && !$tableOnlyReport
263 )
264 ) {
265 $this->currentPage++;
266 $this->TCPDF->AddPage();
267
268 // Table-only reports with more than 2 columns are always landscape
269 if ($tableOnlyManyColumnReport) {
270 $tableOnlyManyColumnReportRowCount = 0;
271 $this->orientation = self::LANDSCAPE;
272 } else {
273 // Graph-only reports are always portrait
274 $this->orientation = $graphOnlyReport ? self::PORTRAIT : ($columnCount > $this->maxColumnCountPortraitOrientation ? self::LANDSCAPE : self::PORTRAIT);
275 }
276
277 $this->TCPDF->setPageOrientation($this->orientation, '', $this->bottomMargin);
278 }
279
280 $graphOnlyReportCount = ($graphOnlyReport && $reportHasData) ? ($graphOnlyReportCount + 1) % self::MAX_GRAPH_REPORTS : 0;
281 $tableOnly2ColumnReportCount = ($tableOnly2ColumnReport && $reportHasData) ? ($tableOnly2ColumnReportCount + 1) % self::MAX_2COL_TABLE_REPORTS : 0;
282 $tableOnlyManyColumnReportRowCount = $tableOnlyManyColumnReport ? ($tableOnlyManyColumnReportRowCount + $rowCount) : 0;
283
284 $title = $this->formatText($this->reportMetadata['name']);
285 $this->TCPDF->SetFont($this->reportFont, $this->reportFontStyle, $this->reportHeaderFontSize);
286 $this->TCPDF->SetTextColor($this->headerTextColor[0], $this->headerTextColor[1], $this->headerTextColor[2]);
287 $this->TCPDF->Bookmark($title);
288 $this->TCPDF->Cell(40, 15, $title);
289 $this->TCPDF->Ln();
290 $this->TCPDF->SetFont($this->reportFont, '', $this->reportSimpleFontSize);
291 $this->TCPDF->SetTextColor($this->reportTextColor[0], $this->reportTextColor[1], $this->reportTextColor[2]);
292 }
293
294 private function reportHasData()
295 {
296 return $this->report->getRowsCount() > 0;
297 }
298
299 private function setBorderColor()
300 {
301 $this->TCPDF->SetDrawColor($this->tableCellBorderColor[0], $this->tableCellBorderColor[1], $this->tableCellBorderColor[2]);
302 }
303
304 public function renderReport($processedReport)
305 {
306 $this->reportMetadata = $processedReport['metadata'];
307 $this->reportRowsMetadata = $processedReport['reportMetadata'];
308 $this->displayGraph = $processedReport['displayGraph'];
309 $this->evolutionGraph = $processedReport['evolutionGraph'];
310 $this->displayTable = $processedReport['displayTable'];
311 $this->segment = $processedReport['segment'];
312 list($this->report, $this->reportColumns) = self::processTableFormat($this->reportMetadata, $processedReport['reportData'], $processedReport['columns']);
313
314 $this->paintReportHeader();
315
316 if (!$this->reportHasData()) {
317 $this->paintMessage(Piwik::translate('CoreHome_ThereIsNoDataForThisReport'));
318 return;
319 }
320
321 if ($this->displayGraph) {
322 $this->paintGraph();
323 }
324
325 if ($this->displayGraph && $this->displayTable) {
326 $this->TCPDF->Ln(5);
327 }
328
329 if ($this->displayTable) {
330 $this->paintReportTableHeader();
331 $this->paintReportTable();
332 }
333 }
334
335 private function formatText($text)
336 {
337 return Common::unsanitizeInputValue($text);
338 }
339
340 private function paintReportTable()
341 {
342 //Color and font restoration
343 $this->TCPDF->SetFillColor($this->tableBackgroundColor[0], $this->tableBackgroundColor[1], $this->tableBackgroundColor[2]);
344 $this->TCPDF->SetTextColor($this->reportTextColor[0], $this->reportTextColor[1], $this->reportTextColor[2]);
345 $this->TCPDF->SetFont('');
346
347 $fill = true;
348 $url = false;
349 $leftSpacesBeforeLogo = str_repeat(' ', $this->leftSpacesBeforeLogo);
350
351 $logoWidth = $this->logoWidth;
352 $logoHeight = $this->logoHeight;
353
354 $rowsMetadata = $this->reportRowsMetadata->getRows();
355
356 // Draw a body of report table
357 foreach ($this->report->getRows() as $rowId => $row) {
358 $rowMetrics = $row->getColumns();
359 $rowMetadata = isset($rowsMetadata[$rowId]) ? $rowsMetadata[$rowId]->getColumns() : array();
360 if (isset($rowMetadata['url'])) {
361 $url = $rowMetadata['url'];
362 }
363 foreach ($this->reportColumns as $columnId => $columnName) {
364 // Label column
365 if ($columnId == 'label') {
366 $isLogoDisplayable = isset($rowMetadata['logo']);
367 $text = '';
368 $posX = $this->TCPDF->GetX();
369 $posY = $this->TCPDF->GetY();
370 if (isset($rowMetrics[$columnId])) {
371 $text = substr($rowMetrics[$columnId], 0, $this->truncateAfter);
372 if ($isLogoDisplayable) {
373 $text = $leftSpacesBeforeLogo . $text;
374 }
375 }
376 $text = $this->formatText($text);
377
378 $this->TCPDF->Cell($this->labelCellWidth, $this->cellHeight, $text, 'LR', 0, 'L', $fill, $url);
379
380 if ($isLogoDisplayable) {
381 if (isset($rowMetadata['logoWidth'])) {
382 $logoWidth = $rowMetadata['logoWidth'];
383 }
384 if (isset($rowMetadata['logoHeight'])) {
385 $logoHeight = $rowMetadata['logoHeight'];
386 }
387 $restoreY = $this->TCPDF->getY();
388 $restoreX = $this->TCPDF->getX();
389 $this->TCPDF->SetY($posY);
390 $this->TCPDF->SetX($posX);
391 $topMargin = 1.3;
392 // Country flags are not very high, force a bigger top margin
393 if ($logoHeight < 16) {
394 $topMargin = 2;
395 }
396 $path = Filesystem::getPathToPiwikRoot() . "/" . $rowMetadata['logo'];
397 if (file_exists($path)) {
398 $this->TCPDF->Image($path, $posX + ($leftMargin = 2), $posY + $topMargin, $logoWidth / 4);
399 }
400 $this->TCPDF->SetXY($restoreX, $restoreY);
401 }
402 } // metrics column
403 else {
404 // No value means 0
405 if (empty($rowMetrics[$columnId])) {
406 $rowMetrics[$columnId] = 0;
407 }
408 $this->TCPDF->Cell($this->cellWidth, $this->cellHeight, NumberFormatter::getInstance()->format($rowMetrics[$columnId]), 'LR', 0, 'L', $fill);
409 }
410 }
411
412 $this->TCPDF->Ln();
413
414 // Top/Bottom grey border for all cells
415 $this->TCPDF->SetDrawColor($this->rowTopBottomBorder[0], $this->rowTopBottomBorder[1], $this->rowTopBottomBorder[2]);
416 $this->TCPDF->Cell($this->totalWidth, 0, '', 'T');
417 $this->setBorderColor();
418 $this->TCPDF->Ln(0.2);
419
420 $fill = !$fill;
421 }
422 }
423
424 private function paintGraph()
425 {
426 $imageGraph = parent::getStaticGraph(
427 $this->reportMetadata,
428 $this->orientation == self::PORTRAIT ? self::IMAGE_GRAPH_WIDTH_PORTRAIT : self::IMAGE_GRAPH_WIDTH_LANDSCAPE,
429 self::IMAGE_GRAPH_HEIGHT,
430 $this->evolutionGraph,
431 $this->segment
432 );
433
434 $this->TCPDF->Image(
435 '@' . $imageGraph,
436 $x = '',
437 $y = '',
438 $w = 0,
439 $h = 0,
440 $type = '',
441 $link = '',
442 $align = 'N',
443 $resize = false,
444 $dpi = 72,
445 $palign = '',
446 $ismask = false,
447 $imgmask = false,
448 $order = 0,
449 $fitbox = false,
450 $hidden = false,
451 $fitonpage = true,
452 $alt = false,
453 $altimgs = array()
454 );
455
456 unset($imageGraph);
457 }
458
459 /**
460 * Draw the table header (first row)
461 */
462 private function paintReportTableHeader()
463 {
464 $initPosX = 10;
465
466 // Get the longest column name
467 $longestColumnName = '';
468 foreach ($this->reportColumns as $columnName) {
469 if (strlen($columnName) > strlen($longestColumnName)) {
470 $longestColumnName = $columnName;
471 }
472 }
473
474 $columnsCount = count($this->reportColumns);
475 // Computes available column width
476 if ($this->orientation == self::PORTRAIT
477 && $columnsCount <= 3
478 ) {
479 $totalWidth = $this->reportWidthPortrait * 2 / 3;
480 } elseif ($this->orientation == self::LANDSCAPE) {
481 $totalWidth = $this->reportWidthLandscape;
482 } else {
483 $totalWidth = $this->reportWidthPortrait;
484 }
485 $this->totalWidth = $totalWidth;
486 $this->labelCellWidth = max(round(($this->totalWidth / $columnsCount)), $this->minWidthLabelCell);
487 $this->cellWidth = round(($this->totalWidth - $this->labelCellWidth) / ($columnsCount - 1));
488 $this->totalWidth = $this->labelCellWidth + ($columnsCount - 1) * $this->cellWidth;
489
490 $this->TCPDF->SetFillColor($this->tableHeaderBackgroundColor[0], $this->tableHeaderBackgroundColor[1], $this->tableHeaderBackgroundColor[2]);
491 $this->TCPDF->SetTextColor($this->tableHeaderTextColor[0], $this->tableHeaderTextColor[1], $this->tableHeaderTextColor[2]);
492 $this->TCPDF->SetLineWidth(.3);
493 $this->setBorderColor();
494 $this->TCPDF->SetFont($this->reportFont, $this->reportFontStyle);
495 $this->TCPDF->SetFillColor(255);
496 $this->TCPDF->SetTextColor($this->tableHeaderBackgroundColor[0], $this->tableHeaderBackgroundColor[1], $this->tableHeaderBackgroundColor[2]);
497 $this->TCPDF->SetDrawColor(255);
498
499 $posY = $this->TCPDF->GetY();
500 $this->TCPDF->MultiCell($this->cellWidth, $this->cellHeight, $longestColumnName, 1, 'C', true);
501 $maxCellHeight = $this->TCPDF->GetY() - $posY;
502
503 $this->TCPDF->SetFillColor($this->tableHeaderBackgroundColor[0], $this->tableHeaderBackgroundColor[1], $this->tableHeaderBackgroundColor[2]);
504 $this->TCPDF->SetTextColor($this->tableHeaderTextColor[0], $this->tableHeaderTextColor[1], $this->tableHeaderTextColor[2]);
505 $this->TCPDF->SetDrawColor($this->tableCellBorderColor[0], $this->tableCellBorderColor[1], $this->tableCellBorderColor[2]);
506
507 $this->TCPDF->SetXY($initPosX, $posY);
508
509 $countColumns = 0;
510 $posX = $initPosX;
511 foreach ($this->reportColumns as $columnName) {
512 $columnName = $this->formatText($columnName);
513
514 //Label column
515 if ($countColumns == 0) {
516 $this->TCPDF->MultiCell($this->labelCellWidth, $maxCellHeight, $columnName, $border = 0, $align = 'L', true);
517 $this->TCPDF->SetXY($posX + $this->labelCellWidth, $posY);
518 } else {
519 $this->TCPDF->MultiCell($this->cellWidth, $maxCellHeight, $columnName, $border = 0, $align = 'L', true);
520 $this->TCPDF->SetXY($posX + $this->cellWidth, $posY);
521 }
522 $countColumns++;
523 $posX = $this->TCPDF->GetX();
524 }
525 $this->TCPDF->Ln();
526 $this->TCPDF->SetXY($initPosX, $posY + $maxCellHeight);
527 }
528
529 /**
530 * Prints a message
531 *
532 * @param string $message
533 * @return void
534 */
535 private function paintMessage($message)
536 {
537 $this->TCPDF->SetFont($this->reportFont, $this->reportFontStyle, $this->reportSimpleFontSize);
538 $this->TCPDF->SetTextColor($this->reportTextColor[0], $this->reportTextColor[1], $this->reportTextColor[2]);
539 $message = $this->formatText($message);
540 $this->TCPDF->Write("1em", $message);
541 $this->TCPDF->Ln();
542 }
543
544 /**
545 * Get report attachments, ex. graph images
546 *
547 * @param $report
548 * @param $processedReports
549 * @param $prettyDate
550 * @return array
551 */
552 public function getAttachments($report, $processedReports, $prettyDate)
553 {
554 return array();
555 }
556 }
557