Subversion Repositories phpLibraryV2

Rev

Rev 45 | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
1 rodolico 1
<?php
2
 
3
   /* 
4
      This class simply extends DBQuery to allow output to be converted to HTML
5
   */
6
 
34 rodolico 7
   require_once( 'DBQuery.class.php' );
1 rodolico 8
 
9
   class DBQueryHTML extends DBQuery {
47 rodolico 10
 
11
      protected $htmlQuoteChar = '"';
1 rodolico 12
 
13
      /*
14
         Function takes an SQL statement and converts it to an HTML table.
15
         Return Value: HTML table representation of the query
16
         Parameters:
17
            $sql    A valid SQL query to run
18
            $format An optional array of format strings (suitable for printf) for each column (empty strings ignored)
19
            $makeTableDef  If True, the resulting HTML has the <table></table> tags; otherwise starts with header
20
            $append   Arbitrary string that is appended as a single column to each row
21
 
22
            NOTE ON $append
23
               $append may optionally contain variables of the form %colname%, which will be replaced
24
               with values from the current row. $colname is taken from the META data from the query, thus
25
               the query select foo from bar would have a meta of header of foo for column 0.
26
               $append is searched for strings of form %foo% in that case, and the current value of column
27
               foo replaces the tag %foo%.
28
               %foo% is ignored if foo is not a valid column name in a query.
29
               thus, a query such as select zip,city,state from zip_codes and a string of Hello %city% I'm glad
30
               you are in %State% will not replace the second as State is not a column of this query (it is case
31
               sensitive). Also, beware of items like select zip,concat(state,', ', city) from zip_codes. It is
32
               much better to rewrite that as select zip,concat(state,', ', city) mytown from zip_codes.
33
 
34
               If you don't know what all that means, get a book on SQL
35
      */
47 rodolico 36
      function queryToTable ( $format = array(), $makeTableDef = true, $append='', $headers = '' ) {
37
         // print "\n\n<pre>$this->query</pre>\n\n";
38
         $tdTextDefinition = '<td valign=' . $this->htmlQuoteChar . 'top' . $this->htmlQuoteChar . '>';
39
         $tdNumberDefinition = '<td valign=' . $this->htmlQuoteChar .'top' . $this->htmlQuoteChar . 'align=' . $this->htmlQuoteChar . 'right' . $this->htmlQuoteChar . '>';
1 rodolico 40
         $html = '';
41
         $rows = array();
47 rodolico 42
         $save = $this->returnType;
43
         $this->returnType = MYSQLI_ASSOC; // temporarily turn off associative arrays
44
         $columnNames = array();
1 rodolico 45
         $this->run();
46
         if ( $this->rowsAffected ) { // we returned at least one row
47 rodolico 47
 
48
            //print "<pre>Found " . $this->rowsAffected . "\n</pre>";
49
            // get the column names; we'll use them later
1 rodolico 50
            foreach ( $this->columnMetaData as $field ) {
47 rodolico 51
               $columnNames[] = $field['name'];
1 rodolico 52
            }
47 rodolico 53
 
54
            // Build the searchFor array for $append
55
            $searchFor = $columnNames;
56
            array_walk( $searchFor, function ( &$value, $key ) { $value = '%' . $value . '%'; } );
57
            // print '<pre>SearchFor ' . print_r( $searchFor, true ) . '</pre>'; die;
58
            //print "<pre>" . print_r($this->columnMetaData,true) . '</pre>'; die;
1 rodolico 59
            /* special condition where only one row is returned. In that case, $this->returnData is not an array
60
            of associations, but a simple association. In this case, we need to convert it
61
            */
62
            if (count($this->returnData[0]) == 1) { // convert from association to single row array of associations
63
               $temp = array();
64
               foreach ($this->returnData as $column => $value) {
65
                  $temp[0][$column] = $value;
66
               } // foreach
67
               $this->returnData = $temp;
68
            }
69
            if (count($format) > 0 ) { // we have some formats, so let's do it the hard, slow way
70
               for ( $row = 0; $row < count($this->returnData); $row++) {
71
                  $rows[$row] = '';
72
                  for ( $column = 0; $column < count($this->returnData[$row]); $column++  ) {
73
                     $rows[$row] .= strlen($format[$column]) && isset($this->returnData[$row][$column])> 0 ?
74
                                    ( $tdNumberDefinition . sprintf($format[$column],$this->returnData[$row][$column]) . '</td>')
75
                                    : ($tdTextDefinition . $this->returnData[$row][$column] . '</td>');
76
                  } // for $column
77
                  /*
78
                     let's append some stuff to the row if it exists.
79
                     We will take the array of SearchFor containing the column names
80
                     and the array of values from this row, then look for matches and replace them
81
                     with the correct values. Note, the column names in $append should have percent
82
                     signs appended and prepended, thus a column name of joe would be %joe% in %append
83
                  */
84
                  if (strlen($append) > 0) { // let's append some stuff to the row
85
                     $rows[$row] .= $tdTextDefinition . str_replace ( $searchFor, $this->returnData[$row], $append ) . '</td>';
86
                  }
87
               } // for $row
88
            } else { // no formatting, so we just slam the stuff together
89
               for ( $row = 0; $row < count($this->returnData); $row++) {
47 rodolico 90
                  $temp = array();
91
                  foreach ( $columnNames as $col ) {
92
                     $temp[] = $this->returnData[$row][$col];
93
                  }
94
                  $currentValue = $tdTextDefinition . implode( '</td>' . $tdTextDefinition, $temp) . '</td>';
1 rodolico 95
                  if (strlen($append) > 0) { // see explaination in if part of this structure
96
                     $currentValue  .= $tdTextDefinition . str_replace ( $searchFor, $this->returnData[$row], $append ) . '</td>';
97
                  }
98
                  $rows[] = $currentValue;
99
               }
100
            }
101
            // ok, let's get the field headers from the table
102
            $html .= '<tr>';
103
            if ( $headers ) { // user has passed in some header fields for us to use
104
               $html .= '<th>' . implode( '</th><th>',  $headers ) . '</th>';
105
            } else { // no headers, so we just get them from the returned column names
106
               foreach ( $this->columnMetaData as $field ) {
47 rodolico 107
                  $html .= '<th>' . ((array)$field)['name'] . '</th>';
1 rodolico 108
               }
109
            } // if headers .. else
110
            $html .= '</tr>';
111
            // we now have all the info, so let's make it into a table
112
            $html .= '<tr>' . implode('</tr><tr>', $rows ) . '</tr>';
113
         } else {
114
            $html = '<tr><td>No rows returned by the query</td></tr>';
115
         }
116
         if ( $makeTableDef ) { // they want the <table> def, so let's give it to them
47 rodolico 117
            $html = '<table border=' . $this->htmlQuoteChar . '1' . $this->htmlQuoteChar . '>' . $html . '</table>';
1 rodolico 118
         } // if ( $makeTableDef
119
 
47 rodolico 120
         $this->returnType = $save;
1 rodolico 121
         //return '<pre>' . print_r ($this,true) .  '</pre>';
122
         return $html;
123
      }
124
 
125
      /*
126
         function executes a query, then returns an array containing only the values of the first
127
         field in the return as the keys to an associative array. NOTE: any duplicates will be
128
         discarded. This is useful when you simply want to know if a value exists, ie if you
129
         are building an html select from a query, and a separate query needs to hold the
130
         values that are currently selected
131
      */
132
 
133
      function valuesToKeys () {
134
         $returnValue = array();
135
         $save = $this->useAssociativeArray;
136
         $useAssociativeArray = false; // temporarily turn off associative arrays
137
         $this->run();
138
         if ( $this->rowsAffected ) { // we returned at least one row
139
            foreach ( $info as $key => $value ) { // only thing I know to do is iterate
140
               $returnValue[$this->returnData[0]] = true;
141
            }
142
         } // if
143
         $useAssociativeArray = $save;
144
         return $returnValue;
145
      }
146
 
147
      /* this function will take the result of an SQL query that returns at least two columns.
148
         The first column becomes the keys in an associative array, and the second column
149
         becomes the value.
150
 
151
         Note, because it is an associative array, duplicates of the first column will only contain
152
         the last value.
153
      */
154
 
47 rodolico 155
      function ColumnColumnArray ( $query = null ) {
156
         if ( isset( $query) ) {
157
            $this->parameters['query'] = $query;
158
         }
1 rodolico 159
         $returnValue = array();
160
         $save = $this->useAssociativeArray;
161
         $useAssociativeArray = false; // temporarily turn off associative arrays
162
         $this->run();
163
         if ( $this->rowsAffected ) { // we returned at least one row
47 rodolico 164
            //print '<pre>' . print_r($this->parameters, true) . '</pre>'; die;
165
            foreach ( $this->returnData as $key => $value ) { // only thing I know to do is iterate
166
               $returnValue[$value[0]] = $value[1];
1 rodolico 167
            }
168
         } // if
169
         $useAssociativeArray = $save;
170
         return $returnValue;
171
      }
172
 
37 rodolico 173
 
174
      /**
175
       * Builds an HTML select out of a query, or data
176
       * 
177
       * $parameters may contain the following keys
178
       * 
179
       * Must have one of the following. If both are present, 'query' is
180
       * ignored
181
       * 'query' - An SQL query to run. Should return 2 columns; first is value, second id display
182
       * 'data' - An array of key/value pair. Key is used for value, value is display
183
       * 
184
       * 'name' - HTML name for the select. If this is not set, only the options will be returned
185
       * 'class' - used for class='whatever' in select
186
       * 'selected' - key in 'data' or result of 'query' which will be selected
187
       * 'label' - used as <label>. If this is not set, no <label> is generated
188
       * 'nullok' - adds a entry at top with value of -1 and display of three dashes (---)
189
       * 
190
       * 
191
       * @parameters string $parameters an array of data to decide what/how to process
192
       * @returns string an HTML select entity
193
       */
194
      function htmlSelect ( $parameters ) {
1 rodolico 195
 
37 rodolico 196
         //print "<pre>" . print_r( $parameters, true ) . "</pre>"; die;
197
 
198
         if ( empty( $parameters['data'] ) ) {
45 rodolico 199
            // print "<pre>No data, running query\n" . $parameters['query'] . "</pre>"; die;
200
            if ( empty( $parameters['query'] ) )
37 rodolico 201
               return '';
202
            $save = $this->useAssociativeArray;
203
            $useAssociativeArray = false; // temporarily turn off associative arrays
45 rodolico 204
            //print "<pre>Running Query\n</pre>";
205
            $data = $this->doSQL( $parameters['query'] );
206
            //print "<pre>" . print_r( $data, true ) . "</pre>"; die;
207
            if ( $data['rowsAffected'] ) { // we returned at least one row
208
               $data = $data['returnData'];
209
               foreach ($data as $rowNumber => $value ) {
37 rodolico 210
                  $parameters['data'][$value[0]] = $value[1];
1 rodolico 211
               }
212
            }
213
         }
45 rodolico 214
         //return "<pre>Data is \n" . print_r( $parameters['data'], true ) . "</pre>";
37 rodolico 215
         $selectedKey = isset( $parameters['selected'] ) ? $parameters['selected'] : '';
216
         $options = array();
217
         if ( isset( $parameters['nullok'] ) ) {
218
            $options[] = '<option value="-1">---</option>';
219
         }
220
         foreach ( $parameters['data'] as $key => $value ) {
221
            $options[] = sprintf( 
222
               '<option value="%s"%s>%s</option>',
223
               $key,
224
               $key == $selectedKey ? ' selected' : '',
225
               $value
226
               );
227
         } // foreach
228
         $return = implode( "\n", $options );
229
         if ( isset( $parameters['name'] ) ) {
230
            $return = "<select name='$parameters[name]'>\n$return\n</select>";
231
            if ( isset( $parameters['label'] ) ) {
232
               $return = "<label>$parameters[label]\n$return\n</label>\n";
1 rodolico 233
            }
234
         }
37 rodolico 235
         return $return;
1 rodolico 236
      }
237
 
37 rodolico 238
      /**
239
       * Create an HTML checkbox block from a query, or array of data passed in
240
       * 
241
       * if $parameters['data'] is set, no further query is used. $parameters['data']
242
       * should contain an array of data. Each row in that array should be another 
243
       * array with keys 
244
       *    'id' -- 'id' and 'name' of the checkbox
245
       *    'name' -- display name of the checkbox
246
       *    'checked' -- boolean (or 0/1) saying whether this has a check
247
       * 
248
       * of $parameters['data'] is not set and $parameters['query'] is set
249
       * the query will be run. It MUST contain the column names listed above.
250
       * 
39 rodolico 251
       * If $parameters['template'] is set, that template will be used. If it
252
       * is not set, a template will be defaulted to.
253
       * 
254
       * If $paramters['arrayName'] is set, the form of the template will be
255
       * name='arrayname[name]'
256
       * 
37 rodolico 257
       * Processing will then continue
1 rodolico 258
      */
259
 
37 rodolico 260
      function htmlCheckBoxes ( $parameters ) {
261
         if ( empty( $parameters['template'] ) ) { // they did not send us a template
39 rodolico 262
            if ( empty( $parameters['arrayName'] ) ) {
41 rodolico 263
               $parameters['template'] = "<li><input type='checkbox' id='~~id~~' name='~~id~~' ~~checked~~>\n<label for='~~id~~'>~~name~~</label></li>\n";
39 rodolico 264
            } else {
41 rodolico 265
               $parameters['template'] = "<li><input type='checkbox' id='$parameters[arrayName]~~id~~' name='$parameters[arrayName][~~id~~]' ~~checked~~>\n<label for='~~id~~'>~~name~~</label></li>\n";
39 rodolico 266
            }
1 rodolico 267
         }
37 rodolico 268
         //print "<pre>" . print_r($parameters, true) . "</pre>"; die;
269
         if ( empty( $parameters['data'] ) ) {
270
            if ( empty( $parameters['query'] ) )
271
               return '';
272
            $save = $this->useAssociativeArray;
273
            $useAssociativeArray = false; // temporarily turn off associative arrays
274
            $this->doSQL( $parameters['query'] );
275
            if ( $this->rowsAffected ) { // we returned at least one row
276
               foreach ($this->returnData as $rowNumber => $value ) {
277
                  $parameters['data'][] = $value;
278
               }
279
            }
1 rodolico 280
         }
37 rodolico 281
         //print "<pre>" . print_r($parameters, true) . "</pre>"; die;
282
         foreach ( $parameters['data'] as $key => $value ) {
283
            $replacement = array(
284
               'id' => $value['id'], 
285
               'name' => $value['name'], 
286
               'checked' => $value['checked'] ? 'checked' : ''
287
               );
288
            $html[] = $this->templateReplace($parameters['template'],$replacement);
289
         }
41 rodolico 290
         return '<ul>' . implode( '', $html ) . '</ul>';
1 rodolico 291
      }
292
 
37 rodolico 293
      /**
294
       * Replaces instances of replacement strings in string
295
       * 
296
       * Designed to allow the caller to build a string with things to be
297
       * replaced, for example
298
       * <input type='text' name='~~name~~'>
299
       * All instances of ~~name~~ will be replaced 
300
       */
301
      public function templateReplace ( $template, $replacmentStrings, $delimiter = '~~' ) {
43 rodolico 302
         //print "<pre>Replacement Strings\n" . print_r($replacmentStrings, true) . "</pre>";
303
         //print "<pre>Template\n" . print_r($template, true) . "</pre>"; die;
37 rodolico 304
         foreach ( $replacmentStrings as $key => $replace ) {
43 rodolico 305
            if ( is_array( $replace ) )
306
               continue;
37 rodolico 307
            $search = '/' . $delimiter . $key . $delimiter . '/';
308
            //print "<pre>" . print_r($search, true) . "</pre>"; die;
309
            $template = preg_replace( $search, $replace, $template );
310
         }
311
         return $template;
312
      }
313
 
1 rodolico 314
   /*   
315
      function CSV ( $sql ) {
316
         $rows = array();
317
         $CSV = '';
318
         $info = array();
319
         if ( $result = queryDatabaseExtended($sql,0) ) {
320
            $meta = $result['meta'];
321
            //objectDebugScreen($result);
322
            $info = $result['data'];
323
            unset ($result);
324
            $headers = array();
325
            foreach ( $meta as $field ) {
326
               $headers[] = $field['name'];
327
            } // foreach
328
            $rows[] = implode("\t", $headers);
329
            // special condition where only one row is returned. In that case, $info is not an array
330
            //  of associations, but a simple association. In this case, we need to convert it
331
 
332
            if (count($info[0]) == 1) { // convert from association to single row array of associations
333
               $temp = array();
334
               foreach ($info as $column => $value) {
335
                  $temp[0][$column] = $value;
336
               } // foreach
337
               $info = $temp;
338
            }
339
            for ( $row = 0; $row < count($info); $row++) {
340
               $rows[] = implode("\t", $info[$row]);
341
            }
342
            // we now have all the info, so let's make it into a table
343
            $CSV .= implode("\n", $rows );
344
         } // if ( $info = queryDatabase($sql,0) )
345
         // print '<pre>';  print_r ($info); print '</pre>';
346
         return $CSV;
347
      }
348
 
349
   */
350
 
351
   } // class DBQueryHTML
352
 
353
?>