Xataface  2.0alpha2
Xataface Application Framework
 All Data Structures Namespaces Files Functions Variables Groups Pages
SearchForm.php
Go to the documentation of this file.
1 <?php
2 /*-------------------------------------------------------------------------------
3  * Xataface Web Application Framework
4  * Copyright (C) 2005-2008 Web Lite Solutions Corp (shannah@sfu.ca)
5  *
6  * This program is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU General Public License
8  * as published by the Free Software Foundation; either version 2
9  * of the License, or (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software
18  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
19  *-------------------------------------------------------------------------------
20  */
21 /*******************************************************************************
22  * File: Dataface/SearchForm.php
23  * Author: Steve Hannah
24  * Description:
25  * An extension of HTML_QuickForm to auto-generate a form for a particular table
26  * in an SQL database.
27  *
28  *******************************************************************************/
29 
30 require_once 'HTML/QuickForm.php';
31 require_once 'Dataface/Table.php';
32 require_once 'Dataface/Vocabulary.php';
33 require_once 'Dataface/QueryBuilder.php';
34 require_once 'Dataface/ResultController.php';
35 require_once 'Dataface/ResultList.php';
36 require_once 'Dataface/QueryTool.php';
37 
38 
39 // Register our special types
40 $GLOBALS['HTML_QUICKFORM_ELEMENT_TYPES']['htmlarea'] = array('HTML/QuickForm/htmlarea.php', 'HTML_QuickForm_htmlarea');
41 
42 
46 class Dataface_SearchForm extends HTML_QuickForm {
47 
49 
50  var $db;
51 
52  var $_iniFile;
53 
54  var $_query;
55 
56  var $_exactMatches = false;
57 
58  var $_table;
59 
61 
62 
63 
68  var $_fields = array();
69 
70  var $_isBuilt = false;
71 
72  function Dataface_SearchForm($tablename, $db='', $query='', $fields=null){
73  $widgetTypes = array();
74  $this->tablename = $tablename;
75  $this->db = $db;
76  $this->_query = is_array($query) ? $query : array();
77 
78  if ( !isset( $this->_query['-cursor'] ) ){
79  $this->_query['-cursor'] = 0;
80  }
81 
82  $this->_resultSet =& Dataface_QueryTool::loadResult($tablename, $db, $this->_query);
83 
84 
85  parent::HTML_QuickForm($tablename, 'post');
86 
87  // Get column information directly from the database
88 
89 
90  $this->tablename = preg_replace('/ /', '', $this->tablename);
91  $this->_table =& Dataface_Table::loadTable($this->tablename, $this->db);
92 
93  $this->_fields = array();
94  if ( !isset($fields) ){
95  $fields = array_keys($this->_table->fields(false,true));
96 
97  foreach ($this->_table->relationships() as $relationship){
98  if ( @$relationship->_schema['visibility'] and @$relationship->_schema['visibility']['find'] == 'hidden' ){
99  continue;
100  }
101  $rfields = $relationship->fields(true);
102  $fkeys = $relationship->getForeignKeyValues();
103  $removedKeys = array();
104  foreach($fkeys as $fkeyTable => $fkey){
105  foreach (array_keys($fkey) as $fkeyKey){
106  $removedKeys[] = $fkeyTable.'.'.$fkeyKey;
107  }
108  }
109 
110  $rfields = array_diff($rfields, $removedKeys);
111 
112  foreach ($rfields as $rfield){
113  list($rtable,$rfield) = explode('.',$rfield);
114  $fields[] = $relationship->getName().'.'.$rfield;
115  }
116  unset($rfields);
117  unset($relationship);
118 
119  }
120  }
121 
122  $this->_fields = array();
123  foreach ($fields as $fieldname){
124  $this->_fields[$fieldname] =& $this->_table->getField($fieldname);
125  }
126 
127 
128 
129 
130 
131 
132 
133 
134 
135 
136  }
137 
138 
139 
140 
141 
142 
143 
144 
145  function _build(){
146  if ( $this->_isBuilt ){
147  return;
148  }
149  $this->_isBuilt = true;
150 
151  $renderer =& $this->defaultRenderer();
152  foreach ($_REQUEST as $qkey=>$qval){
153  if ( strlen($qkey)>1 and $qkey{0} == '-' and strpos($qkey, '-findq:') !== 0){
154  $this->addElement('hidden', $qkey);
155  $this->setDefaults( array($qkey=>$qval));
156  }
157  }
158 
159  $this->addElement('hidden', '--find-submit');
160  $this->setConstants( array('--find-submit'=>1));
161 
162  $relatedSections=array(); // keeps track of which relationship sections have been started
163 
164  foreach ( $this->_fields as $name => $field ){
166  if ( $this->_table->isPassword($name) ) continue;
167  if ( @$field['visibility']['find'] == 'hidden') continue;
168  // add the field to the form
169  $widget = $field['widget'];
170  if ( isset($widget['find']) ){
171  $widget = $widget['find'];
172  }
173  $vocabulary = $field['vocabulary'];
174 
175  if ( $widget['type'] == 'meta' ) continue;
176 
177  $inputName = $field['name'];
178 
179  if ( strpos($name,'.') !== false ){
180  unset($table);
181 
182  $table =& Dataface_Table::loadTable($field['tablename']);
183  list($relationshipName,$name) = explode('.', $name);
184  $inputName = $relationshipName.'/'.$name;
185 
186  if ( !isset($relatedSections[$relationshipName]) ){
187  $relationship = $this->_table->getRelationship($relationshipName);
188  if ( PEAR::isError($relationship) ){
189  die($relationship->toString());
190  }
191  $this->addElement('submit', '--submit', df_translate('scripts.GLOBAL.LABEL_SUBMIT', 'Submit'));
192  $this->addElement('header',$relationshipName,$relationship->getLabel());
193  $relatedSections[$relationshipName] = true;
194  }
195  }
196 
197  if ( isset( $vocabulary) && $vocabulary ){
198  //$vocab =& Dataface_Vocabulary::getVocabulary($vocabulary);
199  //$options = $vocab->options();
200  $options = $table->getValuelist($field['vocabulary']);
201  if ( is_array($options) ){
202  $opts = array(''=>df_translate('scripts.GLOBAL.FORMS.OPTION_PLEASE_SELECT', "Please Select..."));
203  foreach ($options as $key=>$value){
204  $opts[$key] = $value;
205  }
206  $options = $opts;
207  }
208  }
209 
210 
211  if ( isset($field['vocabulary']) and $field['vocabulary'] ){
212  $options = $table->getValuelist($field['vocabulary']);
213  $boxes = array();
214 
215  $el =& $this->addElement('select', '-findq:'.$inputName, $widget['label'], $options, array('size'=>'5','multiple'=>1));
216  $widgetTypes[$inputName] = 'select';
217  $el->setFieldDef($field);
218  if ( isset($field['repeat']) and $field['repeat']){
219 
220  $this->addElement('radio', '-find-op:'.$inputName, '',df_translate('scripts.Dataface_SearchForm.LABEL_MATCH_ALL', 'Match all selected'), 'AND');
221  }
222 
223  $this->addElement('radio', '-find-op:'.$inputName,'',df_translate('scripts.Dataface_SearchForm.LABEL_MATCH_ANY', 'Match any selected'), 'OR');
224 
225  $this->addElement('radio', '-find-op:'.$inputName,'',df_translate('scripts.Dataface_SearchForm.LABEL_MATCH_NONE', 'Do not match selected'), 'None');
226 
227 
228  } else {
229 
230  $el =& $this->addElement('text', '-findq:'.$inputName, $widget['label'], array('class'=>$widget['class'], 'id'=>$inputName) );
231  $widgetTypes[$inputName] = 'text';
232  $el->setFieldDef($field);
233  }
234 
235  }
236 
237 
238  $this->addElement('submit','--submit',df_translate('scripts.GLOBAL.LABEL_FIND', 'Find'));
239  $this->addElement('hidden', '-action');
240  $this->addElement('hidden', '-edit');
241  $this->addElement('hidden', '-table');
242 
243  $defaults = array();
244  foreach ($this->_query as $key=>$value){
245  if ( $key{0} != '-' ){
246  if ( @$widgetTypes[$key] == 'select'){
247  $parts = explode(' OR ', $value);
248  $value = array();
249  foreach ($parts as $part ){
250  while ( $part and in_array($part{0}, array('=','<','>','!') ) ) {
251  $part = substr($part,1);
252  //$value = array($value);
253  }
254  $value[] = $part;
255  }
256  }
257 
258  $defaults['-findq:'.$key] = $value;
259  } else {
260  $defaults[$key] = $value;
261  }
262  }
263 
264  $this->setDefaults( $defaults);
265  $this->setConstants(array('-action'=>'find', '-edit'=>1, '-table'=>$this->tablename));
266 
267 
268 
269  }
270 
271  function display(){
272  $this->_build();
273 
274 
275  $tableLabel = htmlspecialchars($this->_table->getLabel());
276 
277  df_display(array(
278  'tableLabel' => $tableLabel
279  ), 'Dataface_Search_Instructions.html'
280  );
281 
282  //parent::display();
283  import('Dataface/FormTool.php');
285  $ft->display($this, 'Dataface_FindForm.html');
286  //echo '</div>';
287  }
288 
289 
293  function performFind($values){
295  $query = $app->getQuery();
296 
297  if ( isset( $values['-find:result_action']) ){
298  $qstr = '-action='.$values['-find:result_action'];
299  } else {
300  $qstr = '-action=list';
301  }
302  if ( isset($values['-skip']) ) $values['-skip'] = 0;
303  if ( isset($values['-cursor']) ) $values['-cursor'] = 0;
304  // Checkbox groups with nothing selected may not be submitted with the form,
305  // even though their accompanying 'None' radio button may be selected. If none
306  // is selected, then we need to add a value
307  foreach ($values as $key=>$value){
308  if ( strpos($key, '-find-op:') === 0 ){
309  $key = substr($key, 9);
310  if ( !isset($values['-findq:'.$key]) or !is_array($values['-findq:'.$key]) ){
311  $values['-findq:'.$key] = array('');
312  }
313  }
314  }
315  foreach ($values as $key=>$value){
316  if ( strpos($key, '-findq:') === 0 ){
317  $key = substr($key, 7);
318  $field = $this->_table->getField(str_replace('/','.',$key));
319  if ( PEAR::isError($field) ){
320  echo "Failed to get field $key: ".$field->getMessage();
321  }
322  if ( is_array($value) and count($value) > 0){
323  $op = ( (isset( $values['-find-op:'.$key] ) ) ? $values['-find-op:'.$key] : 'AND');
324  if (!isset($field['repeat']) or !$field['repeat']) $op = 'OR';
325  if ( isset($values['-find-op:'.$key]) and $values['-find-op:'.$key] == 'None' ){
326  $qstr .= '&'.urlencode($key).'='.urlencode('=');
327  } else {
328  $qstr .= '&'.urlencode($key).'='.urlencode('='.implode( ' '.$op.' =', $value));
329  }
330  } else if ( !empty($value) ){
331 
332  $qstr .= '&'.urlencode($key).'='.urlencode($value);
333  }
334  unset($field);
335  } else if ( $key{0} == '-' and $key{1} != '-' and $key != '-action' and $key != '-search' and strpos($key, '-find') !== 0 ){
336  $qstr .= '&'.urlencode($key).'='.urlencode($value);
337  }
338 
339  }
340 
341  $url = $_SERVER['HOST_URI'].DATAFACE_SITE_HREF.'?'.$qstr;
342  $app->redirect($url);
343  }
344 
345  function process($callback=null, $mergFiles=true){
346  if ( isset( $this->_query['--find-submit']) ){
347  return parent::process( array(&$this, 'performFind'));
348  } else {
349  return null;
350  }
351  }
352 
353  function getKeys(){
354  $keys = array();
355  foreach ($this->_fields as $key=>$value){
356  if ( strtolower($value['Key']) == strtolower('PRI') ){
357  $keys[$key] =& $this->_fields[$key];
358  }
359  }
360  return $keys;
361  }
362 
363  function deserialize($field){
364  return Dataface_Table::_deserialize($field);
365 
366 
367  }
368 
369  function serialize($field){
370 
371  return Dataface_Table::_serialize($field);
372 
373 
374 
375  }
376 }