Form.class.php

Go to the documentation of this file.
00001 <?php
00002 /****************************************************************************
00003  *   Copyright (C) 2004-2009 by Konstantin V. Arkhipov, Anton E. Lebedevich *
00004  *                                                                          *
00005  *   This program is free software; you can redistribute it and/or modify   *
00006  *   it under the terms of the GNU Lesser General Public License as         *
00007  *   published by the Free Software Foundation; either version 3 of the     *
00008  *   License, or (at your option) any later version.                        *
00009  *                                                                          *
00010  ****************************************************************************/
00011 
00020     final class Form extends RegulatedForm
00021     {
00022         const WRONG         = 0x0001;
00023         const MISSING       = 0x0002;
00024         
00025         private $errors             = array();
00026         private $labels             = array();
00027         private $describedLabels    = array();
00028         
00029         private $proto              = null;
00030         
00031         private $importFiltering    = true;
00032         
00036         public static function create()
00037         {
00038             return new self;
00039         }
00040         
00041         public function getErrors()
00042         {
00043             return array_merge($this->errors, $this->violated);
00044         }
00045         
00046         public function getInnerErrors()
00047         {
00048             $result = $this->getErrors();
00049             
00050             foreach ($this->primitives as $name => $prm) {
00051                 if (
00052                     (
00053                         ($prm instanceof PrimitiveFormsList)
00054                         || ($prm instanceof PrimitiveForm)
00055                     )
00056                     && $prm->getValue()
00057                 ) {
00058                     if ($errors = $prm->getInnerErrors()) {
00059                         $result[$name] = $errors;
00060                     } else {
00061                         unset($result[$name]);
00062                     }
00063                 }
00064             }
00065             
00066             return $result;
00067         }
00068         
00072         public function dropAllErrors()
00073         {
00074             $this->errors   = array();
00075             $this->violated = array();
00076             
00077             return $this;
00078         }
00079         
00083         public function enableImportFiltering()
00084         {
00085             $this->importFiltering = true;
00086             
00087             return $this;
00088         }
00089         
00093         public function disableImportFiltering()
00094         {
00095             $this->importFiltering = false;
00096             
00097             return $this;
00098         }
00099         
00107         public function markMissing($primitiveName)
00108         {
00109             return $this->markCustom($primitiveName, Form::MISSING);
00110         }
00111         
00117         public function markWrong($name)
00118         {
00119             if (isset($this->primitives[$name]))
00120                 $this->errors[$name] = self::WRONG;
00121             elseif (isset($this->rules[$name]))
00122                 $this->violated[$name] = self::WRONG;
00123             else
00124                 throw new MissingElementException(
00125                     $name.' does not match known primitives or rules'
00126                 );
00127             
00128             return $this;
00129         }
00130         
00134         public function markGood($primitiveName)
00135         {
00136             if (isset($this->primitives[$primitiveName]))
00137                 unset($this->errors[$primitiveName]);
00138             elseif (isset($this->rules[$primitiveName]))
00139                 unset($this->violated[$primitiveName]);
00140             else
00141                 throw new MissingElementException(
00142                     $primitiveName.' does not match known primitives or rules'
00143                 );
00144             
00145             return $this;
00146         }
00147         
00153         public function markCustom($primitiveName, $customMark)
00154         {
00155             Assert::isInteger($customMark);
00156             
00157             $this->errors[$this->get($primitiveName)->getName()] = $customMark;
00158             
00159             return $this;
00160         }
00162         
00166         public function getTextualErrors()
00167         {
00168             $list = array();
00169             
00170             foreach (array_keys($this->labels) as $name) {
00171                 if ($label = $this->getTextualErrorFor($name))
00172                     $list[] = $label;
00173             }
00174             
00175             return $list;
00176         }
00177         
00178         public function getTextualErrorFor($name)
00179         {
00180             if (
00181                 isset(
00182                     $this->violated[$name],
00183                     $this->labels[$name][$this->violated[$name]]
00184                 )
00185             )
00186                 return $this->labels[$name][$this->violated[$name]];
00187             elseif (
00188                 isset(
00189                     $this->errors[$name],
00190                     $this->labels[$name][$this->errors[$name]]
00191                 )
00192             )
00193                 return $this->labels[$name][$this->errors[$name]];
00194             else
00195                 return null;
00196         }
00197         
00198         public function getErrorDescriptionFor($name)
00199         {
00200             if (
00201                 isset(
00202                     $this->violated[$name],
00203                     $this->describedLabels[$name][$this->violated[$name]]
00204                 )
00205             )
00206                 return $this->describedLabels[$name][$this->violated[$name]];
00207             elseif (
00208                 isset(
00209                     $this->errors[$name],
00210                     $this->describedLabels[$name][$this->errors[$name]]
00211                 )
00212             )
00213                 return $this->describedLabels[$name][$this->errors[$name]];
00214             else
00215                 return null;
00216         }
00217         
00221         public function addErrorDescription($name, $errorType, $description)
00222         {
00223             
00224             if (
00225                 !isset($this->rules[$name])
00226                 && !$this->get($name)->getName()
00227             )
00228                 throw new MissingElementException(
00229                     "knows nothing about '{$name}'"
00230                 );
00231             
00232             $this->describedLabels[$name][$errorType] = $description;
00233             
00234             return $this;
00235         }
00236         
00240         public function addWrongLabel($primitiveName, $label)
00241         {
00242             return $this->addErrorLabel($primitiveName, Form::WRONG, $label);
00243         }
00244         
00248         public function addMissingLabel($primitiveName, $label)
00249         {
00250             return $this->addErrorLabel($primitiveName, Form::MISSING, $label);
00251         }
00252         
00256         public function addCustomLabel($primitiveName, $customMark, $label)
00257         {
00258             return $this->addErrorLabel($primitiveName, $customMark, $label);
00259         }
00260         
00261         public function getWrongLabel($primitiveName)
00262         {
00263             return $this->getErrorLabel($primitiveName, Form::WRONG);
00264         }
00265         
00266         public function getMissingLabel($primitiveName)
00267         {
00268             return $this->getErrorLabel($primitiveName, Form::MISSING);
00269         }
00270         
00274         public function import($scope)
00275         {
00276             foreach ($this->primitives as $prm)
00277                 $this->importPrimitive($scope, $prm);
00278             
00279             return $this;
00280         }
00281         
00285         public function importMore($scope)
00286         {
00287             foreach ($this->primitives as $prm) {
00288                 if (!$prm->isImported())
00289                     $this->importPrimitive($scope, $prm);
00290             }
00291             
00292             return $this;
00293         }
00294         
00298         public function importOne($primitiveName, $scope)
00299         {
00300             return $this->importPrimitive($scope, $this->get($primitiveName));
00301         }
00302         
00306         public function importValue($primitiveName, $value)
00307         {
00308             $prm = $this->get($primitiveName);
00309             
00310             return $this->checkImportResult($prm, $prm->importValue($value));
00311         }
00312         
00316         public function importOneMore($primitiveName, $scope)
00317         {
00318             $prm = $this->get($primitiveName);
00319             
00320             if (!$prm->isImported())
00321                 return $this->importPrimitive($scope, $prm);
00322             
00323             return $this;
00324         }
00325         
00326         public function exportValue($primitiveName)
00327         {
00328             return $this->get($primitiveName)->exportValue();
00329         }
00330         
00331         public function export()
00332         {
00333             $result = array();
00334             
00335             foreach ($this->primitives as $name => $prm) {
00336                 if ($prm->isImported())
00337                     $result[$name] = $prm->exportValue();
00338             }
00339             
00340             return $result;
00341         }
00342         
00343         public function toFormValue($value)
00344         {
00345             if ($value instanceof FormField)
00346                 return $this->getValue($value->getName());
00347             elseif ($value instanceof LogicalObject)
00348                 return $value->toBoolean($this);
00349             else
00350                 return $value;
00351         }
00352         
00356         public function setProto(EntityProto $proto)
00357         {
00358             $this->proto = $proto;
00359             
00360             return $this;
00361         }
00362         
00366         public function getProto()
00367         {
00368             return $this->proto;
00369         }
00370         
00374         private function importPrimitive($scope, BasePrimitive $prm)
00375         {
00376             if (!$this->importFiltering) {
00377                 if ($prm instanceof FiltrablePrimitive) {
00378                     
00379                     $chain = $prm->getImportFilter();
00380                     
00381                     $prm->dropImportFilters();
00382                     
00383                     $result = $this->checkImportResult(
00384                         $prm,
00385                         $prm->import($scope)
00386                     );
00387                     
00388                     $prm->setImportFilter($chain);
00389                     
00390                     return $result;
00391                     
00392                 } elseif ($prm instanceof PrimitiveForm) {
00393                     return $this->checkImportResult(
00394                         $prm,
00395                         $prm->unfilteredImport($scope)
00396                     );
00397                 }
00398             }
00399             
00400             return $this->checkImportResult($prm, $prm->import($scope));
00401         }
00402         
00406         private function checkImportResult(BasePrimitive $prm, $result)
00407         {
00408             if (
00409                 $prm instanceof PrimitiveAlias
00410                 && $result !== null
00411             )
00412                 $this->markGood($prm->getInner()->getName());
00413             
00414             $name = $prm->getName();
00415             
00416             if (null === $result) {
00417                 if ($prm->isRequired())
00418                     $this->errors[$name] = self::MISSING;
00419                 
00420             } elseif (true === $result) {
00421                 unset($this->errors[$name]);
00422                 
00423             } elseif ($error = $prm->getCustomError()) {
00424                 
00425                 $this->errors[$name] = $error;
00426                 
00427             } else
00428                 $this->errors[$name] = self::WRONG;
00429             
00430             return $this;
00431         }
00432         
00443         private function addErrorLabel($name, $errorType, $label)
00444         {
00445             if (
00446                 !isset($this->rules[$name])
00447                 && !$this->get($name)->getName()
00448             )
00449                 throw new MissingElementException(
00450                     "knows nothing about '{$name}'"
00451                 );
00452             
00453             $this->labels[$name][$errorType] = $label;
00454             
00455             return $this;
00456         }
00457         
00458         private function getErrorLabel($name, $errorType)
00459         {
00460             // checks for primitive's existence
00461             $this->get($name);
00462             
00463             if (isset($this->labels[$name][$errorType]))
00464                 return $this->labels[$name][$errorType];
00465             
00466             return null;
00467         }
00468     }
00469 ?>