1 |
rodolico |
1 |
<?php
|
|
|
2 |
|
14 |
rodolico |
3 |
/*
|
|
|
4 |
Author: R. W. Rodolico
|
|
|
5 |
Date: 20090403
|
|
|
6 |
|
|
|
7 |
Class which holds basic reports for generation in client programs.
|
|
|
8 |
Assumes a database table of at least the following format (all additional columns ignored)
|
|
|
9 |
create table report (
|
|
|
10 |
report_id int unsigned not null auto_increment,
|
|
|
11 |
name varchar(20) not null comment 'Display Name of Report',
|
|
|
12 |
query text not null comment 'Query to be executed',
|
|
|
13 |
parameters text comment 'All parameters used in above',
|
|
|
14 |
primary key (report_id)
|
|
|
15 |
) comment 'holds definition for report';
|
|
|
16 |
|
|
|
17 |
Columns are defined as:
|
|
|
18 |
name -- This is the name of the report for display. This is displayed by Report::listAllReports
|
|
|
19 |
query -- an SQL Query for the report. Parameters may be inserted by surrounding them with '<' and '>'
|
|
|
20 |
and these parameters will be replaced by user input values on execution.
|
|
|
21 |
parameters -- List of parameter information to form query. These are one parameter per line. Each line
|
|
|
22 |
is a $parametersDelimiter delimited string of data.
|
|
|
23 |
|
|
|
24 |
1 - user prompt for value
|
|
|
25 |
2 - query.
|
|
|
26 |
3 - displayQuery
|
|
|
27 |
|
|
|
28 |
This class is free software: you can redistribute it and/or modify
|
|
|
29 |
it under the terms of the GNU General Public License as published by
|
|
|
30 |
the Free Software Foundation, either version 3 of the License, or
|
|
|
31 |
(at your option) any later version.
|
|
|
32 |
|
|
|
33 |
This program is distributed in the hope that it will be useful,
|
|
|
34 |
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
35 |
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
36 |
GNU General Public License for more details.
|
|
|
37 |
|
|
|
38 |
You should have received a copy of the GNU General Public License
|
|
|
39 |
along with this program. If not, see <http://www.gnu.org/licenses/>
|
|
|
40 |
*/
|
|
|
41 |
|
|
|
42 |
/* class QueryParameters
|
|
|
43 |
Designed as a simple helper class to Reports. It simplified the writing of the Reports class by abstracting
|
|
|
44 |
all of the parameters functions. The parameters are a very complex topic in and of themselves.
|
|
|
45 |
*/
|
1 |
rodolico |
46 |
class QueryParameters {
|
14 |
rodolico |
47 |
protected $parameter; // parameter name. matches <param_name> in report query
|
|
|
48 |
protected $prompt; // user prompt when requesting a value for this parameter
|
|
|
49 |
protected $query; // if defined, generates a <select> block to acquire the value for this parameter instead of an <INPUT> block
|
|
|
50 |
protected $displayQuery; // if defined, result is concated with any other displayQuery results for the title of the report
|
|
|
51 |
protected $value; // value used for displayQuery. See documentation
|
|
|
52 |
private $parametersDelimiter = '++'; // parameter delimiter
|
1 |
rodolico |
53 |
|
|
|
54 |
function __constructor ( $parameter = '', $prompt = '', $query = '' ) {
|
|
|
55 |
$this->parameter = $parameter;
|
|
|
56 |
$this->prompt = $prompt;
|
|
|
57 |
$this->query = $query;
|
|
|
58 |
}
|
|
|
59 |
|
14 |
rodolico |
60 |
/* following functions are setters/getters for the class members */
|
|
|
61 |
function parametersDelimiter ( $newDelimiter = '' ) {
|
|
|
62 |
$oldValue = $this->parametersDelimiter;
|
|
|
63 |
if ($newDelimiter) {
|
|
|
64 |
$this->parametersDelimiter = $newDelimiter;
|
|
|
65 |
}
|
|
|
66 |
return $oldValue;
|
1 |
rodolico |
67 |
}
|
|
|
68 |
|
|
|
69 |
function name ( $newParameter = '' ) {
|
|
|
70 |
$oldParameter = $this->parameter;
|
|
|
71 |
if ($newParameter) {
|
|
|
72 |
$this->parameter = $newParameter;
|
|
|
73 |
}
|
|
|
74 |
return $oldParameter;
|
|
|
75 |
}
|
|
|
76 |
|
|
|
77 |
function value ( $newValue = '' ) {
|
|
|
78 |
$oldValue = $this->value;
|
|
|
79 |
if ($newValue) {
|
|
|
80 |
$this->value = $newValue;
|
|
|
81 |
}
|
|
|
82 |
return $oldValue;
|
|
|
83 |
}
|
|
|
84 |
|
|
|
85 |
function prompt ( $newPrompt = '' ) {
|
|
|
86 |
$oldPrompt = $this->prompt;
|
|
|
87 |
if ($newPrompt) {
|
|
|
88 |
$this->prompt = $newPrompt;
|
|
|
89 |
}
|
|
|
90 |
return $oldPrompt;
|
|
|
91 |
}
|
|
|
92 |
|
|
|
93 |
function query ( $newQuery = '' ) {
|
|
|
94 |
$oldQuery = $this->query;
|
|
|
95 |
if ($newQuery) {
|
|
|
96 |
$this->query = $newQuery;
|
|
|
97 |
}
|
|
|
98 |
return $oldQuery;
|
|
|
99 |
}
|
|
|
100 |
|
|
|
101 |
function displayQuery ( $newQuery = '' ) {
|
|
|
102 |
$oldQuery = $this->displayQuery;
|
|
|
103 |
if ($newQuery) {
|
|
|
104 |
$this->displayQuery = $newQuery;
|
|
|
105 |
}
|
|
|
106 |
return $oldQuery;
|
|
|
107 |
}
|
|
|
108 |
|
14 |
rodolico |
109 |
// takes a single line of a parameters entry and breaks it into its values
|
|
|
110 |
function stringToParameter( $string ) {
|
|
|
111 |
$temp = explode( $this->parametersDelimiter, $string );
|
|
|
112 |
$this->parameter = $temp[0];
|
|
|
113 |
$this->prompt = $temp[1];
|
|
|
114 |
$this->query = $temp[2];
|
|
|
115 |
$this->displayQuery = $temp[3];
|
|
|
116 |
}
|
|
|
117 |
|
|
|
118 |
/*
|
|
|
119 |
creates a td with the prompt, and an <input> enter the value for that parameter.
|
|
|
120 |
If query is defined, will generate a <select> instead
|
|
|
121 |
*/
|
1 |
rodolico |
122 |
function toHTML () {
|
|
|
123 |
$result = "<td>$this->prompt</td><td>";
|
|
|
124 |
if ( $this->query ) {
|
|
|
125 |
$result .= "<select name='report_param_$this->parameter'>" . queryToSelect( $this->query ) . '</select>';
|
|
|
126 |
} else {
|
23 |
rodolico |
127 |
$result .= "<input type='text' name='report_param_$this->parameter'>";
|
1 |
rodolico |
128 |
}
|
|
|
129 |
$result .= '</td>';
|
|
|
130 |
return $result;
|
|
|
131 |
}
|
|
|
132 |
} // class QueryParameters
|
14 |
rodolico |
133 |
|
|
|
134 |
/*
|
|
|
135 |
the Report class is designed to be semi-automatic. It can, with little code, create a <select> containing the available reports,
|
|
|
136 |
display any parameters required for that report, then run the report and return a table containing the results.
|
|
|
137 |
*/
|
1 |
rodolico |
138 |
|
|
|
139 |
class Report {
|
14 |
rodolico |
140 |
protected $name; // name of report
|
|
|
141 |
protected $title; // title for the report
|
|
|
142 |
protected $query; // query to generate the report
|
|
|
143 |
protected $parameters = array(); // array of parameters entries for the report. Class QueryParameters
|
1 |
rodolico |
144 |
private $tableName = 'report';
|
|
|
145 |
private $nameField = 'name';
|
|
|
146 |
private $queryField = 'query';
|
|
|
147 |
private $parametersField = 'parameters';
|
|
|
148 |
private $idField = 'report_id';
|
|
|
149 |
|
14 |
rodolico |
150 |
/* will simply get a list of all reports from the table and allow the user to select one */
|
1 |
rodolico |
151 |
static public function listAllReports( $tableName = 'report', $nameField = 'name', $idField = 'report_id' ) {
|
|
|
152 |
return queryToSelect( "select $idField, $nameField from $tableName" );
|
|
|
153 |
}
|
|
|
154 |
|
|
|
155 |
function __constructor ($name = '', $title = '', $query = '', $parameters = array() ) {
|
|
|
156 |
$this->name = $name;
|
|
|
157 |
$this->title = $title;
|
|
|
158 |
$this->query = $query;
|
|
|
159 |
$this->parameters = $parameters;
|
|
|
160 |
}
|
|
|
161 |
|
14 |
rodolico |
162 |
/* setters/getters for the various class members */
|
1 |
rodolico |
163 |
function name ( $newName = '' ) {
|
|
|
164 |
$oldName = $this->name;
|
|
|
165 |
if ($newName) {
|
|
|
166 |
$this->name = $newName;
|
|
|
167 |
}
|
|
|
168 |
return $oldName;
|
|
|
169 |
}
|
|
|
170 |
|
|
|
171 |
function query ( $newQuery = '' ) {
|
|
|
172 |
$oldQuery = $this->query;
|
|
|
173 |
if ($newQuery) {
|
|
|
174 |
$this->query = $newQuery;
|
|
|
175 |
}
|
|
|
176 |
return $oldQuery;
|
|
|
177 |
}
|
|
|
178 |
|
|
|
179 |
function parameters ( $newParameters = array() ) {
|
|
|
180 |
$oldParameters = $this->parameters;
|
|
|
181 |
if ($newParameters) {
|
|
|
182 |
$this->parameters = $newParameters;
|
|
|
183 |
}
|
|
|
184 |
return $oldParameters;
|
|
|
185 |
}
|
|
|
186 |
|
|
|
187 |
function addParameter ( $newParameter = array() ) {
|
|
|
188 |
$this->parameters[] = $newParameter;
|
|
|
189 |
}
|
|
|
190 |
|
14 |
rodolico |
191 |
/* get the report definition from the database. Will decipher the definition, filling out all class members with their values */
|
|
|
192 |
function loadFromDatabase ( $id ) {
|
|
|
193 |
$sql = "select $this->nameField, $this->queryField, $this->parametersField from $this->tableName where $this->idField = $id";
|
|
|
194 |
$result = queryDatabaseExtended( $sql );
|
|
|
195 |
$result = $result['data'][0];
|
|
|
196 |
$this->name = $result[$this->nameField];
|
|
|
197 |
$this->title = $result[$this->nameField];
|
|
|
198 |
$this->query = $result[$this->queryField];
|
|
|
199 |
$parameters = $result[$this->parametersField];
|
|
|
200 |
$parameters = explode("\n", $parameters);
|
|
|
201 |
foreach ( $parameters as $thisParam ) {
|
|
|
202 |
if (! $thisParam ) {
|
|
|
203 |
continue;
|
|
|
204 |
}
|
|
|
205 |
$temp = new QueryParameters();
|
|
|
206 |
$temp->stringToParameter($thisParam);
|
|
|
207 |
$this->parameters[] = $temp;
|
|
|
208 |
}
|
|
|
209 |
}
|
|
|
210 |
|
|
|
211 |
/*
|
|
|
212 |
runs the report
|
20 |
rodolico |
213 |
$parameters, if passed in, is an array of paramtername=>value and will be used in place of any values on the form
|
|
|
214 |
$additionalLimitations is a partial where clause. When passed in, it will replace the special parameter <additionalLimitations>.
|
|
|
215 |
if it is not passed in, <additionalLimitations> will be removed
|
25 |
rodolico |
216 |
$makeTitle, if set to false, will simply return the data in a table. If true, will return the title and the data
|
14 |
rodolico |
217 |
The return value is the title in an H1, the conditions in H2's, and the results in a table
|
|
|
218 |
*/
|
53 |
rodolico |
219 |
function run( $parameters = '', $additionalLimitations = '', $makeTitle = true, $titleTags = array('startTag' => '<h4>', 'endTag' => '</h4>', 'conditionStart' => '<h2>', 'conditionEnd' => '</h2>' ) ) {
|
1 |
rodolico |
220 |
$conditions = array();
|
26 |
rodolico |
221 |
foreach ( $this->parameters as $parameter ) {
|
|
|
222 |
if ( $parameters[$parameter->name()] ) { // in the array passed in
|
|
|
223 |
$parameter->value( $parameters[$parameter->name()] );
|
|
|
224 |
} elseif ($_POST['report_param_' . $parameter->name()]) { // in $_POST
|
|
|
225 |
$parameter->value($_POST['report_param_' . $parameter->name()]);
|
1 |
rodolico |
226 |
}
|
|
|
227 |
}
|
23 |
rodolico |
228 |
// print "<pre>"; print_r( $this ); print "</pre>";
|
1 |
rodolico |
229 |
foreach ( $this->parameters as $parameter ) {
|
|
|
230 |
$toFind = '<' . $parameter->name() . '>';
|
|
|
231 |
$this->query = preg_replace( "/$toFind/", $parameter->value(), $this->query );
|
|
|
232 |
if ( $parameter->displayQuery() ) {
|
|
|
233 |
//$result = preg_replace( '/<value>/', $parameter->value(), $parameter->displayQuery() );
|
23 |
rodolico |
234 |
$sql = preg_replace( '/<value>/', $parameter->value(), $parameter->displayQuery() );
|
|
|
235 |
// print "<pre>$sql</pre>\n";
|
|
|
236 |
$result = queryDatabaseExtended($sql , false);
|
1 |
rodolico |
237 |
//print "<pre>" . print_r( $result ); print "</pre>";
|
|
|
238 |
$conditions[] = $parameter->name() . ' - ' . $result['data'][0][0];
|
|
|
239 |
} else {
|
|
|
240 |
$conditions[] = $parameter->name() . ' - ' . $parameter->value();
|
|
|
241 |
}
|
|
|
242 |
}
|
20 |
rodolico |
243 |
if ($additionalLimitations) { // the user wants us to limit additionally
|
21 |
rodolico |
244 |
$this->query = preg_replace( '/<additionalLimitations>/', ' and ' . $additionalLimitations, $this->query );
|
20 |
rodolico |
245 |
} else {
|
21 |
rodolico |
246 |
$this->query = preg_replace( '/<additionalLimitations>/', '', $this->query );
|
20 |
rodolico |
247 |
}
|
23 |
rodolico |
248 |
// print "<pre>$this->query</pre>";
|
53 |
rodolico |
249 |
$return = queryToTable($this->query);
|
|
|
250 |
if ( $return && $makeTitle ) {
|
|
|
251 |
$return = $titleTags['startTag'] . $this->title . $titleTags['endTag'] .
|
|
|
252 |
$titleTags['conditionStart'] .
|
|
|
253 |
implode($titleTags['conditionEnd'] . $titleTags['conditionStart'], $conditions) .
|
|
|
254 |
$titleTags['conditionEnd'] .
|
|
|
255 |
$return;
|
|
|
256 |
}
|
|
|
257 |
return $return;
|
1 |
rodolico |
258 |
}
|
|
|
259 |
|
14 |
rodolico |
260 |
/*
|
|
|
261 |
Creates a table with the necessary INPUT or SELECT fields to get the parameter values from the user
|
|
|
262 |
returns a table suitable for inserting into a FORM
|
|
|
263 |
*/
|
|
|
264 |
function parameterInputScreen () {
|
1 |
rodolico |
265 |
$result = "<table border='1'>\n";
|
|
|
266 |
$result .= "<tr><td colspan='2'>$this->name</td></tr>";
|
|
|
267 |
foreach ( $this->parameters as $parameter ) {
|
|
|
268 |
$result .= '<tr>' . $parameter->toHTML() . '</tr>';
|
|
|
269 |
}
|
23 |
rodolico |
270 |
return $result . '</table>';
|
1 |
rodolico |
271 |
}
|
14 |
rodolico |
272 |
|
|
|
273 |
// kept because some code used the old name. I messed up when I wrote the original. I don't think the name is indicative of the
|
|
|
274 |
// use of this function. This will be removed in the future.
|
|
|
275 |
function toHTML( ) {
|
|
|
276 |
return parameterInputScreen();
|
|
|
277 |
}
|
1 |
rodolico |
278 |
|
|
|
279 |
} // class Report
|
|
|
280 |
|
53 |
rodolico |
281 |
?>
|