36 |
rodolico |
1 |
<?php
|
|
|
2 |
|
38 |
rodolico |
3 |
/* database.class.php
|
|
|
4 |
Author: R. W. Rodolico (rodo at dailydata.net)
|
|
|
5 |
GNU Public License
|
|
|
6 |
20091023
|
|
|
7 |
|
|
|
8 |
Encapsulates a database, specifically targeting allowing a database and HTML forms to interact
|
|
|
9 |
Main function is to allow editing of databases simply by defining the database structure in a variable
|
|
|
10 |
|
|
|
11 |
This code was written in procedural form in my library.php, but the decision to "objectify" it was made
|
|
|
12 |
for ease of maintenance in the future. For example, I had thought to define columns that would be editable
|
|
|
13 |
in an HTML widget, or special needs column types such as columns with special content (ie, one application
|
|
|
14 |
we have stores PHP in a text column, and another stores menus and reports in two tables with very weird
|
|
|
15 |
storage requirements). By simply adding extensions to the basic DBColumn class, these special purpose
|
|
|
16 |
uses can be rapidly created.
|
|
|
17 |
|
|
|
18 |
A database object may be created manually, or may be created as an array of information
|
|
|
19 |
|
|
|
20 |
*/
|
|
|
21 |
|
|
|
22 |
|
36 |
rodolico |
23 |
|
38 |
rodolico |
24 |
|
40 |
rodolico |
25 |
require_once "Logging.class.php"; // For logging
|
38 |
rodolico |
26 |
|
36 |
rodolico |
27 |
/*
|
|
|
28 |
This is the basic column type. It is a simple string,
|
|
|
29 |
left justified on HTML display
|
|
|
30 |
<input type='text'> for form input
|
|
|
31 |
varchar for db storage
|
|
|
32 |
It is also used as the basis for all of the other column types
|
|
|
33 |
*/
|
|
|
34 |
|
|
|
35 |
|
|
|
36 |
/*
|
|
|
37 |
CSS Classes used
|
|
|
38 |
db_string display and input a string
|
|
|
39 |
db_field_name display table column header or td
|
|
|
40 |
db_textarea display and input textarea (td or <textarea>)
|
|
|
41 |
db_bool display and input true/false (radio)
|
|
|
42 |
db_date display and input date (text)
|
|
|
43 |
db_datetime display and input date and time (text)
|
|
|
44 |
db_int display and input integers
|
|
|
45 |
db_real display and input floating point numbers
|
|
|
46 |
db_password display and input password (password, display is a series of 8 asterisks)
|
|
|
47 |
db_file display and input file (type="file")
|
|
|
48 |
*/
|
|
|
49 |
|
|
|
50 |
class DBColumn {
|
|
|
51 |
/*
|
|
|
52 |
A column has
|
|
|
53 |
name
|
|
|
54 |
type (used to define how it is processed)
|
|
|
55 |
nullable (if it can be null or not)
|
|
|
56 |
default value (used if creating a row)
|
|
|
57 |
required (must have a non-null value entered)
|
|
|
58 |
readOnly (will be displayed as text in an input form)
|
|
|
59 |
width (size of the actual field)
|
|
|
60 |
*/
|
|
|
61 |
public $columnName; // name in database
|
|
|
62 |
public $primaryKey; // true if this is a member of the primary key
|
|
|
63 |
public $displayName; // human readable name, uses $columnName if not defined
|
|
|
64 |
public $value; // in most cases, can hold the actual value (not type file or manyToMany)
|
|
|
65 |
public $required; // if false, may be set to null
|
|
|
66 |
public $default; // for not null columns, what value to use if it is null. Also displayed on creation of an insert new row screen
|
37 |
rodolico |
67 |
public $readOnly; // if set, an input field will not be created for this column; it will be displayed instead.
|
36 |
rodolico |
68 |
public $width; // width of input field and/or html display
|
38 |
rodolico |
69 |
public $nullable; // true/false if it can be null (as opposed to empty)
|
36 |
rodolico |
70 |
|
|
|
71 |
/*
|
|
|
72 |
display and data input are based upon these three display templates
|
|
|
73 |
These templates can be modified at runtime by the appropriate functions
|
|
|
74 |
Templates built in assume data will be displayed in a table
|
|
|
75 |
NOTE: these templates have class attributes which may be loaded via a css file to ease formatting
|
|
|
76 |
*/
|
|
|
77 |
protected $HTMLHeaderTemplate = '<td class="db_field_name">~~display_name~~</td>';
|
|
|
78 |
protected $HTMLValueTemplate = '<td class="db_string">~~value~~</td>';
|
|
|
79 |
protected $HTMLInputTemplate = '<td class="db_field_name">~~display_name~~</td><td ><input type="text" name="~~column_name~~" class="db_string"> value="~~value~~"</td>';
|
|
|
80 |
|
|
|
81 |
// Accepts a column name (required), and array of definitions, and a value (both optional)
|
|
|
82 |
public function __construct ( $columnName, $definition = '', $value='') {
|
|
|
83 |
$this->columnName = $columnName;
|
|
|
84 |
$this->value = $value;
|
|
|
85 |
$this->displayName = $definition['display name'];
|
|
|
86 |
$this->required = $definition['required'];
|
|
|
87 |
$this->default = $definition['default'];
|
|
|
88 |
$this->width = $definition['width'];
|
|
|
89 |
$this->readOnly = $definition['readonly'];
|
|
|
90 |
if ( $definition['default'] == 'null' or $definition['null_ok'] ) {
|
|
|
91 |
$this->null = true;
|
|
|
92 |
$this->default = '';
|
|
|
93 |
}
|
|
|
94 |
$this->primaryKey = ($definition['keyfield'] ? true : false);
|
|
|
95 |
} // function __construct
|
|
|
96 |
|
|
|
97 |
// following three functions simply allow user to set and get values for the different templates
|
|
|
98 |
public function valueTemplate( $newValue = '' ) {
|
|
|
99 |
$returnValue = $HTMLValueTemplate;
|
|
|
100 |
if ($newValue) {
|
|
|
101 |
$HTMLValueTemplate = $newValue;
|
|
|
102 |
}
|
|
|
103 |
return $returnValue;
|
|
|
104 |
}
|
|
|
105 |
public function headerTemplate( $newValue = '' ) {
|
|
|
106 |
$returnValue = $HTMLHeaderTemplate;
|
|
|
107 |
if ($newValue) {
|
|
|
108 |
$HTMLHeaderTemplate = $newValue;
|
|
|
109 |
}
|
|
|
110 |
return $returnValue;
|
|
|
111 |
}
|
37 |
rodolico |
112 |
public function inputTemplate( $newValue = '' ) {
|
36 |
rodolico |
113 |
$returnValue = $HTMLInputTemplate;
|
|
|
114 |
if ($newValue) {
|
|
|
115 |
$HTMLInputTemplate = $newValue;
|
|
|
116 |
}
|
|
|
117 |
return $returnValue;
|
|
|
118 |
}
|
|
|
119 |
|
37 |
rodolico |
120 |
/*
|
|
|
121 |
function takes a string, and looks for the array names in $values, replacing occurrences of it with
|
36 |
rodolico |
122 |
*/
|
37 |
rodolico |
123 |
private function replaceTokens ( $string, $values ) {
|
36 |
rodolico |
124 |
foreach( $values as $token => $value ) {
|
|
|
125 |
$string = preg_replace("/$token/", $value, $string);
|
|
|
126 |
}
|
|
|
127 |
return $string;
|
|
|
128 |
}
|
|
|
129 |
|
38 |
rodolico |
130 |
function makeSafeSQLValue ( $value = '' ) {
|
|
|
131 |
if ($value) {
|
|
|
132 |
$this->value = $value;
|
|
|
133 |
}
|
|
|
134 |
if (strlen($this->value)) { // it actually has a value
|
|
|
135 |
if(get_magic_quotes_gpc()) {
|
|
|
136 |
$this->value = stripslashes($this->value);
|
|
|
137 |
}
|
|
|
138 |
$this->value = mysql_real_escape_string( $this->value );
|
|
|
139 |
$this->value = "'" . $this->value . "'"; // put the quotes around it
|
|
|
140 |
} else {
|
|
|
141 |
$this->value = ($this->nullable ? 'null' : "''");
|
|
|
142 |
}
|
|
|
143 |
return $this->value;
|
|
|
144 |
}
|
|
|
145 |
|
36 |
rodolico |
146 |
/* function will return a display field based on template, with the value inside it */
|
|
|
147 |
public function displayHTML ($template = '') {
|
|
|
148 |
return replaceTokens($HTMLValueTemplate, array('~~value~~'=>$this->value));
|
|
|
149 |
} // function displayHTML
|
|
|
150 |
|
|
|
151 |
/* function will return a formatted header for column names of tables, etc... */
|
|
|
152 |
public function HTMLColumnName ($template = '') {
|
|
|
153 |
return replaceTokens($HTMLHeaderTemplate, array('~~display_name~~'=>($this->displayName ? $this->displayName : $this->columnName),
|
|
|
154 |
'~~column_name~~' => $this->columnName));
|
|
|
155 |
} // function HTMLColumnName
|
|
|
156 |
|
|
|
157 |
/* function will return an input field */
|
|
|
158 |
public function HTMLInputField ($template = '') {
|
|
|
159 |
return replaceTokens($HTMLInputTemplate, array( '~~display_name~~'=>($this->displayName ? $this->displayName : $this->columnName),
|
37 |
rodolico |
160 |
'~~column_name~~' => $this->columnName,
|
36 |
rodolico |
161 |
'~~value~~'=>$this->value
|
|
|
162 |
)
|
|
|
163 |
);
|
|
|
164 |
} // function HTMLInputField
|
|
|
165 |
|
|
|
166 |
}
|
|
|
167 |
|
|
|
168 |
/* ======================================================================================================================
|
|
|
169 |
class DBColumnBool
|
|
|
170 |
Used for multi row columns, ie HTML TextArea's and DB Text columns
|
|
|
171 |
*/
|
|
|
172 |
class DBColumnText extends DBColumn {
|
|
|
173 |
protected $HTMLInputTemplate = '<td class="db_field_name">~~display_name~~</td><td><textarea name="~~column_name~~" class="db_textarea">~~value~~</textarea>';
|
|
|
174 |
protected $HTMLValueTemplate = '<td class="db_textarea">~~value~~</td>';
|
38 |
rodolico |
175 |
public $HTML = false; // if true, field contains HTML
|
36 |
rodolico |
176 |
} // class DBColumnText
|
|
|
177 |
|
|
|
178 |
/* ======================================================================================================================
|
|
|
179 |
class DBColumnBool
|
|
|
180 |
used for True/False, 1/0, etc...
|
|
|
181 |
html display T or F (can be overridden)
|
|
|
182 |
Input is a True/False drop down on form input
|
|
|
183 |
Stored in a char
|
|
|
184 |
*/
|
|
|
185 |
class DBColumnBool extends DBColumn {
|
|
|
186 |
protected $HTMLInputTemplate = '<td class="db_field_name">~~display_name~~</td><td><INPUT class="db_bool" type="radio" ~~checked~~ name="~~column_name~~"></td>';
|
|
|
187 |
protected $HTMLValueTemplate = '<td class="db_bool">~~value~~</td>';
|
38 |
rodolico |
188 |
public $falseValues; // array containing the values considered as the keys. If '' is included, an empty string is considered false also
|
36 |
rodolico |
189 |
|
|
|
190 |
/* function will return a display field based on template, with the value inside it */
|
|
|
191 |
public function displayHTML ($template = '') {
|
|
|
192 |
return replaceTokens($HTMLValueTemplate, array('~~value~~'=>($this->value ? 'true' : 'false')));
|
|
|
193 |
} // function displayHTML
|
|
|
194 |
|
|
|
195 |
public function HTMLInputField ($template = '') {
|
|
|
196 |
return replaceTokens($HTMLInputTemplate, array( '~~display_name~~'=>($this->displayName ? $this->displayName : $this->columnName),
|
37 |
rodolico |
197 |
'~~column_name~~' => $this->columnName,
|
36 |
rodolico |
198 |
'~~checked~~'=> ($this->value ? 'checked' : '' ) // puts a check mark in if the value is true
|
|
|
199 |
)
|
|
|
200 |
);
|
|
|
201 |
} // function HTMLInputField
|
38 |
rodolico |
202 |
|
|
|
203 |
public function __construct ( $columnName, $definition = '', $value='') {
|
|
|
204 |
parent::__construct( $columnName, $definitions = '', $value = '' ); // first call base class
|
|
|
205 |
$this->falseValues = $definitions['null values'] ? $definitions['null values'] : array ( 'f' => 1, 'F' => 1, 'n' => 1, 'N' => 1, '0' => 1, '' => 1 );
|
|
|
206 |
} // function __construct
|
|
|
207 |
|
|
|
208 |
public function makeSafeSQLValue ( $value = '' ) {
|
|
|
209 |
// definition of values which will be interpreted as false
|
|
|
210 |
if ($value) {
|
|
|
211 |
$this->value = ($value == 'null' ? '' : $value);
|
|
|
212 |
}
|
|
|
213 |
if ($this->value) {
|
|
|
214 |
$this->value = $this->falseValues[$this->value] ? '0' : '1';
|
|
|
215 |
} else {
|
|
|
216 |
$this->value = ($this->nullable ? 'null' : "'0'");
|
|
|
217 |
}
|
|
|
218 |
return $this->value;
|
|
|
219 |
} // function makeSafeSQLValue
|
|
|
220 |
|
36 |
rodolico |
221 |
} // class DBColumnBool
|
|
|
222 |
|
|
|
223 |
/* ======================================================================================================================
|
|
|
224 |
class DBColumnDate
|
|
|
225 |
holds a date only (ie, no time)
|
|
|
226 |
html display is yyyy-mm-dd (can be overridden)
|
|
|
227 |
input uses advanced library
|
|
|
228 |
stored in a date
|
|
|
229 |
*/
|
|
|
230 |
class DBColumnDate extends DBColumn {
|
|
|
231 |
protected $HTMLValueTemplate = '<td class="db_date">~~value~~</td>';
|
|
|
232 |
protected $HTMLInputTemplate = '<td class="db_field_name">~~display_name~~</td><td ><input type="text" name="~~column_name~~" class="db_date"> value="~~value~~"</td>';
|
38 |
rodolico |
233 |
|
|
|
234 |
function makeSafeSQLValue ( $value = '' ) {
|
|
|
235 |
if ($value) {
|
|
|
236 |
$this->value = ($value == 'null' ? '' : $value);
|
|
|
237 |
}
|
|
|
238 |
if ( $result = strtotime( $value ) ) {
|
|
|
239 |
$this->value = "'" . Date( 'Y-m-d', $result) . "'";
|
|
|
240 |
} else {
|
|
|
241 |
$this->value = ($this->nullable ? 'null' : "'0000-00-00'");
|
|
|
242 |
}
|
|
|
243 |
return $this->value;
|
|
|
244 |
}
|
|
|
245 |
|
36 |
rodolico |
246 |
} // class DBColumnDate
|
|
|
247 |
|
|
|
248 |
/* ======================================================================================================================
|
|
|
249 |
class DBColumnDateTime
|
|
|
250 |
holds a date time stamp
|
|
|
251 |
html display is yyyy-mm-dd hh:mm:ss (can be overridden)
|
|
|
252 |
input uses advanced library
|
|
|
253 |
stored in datetime
|
|
|
254 |
*/
|
|
|
255 |
class DBColumnDateTime extends DBColumn {
|
|
|
256 |
protected $HTMLValueTemplate = '<td class="db_datetime">~~value~~</td>';
|
|
|
257 |
protected $HTMLInputTemplate = '<td class="db_field_name">~~display_name~~</td><td ><input type="text" name="~~column_name~~" class="db_datetime"> value="~~value~~"</td>';
|
38 |
rodolico |
258 |
|
|
|
259 |
function makeSafeSQLValue ( $value = '' ) {
|
|
|
260 |
if ($value) {
|
|
|
261 |
$this->value = ($value == 'null' ? '' : $value);
|
|
|
262 |
}
|
|
|
263 |
if ( $result = strtotime( $this->value ) ) {
|
|
|
264 |
$this->value = "'" . Date( 'Y-m-d H:i:s', $result) . "'";
|
|
|
265 |
} else {
|
|
|
266 |
$this->value = ($this->nullable ? 'null' : "'0000-00-00 00:00:00'");
|
|
|
267 |
}
|
|
|
268 |
return $this->value;
|
|
|
269 |
}
|
|
|
270 |
|
|
|
271 |
|
|
|
272 |
|
36 |
rodolico |
273 |
} // class DBColumnDateTime
|
|
|
274 |
|
|
|
275 |
/* ======================================================================================================================
|
|
|
276 |
class DBColumnInt
|
|
|
277 |
holds an integer
|
|
|
278 |
html display is right justified
|
|
|
279 |
input verifies numerics only
|
|
|
280 |
stored in int (may be stored in int unsigned)
|
|
|
281 |
*/
|
|
|
282 |
class DBColumnInt extends DBColumn {
|
|
|
283 |
protected $HTMLValueTemplate = '<td class="db_int">~~value~~</td>';
|
|
|
284 |
protected $HTMLInputTemplate = '<td class="db_field_name">~~display_name~~</td><td ><input type="text" name="~~column_name~~" class="db_int"> value="~~value~~"</td>';
|
|
|
285 |
public $range; // if defined, number must be within this range
|
|
|
286 |
public $signed = true; // if false, uses int unsigned
|
|
|
287 |
|
|
|
288 |
public function __constructor( $columnName, $definitions = '', $value = '') {
|
|
|
289 |
parent::__construct( $columnName, $definitions = '', $value = '' ); // first call base class
|
|
|
290 |
if ($definition['min']) {
|
|
|
291 |
$this->range['min'] = $definition['min'];
|
|
|
292 |
}
|
|
|
293 |
if ($definition['max']) {
|
|
|
294 |
$this->range['max'] = $definition['max'];
|
|
|
295 |
}
|
|
|
296 |
if ($definition['signed']) {
|
|
|
297 |
$this->signed = $definition['signed'];
|
|
|
298 |
}
|
|
|
299 |
} // function __constructor
|
|
|
300 |
|
38 |
rodolico |
301 |
function makeSafeSQLValue ( $value = '' ) { // simply remove all non-numerics
|
|
|
302 |
if ($value) {
|
|
|
303 |
$this->value = $value = 'null' ? '' : $value;
|
|
|
304 |
}
|
|
|
305 |
$this->value = preg_replace( '/[^0-9]/', '', $this->value );
|
|
|
306 |
if ( ! strlen($this->value) ) {
|
|
|
307 |
$this->value = $this->nullable ? 'null' : '0';
|
|
|
308 |
}
|
|
|
309 |
return $this->value;
|
|
|
310 |
}
|
|
|
311 |
|
36 |
rodolico |
312 |
} // class DBColumnInt
|
|
|
313 |
|
|
|
314 |
/* ======================================================================================================================
|
|
|
315 |
class DBColumnReal
|
|
|
316 |
holds a floating point number
|
|
|
317 |
html display is right justified
|
|
|
318 |
may be padded
|
|
|
319 |
input verfies floating point number
|
|
|
320 |
stored in float
|
|
|
321 |
*/
|
|
|
322 |
class DBColumnReal extends DBColumnInt {
|
|
|
323 |
public $decimalPlaces;
|
|
|
324 |
protected $HTMLValueTemplate = '<td class="db_real">~~value~~</td>';
|
|
|
325 |
protected $HTMLInputTemplate = '<td class="db_field_name">~~display_name~~</td><td ><input type="text" name="~~column_name~~" class="db_real"> value="~~value~~"</td>';
|
|
|
326 |
|
|
|
327 |
public function __constructor( $columnName, $definitions = '', $value = '') {
|
|
|
328 |
parent::__construct( $columnName, $definitions = '', $value = '' ); // first call base class
|
|
|
329 |
$this->decimalPlaces = $definition['decimal places'];
|
|
|
330 |
} // function __constructor
|
|
|
331 |
|
38 |
rodolico |
332 |
function makeSafeSQLValue ( $value = '' ) { // same as int version, but allows periods
|
|
|
333 |
if ($value) {
|
|
|
334 |
$this->value = $value = 'null' ? '' : $value;
|
|
|
335 |
}
|
|
|
336 |
$this->value = preg_replace( '/[^0-9.]/', '', $this->value );
|
|
|
337 |
if ( ! strlen($this->value) ) {
|
|
|
338 |
$this->value = $this->nullable ? 'null' : '0';
|
|
|
339 |
}
|
|
|
340 |
return $this->value;
|
|
|
341 |
}
|
|
|
342 |
|
36 |
rodolico |
343 |
} // class DBColumnReal
|
|
|
344 |
|
|
|
345 |
/* ======================================================================================================================
|
|
|
346 |
class DBColumnPassword
|
|
|
347 |
holds a hash of a password
|
|
|
348 |
HTML display is a series of 8 stars
|
|
|
349 |
html input is type='password'
|
|
|
350 |
stored in a char(32). This is the MD5 sum of the password
|
|
|
351 |
*/
|
|
|
352 |
class DBColumnPassword extends DBColumn {
|
|
|
353 |
protected $HTMLValueTemplate = '<td class="db_password">********</td>';
|
|
|
354 |
protected $HTMLInputTemplate = '<td class="db_field_name">~~display_name~~</td><td ><input type="password" name="~~column_name~~" class="db_password"> value="~~value~~"</td>';
|
38 |
rodolico |
355 |
|
|
|
356 |
function makeSafeSQLValue ( $value = '' ) {
|
|
|
357 |
parent::__makeSafeSQLValue( $value ); // first, process as a string
|
|
|
358 |
$this->value = 'MD5(' . $this->value . ')'; // then, set it to call the MD5 function MySQL, PostgreSQL, Oracle. MS SQL-Server does not have this function
|
|
|
359 |
}
|
|
|
360 |
|
36 |
rodolico |
361 |
} // class DBColumnPassword
|
|
|
362 |
|
|
|
363 |
/* ======================================================================================================================
|
|
|
364 |
class DBColumnFile
|
|
|
365 |
holds file
|
|
|
366 |
html display is file name, click to download
|
|
|
367 |
input is type='file'
|
|
|
368 |
stored either in a blob, or in a varchar as the filename on disk
|
|
|
369 |
*/
|
|
|
370 |
class DBColumnFile extends DBColumn {
|
|
|
371 |
public $viewable; // if true, can be displayed on screen, ie pictures
|
|
|
372 |
public $onDisk = true; // if false, this is a blob column which contains the file. If true, it is a varchar which contains the path
|
|
|
373 |
protected $HTMLValueTemplate = '<td class="db_file">~~value~~</td>';
|
|
|
374 |
protected $HTMLInputTemplate = '<td class="db_field_name">~~display_name~~</td><td ><input type="file" name="~~column_name~~" class="db_file"> value="~~value~~"</td>';
|
|
|
375 |
|
|
|
376 |
public function __constructor( $columnName, $definitions = '', $value = '') {
|
|
|
377 |
parent::__construct( $columnName, $definitions = '', $value = '' ); // first call base class
|
|
|
378 |
$this->viewable = $definition['viewable'];
|
|
|
379 |
} // function __constructor
|
|
|
380 |
|
|
|
381 |
} // class DBColumnFile
|
|
|
382 |
|
|
|
383 |
/* ======================================================================================================================
|
|
|
384 |
class DBColumnLookup
|
|
|
385 |
Holds a foreign key value
|
|
|
386 |
html display is target entry
|
|
|
387 |
input is a dropdown
|
|
|
388 |
stored as an int unsigned foreign key (tablename.primary key)
|
|
|
389 |
The display will be a drop down box which will be filled with display values from the foreign table
|
|
|
390 |
Basically, will generate the query
|
|
|
391 |
select $this->$remotePrimaryKey,$this->remoteDisplayField
|
|
|
392 |
from $this->remoteTableName
|
|
|
393 |
where $this->filter
|
|
|
394 |
sort by $this->sortOrder
|
|
|
395 |
|
|
|
396 |
where
|
|
|
397 |
'$this->filter' will only be used if it is non-null (otherwise, there will be no where clause)
|
|
|
398 |
'sort by $this->sortOrder' will only be used if $sortOrder is non-null (otherwise, there will be no sort by)
|
|
|
399 |
$remoteDisplayField must resolve to a single column in the query result, ie concat(field1, field2), not field1,field2
|
|
|
400 |
|
|
|
401 |
The <select> box will have the remote field highlighted that corresponds to $this->value
|
|
|
402 |
If $this->value is null and this is a nullable field, the special text "No Value" is added to the <select> box
|
|
|
403 |
If $this->value is null and this is not a nullable field, the first item in the drop down will be selected.
|
|
|
404 |
*/
|
|
|
405 |
class DBColumnLookup extends DBColumn {
|
|
|
406 |
protected $remoteTableName; // the actual table name in the database that is used for lookups
|
|
|
407 |
protected $remotePrimaryKey; // column name in $remoteTableName that matches this columns value
|
|
|
408 |
protected $remoteDisplayField; // a string used in select statement to build a display
|
|
|
409 |
protected $filter; // if set, will generate an additional where clause (anded) to limit the display of fields
|
|
|
410 |
protected $sortOrder; // if set, will generate a sort by clause to determine display order
|
|
|
411 |
protected $HTMLValueTemplate = '<td class="db_file">********</td>';
|
|
|
412 |
protected $HTMLInputTemplate = '<td class="db_field_name">~~display_name~~</td><td ><select name="~~column_name~~" class="db_file">~~value~~</select></td>';
|
|
|
413 |
|
|
|
414 |
public function __constructor( $columnName, $definitions = '', $value = '') {
|
|
|
415 |
parent::__construct( $columnName, $definitions = '', $value = '' ); // first call base class
|
|
|
416 |
$this->remoteTableName = $definition['table'];
|
|
|
417 |
$this->remotePrimaryKey = array($definition['keyfiled']);
|
|
|
418 |
$this->remoteDisplayField = $definition['display_field'];
|
|
|
419 |
$this->filter = $definition['filter'];
|
|
|
420 |
$this->sortOrder = $definition['sort by'];
|
|
|
421 |
} // function __constructor
|
|
|
422 |
|
|
|
423 |
|
|
|
424 |
/* function will return an input field */
|
|
|
425 |
public function HTMLInputField ($template = '') {
|
|
|
426 |
$dropDown = makeDropDown ( $this->remoteTableName,
|
|
|
427 |
$this->remotePrimaryKey,
|
|
|
428 |
$this->remoteDisplayField,
|
|
|
429 |
$this->value
|
|
|
430 |
);
|
|
|
431 |
|
|
|
432 |
return replaceTokens($HTMLInputTemplate, array( '~~display_name~~'=>($this->displayName ? $this->displayName : $this->columnName),
|
37 |
rodolico |
433 |
'~~column_name~~' => $this->columnName,
|
36 |
rodolico |
434 |
'~~value~~'=>$this->$dropDown
|
|
|
435 |
)
|
|
|
436 |
);
|
|
|
437 |
} // function HTMLInputField
|
|
|
438 |
|
|
|
439 |
// finds value in child table and simply displays it
|
|
|
440 |
public function displayHTML ($template = '') {
|
|
|
441 |
$display = getOneDBValue("select $this->remoteDisplayField from $this->remoteTableName where $this->remotePrimaryKey = $value");
|
|
|
442 |
return replaceTokens($HTMLValueTemplate, array('~~value~~'=>$display));
|
|
|
443 |
} // function displayHTML
|
|
|
444 |
|
|
|
445 |
} // class DBColumnLookup
|
|
|
446 |
|
|
|
447 |
/* ======================================================================================================================
|
|
|
448 |
class DBColumnManyToMany
|
|
|
449 |
simply indicates a one to many relationship
|
|
|
450 |
HTML display is a list of remote table values
|
|
|
451 |
input is a multi-select
|
|
|
452 |
stored as a secondary table with
|
|
|
453 |
one set of columns containing the primary key of this table
|
|
|
454 |
second set of column containing the primary key of a second table.
|
|
|
455 |
*/
|
|
|
456 |
class DBColumnManyToMany extends DBColumn {
|
|
|
457 |
} // class DBColumnManyToMany
|
|
|
458 |
|
38 |
rodolico |
459 |
/*
|
|
|
460 |
This is the basics of a record. Made up of columns, it is designed to hold, create and edit
|
|
|
461 |
a single record of a table
|
|
|
462 |
*/
|
|
|
463 |
class DBRecord {
|
|
|
464 |
protected $table;
|
|
|
465 |
|
|
|
466 |
// The first value is of type DBTable. The primary key columns should be populated
|
|
|
467 |
public function __construct( $table ) {
|
|
|
468 |
if ( $table instanceof DBTable ) { // check to ensure they have passed in a standard table object
|
|
|
469 |
$this->table = $table;
|
|
|
470 |
} else {
|
|
|
471 |
throw new Exception ('DBRecord->__construct: first parameter must by of type DBTable (database.class.php)');
|
|
|
472 |
} // if..else
|
|
|
473 |
} // function __construct
|
|
|
474 |
|
|
|
475 |
public function loadFromDatabase ( $keyValues = '' ) {
|
|
|
476 |
/* foreach ( $keyValues as $columnName => $value ) {
|
|
|
477 |
$this->table->columns[$columnName] = $value;
|
|
|
478 |
} */
|
40 |
rodolico |
479 |
require_once( 'DBQuery.class.php' );
|
|
|
480 |
$query = new DBQuery( $this->table->getOneRowQuery( ) );
|
|
|
481 |
$query->useAssociativeArray = true;
|
|
|
482 |
if ($query->run()) {
|
|
|
483 |
if ( $query->rowsAffected == 1 ) {
|
|
|
484 |
// print_r( $query);
|
|
|
485 |
foreach ($query->returnData[0] as $thisColumn => $thisValue ) {
|
|
|
486 |
$this->table->columns[$thisColumn]->value = $thisValue;
|
|
|
487 |
}
|
|
|
488 |
} else {
|
|
|
489 |
throw new Exception ('DBRecord->loadFromDatabase returned ' . $info['count'] . ' rows, expected 1' );
|
38 |
rodolico |
490 |
}
|
|
|
491 |
} else {
|
40 |
rodolico |
492 |
print "$query->error\n";
|
38 |
rodolico |
493 |
}
|
|
|
494 |
} // loadFromDatabase
|
|
|
495 |
|
|
|
496 |
} // class DBRecord
|
36 |
rodolico |
497 |
|
40 |
rodolico |
498 |
|
36 |
rodolico |
499 |
/*
|
|
|
500 |
A table is made up of columns
|
|
|
501 |
A table has relationships with other tables
|
|
|
502 |
A table has an array (possibly null) of columns that make up the primary key
|
|
|
503 |
A table has an array of columns displayed for choosing a row from a list
|
|
|
504 |
A table has a (possibly null) query to display the list. If null, will default to select *
|
|
|
505 |
*/
|
|
|
506 |
class DBTable {
|
38 |
rodolico |
507 |
public $tableName;
|
|
|
508 |
public $columns;
|
36 |
rodolico |
509 |
public $displayName;
|
|
|
510 |
public $displayColumns;
|
|
|
511 |
public $displayQuery;
|
|
|
512 |
|
|
|
513 |
public function __construct( $tableName, $displayName = '', $displayColumns = '', $displayQuery = '', $columnDefinitionArray = '' ) {
|
|
|
514 |
$this->tableName = $tableName;
|
|
|
515 |
// if a display name is not passed in, use the table name
|
|
|
516 |
$this->displayName = ($displayName ? $displayName : $tableName );
|
|
|
517 |
// if a list of display columns is not passed in, use the column names from the column definition
|
|
|
518 |
$this->displayColumns = ($displayColumns ? $displayColumns : array_keys($columnDefinitionArray) );
|
|
|
519 |
// if a display query is not passwd in, just do a select *
|
|
|
520 |
$this->displayQuery = ($displayQuery ? $displayQuery : "select * from $this->tableName" );
|
|
|
521 |
// get the column definitions
|
37 |
rodolico |
522 |
$this->columnDefinitionsArrayToObject( $columnDefinitionArray );
|
36 |
rodolico |
523 |
} // function __construct
|
|
|
524 |
|
|
|
525 |
|
|
|
526 |
// Will create an array of DBColumns based upon the definition in $arr
|
|
|
527 |
// see information in separate file for definition of array
|
37 |
rodolico |
528 |
public function columnDefinitionsArrayToObject ( $arr ) {
|
38 |
rodolico |
529 |
|
36 |
rodolico |
530 |
$thisColumn;
|
|
|
531 |
foreach ( $arr as $columnName => $definitions ) {
|
|
|
532 |
switch ( $definitions['type'] ) {
|
|
|
533 |
case 'text' : $thisColumn = new DBColumnText($columnName, $definitions );
|
|
|
534 |
break;
|
|
|
535 |
case 'date' : $thisColumn = new DBColumnDate($columnName, $definitions );
|
|
|
536 |
break;
|
|
|
537 |
case 'datetime': $thisColumn = new DBColumnDateTime($columnName, $definitions );
|
|
|
538 |
break;
|
|
|
539 |
case 'int' : $thisColumn = new DBColumnInt($columnName, $definitions );
|
|
|
540 |
break;
|
|
|
541 |
case 'real' : $thisColumn = new DBColumnReal($columnName, $definitions );
|
|
|
542 |
break;
|
|
|
543 |
case 'password': $thisColumn = new DBColumnPassword($columnName, $definitions );
|
|
|
544 |
break;
|
|
|
545 |
case 'file' : $thisColumn = new DBColumnFile($columnName, $definitions );
|
|
|
546 |
break;
|
|
|
547 |
case 'lookup' : $thisColumn = new DBColumnLookup($columnName, $definitions );
|
|
|
548 |
break;
|
|
|
549 |
case 'multi' : $thisColumn = new DBColumnManyToMany($columnName, $definitions );
|
|
|
550 |
break;
|
|
|
551 |
default : $thisColumn = new DBColumn( $columnName, $definitions );
|
|
|
552 |
} // switch
|
38 |
rodolico |
553 |
$this->columns[$thisColumn->columnName] = $thisColumn;
|
36 |
rodolico |
554 |
} // foreach
|
|
|
555 |
} // function arrayToObject
|
38 |
rodolico |
556 |
|
|
|
557 |
// parameter keyfields must be an array, with indexes being the key field column names and the values being the values to look for
|
|
|
558 |
public function getOneRowQuery ( ) {
|
|
|
559 |
$select = array();
|
|
|
560 |
$keys = array();
|
|
|
561 |
foreach ( $this->columns as $field ) {
|
40 |
rodolico |
562 |
// print_r( $field );
|
38 |
rodolico |
563 |
$select[] = $field->columnName;
|
|
|
564 |
if ( $field->primaryKey ) {
|
40 |
rodolico |
565 |
$keys[] = "$field->columnName = ". $field->makeSafeSQLValue( );
|
38 |
rodolico |
566 |
} // if
|
|
|
567 |
} // foreach
|
|
|
568 |
return 'select ' . implode(',', $select ) . " from $this->tableName where " . implode( ' and ', $keys );
|
|
|
569 |
} // function getOneRowQuery
|
36 |
rodolico |
570 |
|
|
|
571 |
}
|
|
|
572 |
|
|
|
573 |
|
|
|
574 |
class DBDatabase {
|
38 |
rodolico |
575 |
public $databaseName;
|
|
|
576 |
public $tables;
|
|
|
577 |
public $displayOptions;
|
36 |
rodolico |
578 |
|
|
|
579 |
public function __construct( $databaseName, $tableDefinitionArray = '', $displayOptions = '' ) {
|
|
|
580 |
$this->databaseName = $databaseName;
|
|
|
581 |
$this->displayOptions = $displayOptions;
|
|
|
582 |
foreach ( $tableDefinitionArray as $tableName => $definition ) {
|
38 |
rodolico |
583 |
$this->tables[$tableName] = new DBTable($tableName, $definition['display name'], $definition['display columns'], $definition['display query'], $definition['field info'] );
|
36 |
rodolico |
584 |
}
|
|
|
585 |
} // function __construct
|
40 |
rodolico |
586 |
|
|
|
587 |
/*
|
|
|
588 |
function will create a quick and dirty set of edit/update screens, allowing untrained user to modify database files
|
|
|
589 |
will give list of tables as links. If link is clicked, will display tabular list of table contents.
|
|
|
590 |
table contents list will have edit/delete buttons, and an Add button at the top
|
|
|
591 |
If edit button is clicked, will show one row of information, allow user to modify it, then update the database
|
|
|
592 |
If add button is clicked, will show one row of information, with defaults filled in, then values will be inserted into database
|
|
|
593 |
*/
|
|
|
594 |
public function doAdmin() {
|
|
|
595 |
$html = "<ul class='db_database_admin_tablelist'>\n";
|
|
|
596 |
foreach ( $this->tables as $tableEntry ) {
|
|
|
597 |
$html .= "<li><a href='admin.php?command=showtable&tablename=$tableEntry->tableName'>$tableEntry->displayName</a></li>\n";
|
|
|
598 |
}
|
|
|
599 |
$html .= "</ul>";
|
|
|
600 |
return $html;
|
|
|
601 |
}
|
36 |
rodolico |
602 |
} // class DBDatabase
|
|
|
603 |
|
38 |
rodolico |
604 |
|
36 |
rodolico |
605 |
?>
|
|
|
606 |
|
|
|
607 |
|