1
|
|
|
<?php |
2
|
|
|
|
3
|
|
|
declare(strict_types=1); |
4
|
|
|
|
5
|
|
|
/* |
6
|
|
|
* Jasper report integration for PHP |
7
|
|
|
* |
8
|
|
|
* @link https://github.com/belgattitude/soluble-jasper |
9
|
|
|
* @author Vanvelthem Sébastien |
10
|
|
|
* @copyright Copyright (c) 2017 Vanvelthem Sébastien |
11
|
|
|
* @license MIT |
12
|
|
|
*/ |
13
|
|
|
|
14
|
|
|
namespace Soluble\Jasper\Runner; |
15
|
|
|
|
16
|
|
|
use Psr\Log\LoggerInterface; |
17
|
|
|
use Psr\Log\NullLogger; |
18
|
|
|
use Soluble\Japha\Bridge\Adapter as BridgeAdapter; |
19
|
|
|
use Soluble\Jasper\Context\DefaultClassLoader; |
20
|
|
|
use Soluble\Jasper\Context\DefaultFileResolver; |
21
|
|
|
use Soluble\Jasper\DataSource\Contract\DataSourceInterface; |
22
|
|
|
use Soluble\Jasper\DataSource\Contract\JavaSqlConnectionInterface; |
23
|
|
|
use Soluble\Jasper\DataSource\Contract\JRDataSourceFromDataSourceInterface; |
24
|
|
|
use Soluble\Jasper\DataSource\Contract\JRDataSourceFromReportParamsInterface; |
25
|
|
|
use Soluble\Jasper\DataSource\EmptyDataSource; |
26
|
|
|
use Soluble\Jasper\Exception; |
27
|
|
|
use Soluble\Jasper\Exporter\BridgedExportManager; |
28
|
|
|
use Soluble\Jasper\Exporter\ExportManagerInterface; |
29
|
|
|
use Soluble\Jasper\JRParameter; |
30
|
|
|
use Soluble\Jasper\Proxy\Engine\JasperCompileManager; |
31
|
|
|
use Soluble\Jasper\Proxy\Engine\JasperFillManager; |
32
|
|
|
use Soluble\Jasper\Proxy\Engine\JasperPrint; |
33
|
|
|
use Soluble\Jasper\Proxy\Engine\JasperReport; |
34
|
|
|
use Soluble\Jasper\Report; |
35
|
|
|
use Soluble\Jasper\ReportParams; |
36
|
|
|
|
37
|
|
|
class BridgedReportRunner implements ReportRunnerInterface |
38
|
|
|
{ |
39
|
|
|
/** |
40
|
|
|
* @var BridgeAdapter |
41
|
|
|
*/ |
42
|
|
|
private $ba; |
43
|
|
|
|
44
|
|
|
/** |
45
|
|
|
* @var JasperCompileManager |
46
|
|
|
*/ |
47
|
|
|
private $compileManager; |
48
|
|
|
|
49
|
|
|
/** |
50
|
|
|
* @var LoggerInterface |
51
|
|
|
*/ |
52
|
|
|
private $logger; |
53
|
|
|
|
54
|
16 |
|
public function __construct(BridgeAdapter $bridgeAdapter, LoggerInterface $logger = null) |
55
|
|
|
{ |
56
|
16 |
|
$this->ba = $bridgeAdapter; |
57
|
16 |
|
if ($logger === null) { |
58
|
14 |
|
$logger = new NullLogger(); |
59
|
|
|
} |
60
|
16 |
|
$this->logger = $logger; |
61
|
16 |
|
} |
62
|
|
|
|
63
|
|
|
/** |
64
|
|
|
* @param Report $report |
65
|
|
|
* |
66
|
|
|
* @throws Exception\BrokenXMLReportFileException when cannot parse the xml content or invalid xml file |
67
|
|
|
* @throws Exception\ReportFileNotFoundException when the report file cannot be located (both php and java sides) |
68
|
|
|
* @throws Exception\ReportCompileException when there's an error compiling/evaluating the report |
69
|
|
|
* @throws Exception\JavaProxiedException when the compileReport has encountered a Java error |
70
|
|
|
* @throws Exception\RuntimeException when an unexpected problem have been encountered |
71
|
|
|
* |
72
|
|
|
* @return JasperReport |
73
|
|
|
*/ |
74
|
15 |
|
public function compileReport(Report $report): JasperReport |
75
|
|
|
{ |
76
|
|
|
try { |
77
|
15 |
|
if ($this->compileManager === null) { |
78
|
15 |
|
$this->compileManager = new JasperCompileManager($this->ba); |
79
|
|
|
} |
80
|
15 |
|
$jasperReport = $this->compileManager->compileReport($report->getReportFile()); |
81
|
2 |
|
} catch (\Throwable $e) { |
82
|
2 |
|
$this->logger->error( |
83
|
2 |
|
sprintf( |
84
|
2 |
|
"Compilation of report '%s' failed with '%s' (%s)", |
85
|
2 |
|
basename($report->getReportFile()), |
86
|
2 |
|
(new \ReflectionClass($e))->getShortName(), |
87
|
2 |
|
$e->getMessage() |
88
|
|
|
) |
89
|
|
|
); |
90
|
2 |
|
throw $e; |
91
|
|
|
} |
92
|
|
|
|
93
|
13 |
|
return new JasperReport($this->ba, $jasperReport, $report); |
94
|
|
|
} |
95
|
|
|
|
96
|
|
|
/** |
97
|
|
|
* @param JasperReport $jasperReport The compiled version of the jasper report |
98
|
|
|
* @param ReportParams|null $reportParams if set will override/add to the Report->getReportParams() |
99
|
|
|
* @param DataSourceInterface|null $dataSource if ste, will overrive report datasource |
100
|
|
|
* |
101
|
|
|
* @return JasperPrint |
102
|
|
|
* |
103
|
|
|
* @throws Exception\JavaProxiedException |
104
|
|
|
* @throws Exception\BrokenJsonDataSourceException |
105
|
|
|
*/ |
106
|
10 |
|
public function fillReport( |
107
|
|
|
JasperReport $jasperReport, |
108
|
|
|
ReportParams $reportParams = null, |
109
|
|
|
DataSourceInterface $dataSource = null |
110
|
|
|
): JasperPrint { |
111
|
|
|
try { |
112
|
|
|
// Step 1: Get the fill manager |
113
|
10 |
|
$fillManager = new JasperFillManager($this->ba); |
114
|
|
|
|
115
|
|
|
// Step 2: get the datasource |
116
|
10 |
|
if ($dataSource === null) { |
117
|
8 |
|
$dataSource = $jasperReport->getReport()->getDataSource() ?? new EmptyDataSource(); |
118
|
|
|
} |
119
|
|
|
|
120
|
|
|
// Step 2: Assigning reportParams |
121
|
|
|
|
122
|
10 |
|
$originalReportParams = $jasperReport->getReport()->getReportParams() ?? new ReportParams(); |
123
|
10 |
|
$reportParams = $originalReportParams->withMergedParams($reportParams ?? new ReportParams()); |
124
|
|
|
|
125
|
|
|
// Step 3: Getting some defaults |
126
|
|
|
|
127
|
10 |
|
$reportPath = $jasperReport->getReport()->getReportPath(); |
128
|
10 |
|
$fileResolver = (new DefaultFileResolver($this->ba))->getFileResolver([$reportPath]); |
129
|
10 |
|
$classLoader = (new DefaultClassLoader($this->ba))->getClassLoader([$reportPath]); |
130
|
|
|
//$resourceBundle = (new DefaultResourceBundle($this->>ba))->getResourceBundle(); |
|
|
|
|
131
|
10 |
|
$reportParams->addParams([ |
132
|
10 |
|
JRParameter::REPORT_FILE_RESOLVER => $fileResolver, |
133
|
10 |
|
JRParameter::REPORT_CLASS_LOADER => $classLoader |
134
|
|
|
]); |
135
|
|
|
|
136
|
|
|
// Step 4: Assign parameters from datasource or set the JrDatasource |
137
|
|
|
|
138
|
10 |
|
$javaDataSource = null; |
139
|
10 |
|
if ($dataSource instanceof JRDataSourceFromReportParamsInterface) { |
140
|
3 |
|
$dataSource->assignDataSourceReportParams($reportParams); |
141
|
7 |
|
} elseif ($dataSource instanceof JRDataSourceFromDataSourceInterface) { |
142
|
6 |
|
$javaDataSource = $dataSource->getJRDataSource($this->ba); |
143
|
1 |
|
} elseif ($dataSource instanceof JavaSqlConnectionInterface) { |
144
|
1 |
|
$javaDataSource = $dataSource->getJasperReportSqlConnection($this->ba); |
145
|
|
|
} |
146
|
|
|
|
147
|
10 |
|
$paramsHashMap = $this->ba->java('java.util.HashMap', $reportParams->toArray()); |
148
|
|
|
|
149
|
10 |
|
$jasperPrint = $fillManager->fillReport( |
150
|
10 |
|
$jasperReport->getJavaProxiedObject(), |
151
|
10 |
|
$paramsHashMap, |
152
|
10 |
|
$javaDataSource, |
153
|
10 |
|
$jasperReport->getReport()->getReportFile() |
154
|
|
|
); |
155
|
|
|
|
156
|
8 |
|
return new JasperPrint($jasperPrint, $jasperReport->getReport()); |
157
|
2 |
|
} catch (\Throwable $e) { |
158
|
2 |
|
$this->logger->error( |
159
|
2 |
|
sprintf( |
160
|
2 |
|
"Filling report '%s' failed with '%s' (%s)", |
161
|
2 |
|
basename($jasperReport->getReport()->getReportFile()), |
162
|
2 |
|
(new \ReflectionClass($e))->getShortName(), |
163
|
2 |
|
$e->getMessage() |
164
|
|
|
) |
165
|
|
|
); |
166
|
2 |
|
throw $e; |
167
|
|
|
} |
168
|
|
|
} |
169
|
|
|
|
170
|
6 |
|
public function getExportManager(Report $report): ExportManagerInterface |
171
|
|
|
{ |
172
|
6 |
|
return new BridgedExportManager($this, $report); |
173
|
|
|
} |
174
|
|
|
|
175
|
|
|
public function getLogger(): LoggerInterface |
176
|
|
|
{ |
177
|
|
|
return $this->logger; |
178
|
|
|
} |
179
|
|
|
|
180
|
7 |
|
public function getBridgeAdapter(): BridgeAdapter |
181
|
|
|
{ |
182
|
7 |
|
return $this->ba; |
183
|
|
|
} |
184
|
|
|
} |
185
|
|
|
|
Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.
The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.
This check looks for comments that seem to be mostly valid code and reports them.