EntityProto.class.php

Go to the documentation of this file.
00001 <?php
00002 /***************************************************************************
00003  *   Copyright (C) 2007 by Ivan Y. Khvostishkov                            *
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 
00012     class EntityProto extends Singleton
00013     {
00014         const PROTO_CLASS_PREFIX = 'EntityProto';
00015         
00016         public function baseProto()
00017         {
00018             return null;
00019         }
00020         
00021         public function className()
00022         {
00023             return null;
00024         }
00025         
00026         // TODO: think about anonymous primitives and persistant mapping
00027         // instead of creating new one on each call
00028         public function getFormMapping()
00029         {
00030             return array();
00031         }
00032         
00033         // TODO: use checkConstraints($object, $previousObject = null)
00034         // where object may be business object, form, scope, etc.
00035         // NOTE: object may contain errors already
00036         public function checkConstraints(
00037             $object, Form $form, $previousObject = null
00038         )
00039         {
00040             return $this;
00041         }
00042         
00043         public function isAbstract()
00044         {
00045             return false;
00046         }
00047         
00048         public function isInstanceOf(EntityProto $proto)
00049         {
00050             return ClassUtils::isInstanceOf(
00051                 $this->className(), $proto->className()
00052             );
00053         }
00054         
00055         final public function getFullFormMapping()
00056         {
00057             $result = $this->getFormMapping();
00058             
00059             if ($this->baseProto())
00060                 $result = $result + $this->baseProto()->getFullFormMapping();
00061             
00062             return $result;
00063         }
00064         
00065         final public function validate(
00066             $object, $form, $previousObject = null
00067         )
00068         {
00069             if (is_array($object)) {
00070                 return $this->validateList($object, $form, $previousObject);
00071             }
00072             
00073             Assert::isInstance($object, $this->className());
00074             Assert::isInstance($form, 'Form');
00075             
00076             if ($previousObject)
00077                 Assert::isInstance($previousObject, $this->className());
00078             
00079             if ($this->baseProto())
00080                 $this->baseProto()->
00081                     validate($object, $form, $previousObject);
00082             
00083             return $this->validateSelf($object, $form, $previousObject);
00084         }
00085         
00086         final public function validateSelf(
00087             $object, $form, $previousObject = null
00088         )
00089         {
00090             $this->checkConstraints($object, $form, $previousObject);
00091             
00092             $getter = new ObjectGetter($this, $object);
00093             
00094             $previousGetter = $previousObject
00095                 ? new ObjectGetter($this, $previousObject)
00096                 : null;
00097             
00098             foreach ($this->getFormMapping() as $id => $primitive) {
00099                 
00100                 if ($primitive instanceof PrimitiveForm) {
00101                     $proto = $primitive->getProto();
00102                     
00103                     $childForm = $form->getValue($primitive->getName());
00104                     
00105                     $child = $getter->get($id);
00106                     
00107                     $previousChild = $previousGetter
00108                         ? $previousGetter->get($id)
00109                         : null;
00110                     
00111                     $childResult = true;
00112                     
00113                     if (
00114                         $child
00115                         && !$proto->validate(
00116                             $child, $childForm, $previousChild
00117                         )
00118                     ) {
00119                         $form->markWrong($primitive->getName());
00120                     }
00121                 }
00122             }
00123             
00124             $errors = $form->getErrors();
00125             
00126             return empty($errors);
00127         }
00128         
00129         final public function validateList(
00130             $objectsList, $formsList, $previousObjectsList = null
00131         )
00132         {
00133             Assert::isEqual(count($objectsList), count($formsList));
00134             
00135             reset($formsList);
00136             
00137             if ($previousObjectsList) {
00138                 Assert::isEqual(
00139                     count($objectsList), count($previousObjectsList)
00140                 );
00141                 
00142                 reset($previousObjectsList);
00143             }
00144             
00145             $result = true;
00146             
00147             $previousObject = null;
00148             
00149             foreach ($objectsList as $object) {
00150                 
00151                 $form = current($formsList);
00152                 next($formsList);
00153                 
00154                 if ($previousObjectsList) {
00155                     $previousObject = current($previousObjectsList);
00156                     next($previousObjectsList);
00157                 }
00158                 
00159                 if (!$this->validate($object, $form, $previousObject))
00160                     $result = false;
00161             }
00162             
00163             return $result;
00164         }
00165         
00166         final public function createObject()
00167         {
00168             $className = $this->className();
00169             
00170             return new $className;
00171         }
00172         
00178         final public function makeForm()
00179         {
00180             return
00181                 $this->
00182                     attachPrimitives(
00183                         $this->baseProto()
00184                             ? $this->baseProto()->makeForm()
00185                             : Form::create()
00186                     );
00187         }
00188         
00192         final public function attachPrimitives(Form $form)
00193         {
00194             foreach ($this->getFormMapping() as $primitive)
00195                 $form->add($primitive);
00196             
00197             return $form;
00198         }
00199         
00200         final public function getOwnPrimitive($name)
00201         {
00202             $mapping = $this->getFormMapping();
00203             
00204             if (!isset($mapping[$name]))
00205                 throw new WrongArgumentException(
00206                     "i know nothing about property '$name'"
00207                 );
00208             
00209             return $mapping[$name];
00210         }
00211         
00212         final public function getPrimitive($name)
00213         {
00214             try {
00215                 $result = $this->getOwnPrimitive($name);
00216                 
00217             } catch (WrongArgumentException $e) {
00218                 
00219                 if (!$this->baseProto())
00220                     throw $e;
00221                 
00222                 $result = $this->baseProto()->getPrimitive($name);
00223             }
00224             
00225             return $result;
00226         }
00227     }
00228 ?>