00001 <?php
00050
00051 if (!function_exists("__autoload"))
00052 {
00053 function __autoload($class)
00054 {
00055 Form::autload($class);
00056 }
00057 }
00058
00068 class Form
00069 {
00070 private $fields = array();
00071 private $method = 'post';
00072 private $layout;
00073 private $name;
00074 private $action;
00075 private $onSubmit;
00076
00081 public function __construct($layout = null)
00082 {
00083 $this->action = $_SERVER['PHP_SELF'];
00084 $this->layout = $layout === null ? new TableLayout() : $layout;
00085 $this->name = uniqid('form');
00086
00087
00088 $this->add('HiddenField', 'is_submitted', array(
00089 'value' => 1
00090 ));
00091
00092 if(!($this->layout instanceof Layout))
00093 throw new Exception("Passed layout object does not implement Layout");
00094 }
00095
00100 public function __get($name)
00101 {
00102 if(isset($this->$name))
00103 return $this->$name;
00104 else
00105 return false;
00106 }
00107
00113 public function __set($name, $value)
00114 {
00115 switch($name)
00116 {
00117 case 'method':
00118 $value = strtolower($value);
00119 if($value != 'post' && $value != 'get')
00120 throw new InvalidValueException();
00121
00122 $this->method = $value;
00123 break;
00124
00125 case 'layout':
00126 if(!($value instanceof Layout))
00127 throw new InvalidValueException();
00128
00129 $this->layout = $value;
00130 break;
00131
00132 case 'action':
00133 case 'name':
00134 case 'onSubmit':
00135 case 'onsubmit':
00136 $this->$name = $value;
00137 return true;
00138 break;
00139
00140 default:
00141 return false;
00142 }
00143 }
00144
00152 public function add($type, $name, array $options = array())
00153 {
00154 if(array_key_exists($name, $this->fields))
00155 throw new Exception("Field name $name is not unique.");
00156
00157 $field = new $type($name, $this, $options);
00158 $this->fields[$name] = $field;
00159
00160 return $field;
00161 }
00162
00171 public function getField($name)
00172 {
00173
00174 $this->assertFieldExists($fieldName);
00175
00176 return $this->fields[$name];
00177 }
00178
00186 public function replaceField($type, $name, $options = array())
00187 {
00188
00189 $this->assertFieldExists($name);
00190
00191 $field = new $type($name, $this, $options);
00192 $this->fields[$name] = $field;
00193 }
00194
00201 public function addSubmit($title = 'Submit')
00202 {
00203 $this->add('ButtonField', 'submitme', array('value' => $title, 'type' => 'submit'));
00204
00205 return $field;
00206 }
00207
00213 public function remove($name)
00214 {
00215 if ($this->hasField($name))
00216 unset($this->fields[$name]);
00217 else
00218 throw new Exception("Cannot remove field $name, it doesn't exist.");
00219 }
00220
00221
00225 public function isSubmitted()
00226 {
00227 return isset($_POST['is_submitted']);
00228 }
00229
00233 public function validate()
00234 {
00235 foreach($this->fields as $field)
00236 $field->validate();
00237 }
00238
00239
00244 public function setData($data)
00245 {
00246 if(is_string($data))
00247 {
00248 $res =& $this->dbConn->query($data);
00249
00250 if(PEAR::isError($res))
00251 throw new InvalidQueryException($data);
00252
00253 $data = $res->fetchRow(DB_FETCHMODE_ASSOC);
00254 }
00255
00256 if(!is_array($data))
00257 throw new InvalidValueException();
00258
00259 foreach($this->fields as $field)
00260 {
00261
00262 if ($field instanceOf CollectionField)
00263 $field->setFieldsData($data);
00264
00265
00266 if(isset($data[$field->name]))
00267 $field->setData($data[$field->name]);
00268 }
00269 }
00270
00271
00277 public function getData($fieldName = null)
00278 {
00279 if($fieldName != null)
00280 {
00281 $this->assertFieldExists($fieldName);
00282 return $this->fields[$fieldName]->getData();
00283 }
00284
00285 $ret = array();
00286 foreach($this->fields as $field)
00287 {
00288 $ret[$field->name] = $field->getData();
00289 }
00290
00291 return $ret;
00292 }
00293
00299 public function hasError()
00300 {
00301 $error = false;
00302 foreach($this->fields as $field)
00303 $error = $field->hasError() || $error;
00304
00305 return $error;
00306 }
00307
00314 public function hasField($field)
00315 {
00316 return is_object($this->fields[$field]);
00317 }
00318
00323 public function needsDrawn()
00324 {
00325 return (!$this->isSubmitted() || $this->hasError());
00326 }
00327
00335 public function isSubmittedAndValid()
00336 {
00337
00338 if ($this->isSubmitted())
00339 {
00340
00341 $this->validate();
00342 return !$this->hasError();
00343 }
00344
00345
00346 return false;
00347 }
00348
00352 public function drawIfNeeded()
00353 {
00354 if ($this->needsDrawn())
00355 $this->draw();
00356 }
00357
00366 public function drawAll($action = null, $submitText = null)
00367 {
00368
00369 if(!count($this->fields))
00370 throw new Exception('Form has no fields.');
00371
00372
00373 $action = $action === null ? $this->action : $action;
00374
00375
00376
00377 if($submitText !== null)
00378 $this->addSubmit($submitText);
00379
00380 if ($this->onSubmit)
00381 $submit = "onSubmit=\"$this->onSubmit\"";
00382
00383
00384 echo "<form method='$this->method' action='$action' enctype='multipart/form-data' name='$this->name' id='$this->name' $submit>";
00385
00386
00387 $this->layout->drawBeginning();
00388
00389
00390 foreach($this->fields as $field)
00391 $this->layout->drawField($field);
00392
00393
00394 $this->layout->drawEnd();
00395
00396 echo "</form>";
00397 }
00398
00402 public function draw()
00403 {
00404 $this->drawAll();
00405 }
00406
00412 public function setError($fieldName, $errorString = null)
00413 {
00414 $this->assertFieldExists($fieldName);
00415 $field = $this->fields[$fieldName];
00416 $field->forceError();
00417
00418 if($errorString)
00419 $field->errorMessage = $errorString;
00420 }
00421
00426 public function getCss()
00427 {
00428 $css = null;
00429
00430 foreach($this->fields as $field)
00431 $css .= $field->getCss();
00432
00433 return $css;
00434 }
00435
00440 public function assertFieldExists($fieldName)
00441 {
00442 if(!array_key_exists($fieldName, $this->fields))
00443 throw new InvalidFieldNameException();
00444
00445 return true;
00446 }
00447
00452 public static function autoload($class)
00453 {
00454 if(preg_match('/.*Field$/', $class))
00455 {
00456 $class = str_replace('field', '-field', strtolower($class));
00457 require_once("fields/$class.inc.php");
00458 return true;
00459 }
00460 elseif(preg_match('/.*Layout$/', $class))
00461 {
00462 $class = str_replace('layout', '-layout', strtolower($class));
00463 require_once("layouts/$class.inc.php");
00464 return true;
00465 }
00466 elseif(preg_match('/.*Exception$/', $class))
00467 {
00468 $class = str_replace('exception', '-exception', strtolower($class));
00469 require_once("exceptions/$class.inc.php");
00470 return true;
00471 }
00472
00473 return false;
00474 }
00475 }
00476 ?>