Go to the documentation of this file.00001 <?php
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012 abstract class PrototypedBuilder
00013 {
00014 protected $proto = null;
00015
00016 private $limitedPropertiesList = null;
00017
00018 abstract protected function createEmpty();
00019
00023 abstract protected function getGetter($object);
00024
00028 abstract protected function getSetter(&$object);
00029
00030 public function __construct(EntityProto $proto)
00031 {
00032 $this->proto = $proto;
00033 }
00034
00035 public function setLimitedPropertiesList($list)
00036 {
00037 if ($list !== null)
00038 Assert::isArray($list);
00039
00040 $mapping = $this->proto->getFullFormMapping();
00041
00042 foreach ($list as $key => $inner)
00043 Assert::isIndexExists($mapping, $key);
00044
00045 $this->limitedPropertiesList = $list;
00046
00047 return $this;
00048 }
00049
00053 public function cloneBuilder(EntityProto $proto)
00054 {
00055 Assert::isTrue(
00056 $this->proto->isInstanceOf($proto)
00057 || $proto->isInstanceOf($this->proto),
00058
00059 Assert::dumpArgument($proto)
00060 );
00061
00062 $result = new $this($proto);
00063
00064 $result->limitedPropertiesList = $this->limitedPropertiesList;
00065
00066 return $result;
00067 }
00068
00069 public function cloneInnerBuilder($property)
00070 {
00071 $mapping = $this->getFormMapping();
00072
00073 Assert::isIndexExists($mapping, $property);
00074
00075 $primitive = $mapping[$property];
00076
00077 Assert::isInstance($primitive, 'PrimitiveForm');
00078
00079 $result = new $this($primitive->getProto());
00080
00081 if (isset($this->limitedPropertiesList[$primitive->getName()])) {
00082 $result->setLimitedPropertiesList(
00083 $this->limitedPropertiesList[$primitive->getName()]
00084 );
00085 }
00086
00087 return $result;
00088 }
00089
00090 public function makeListItemBuilder($object)
00091 {
00092 return $this;
00093 }
00094
00098 public function makeReverseBuilder()
00099 {
00100 throw new UnimplementedFeatureException(
00101 'reverse builder is not provided yet'
00102 );
00103 }
00104
00109 public function make($object, $recursive = true)
00110 {
00111
00112 if (
00113 ($object instanceof PrototypedEntity)
00114 || ($object instanceof Form)
00115 ) {
00116 $proto = $this->proto;
00117
00118 if ($object instanceof Form) {
00119 $objectProto = $object->getProto();
00120 } else
00121 $objectProto = $object->entityProto();
00122
00123 if (
00124 $objectProto
00125 && !ClassUtils::isInstanceOf($proto, $objectProto)
00126 ) {
00127 if (!$objectProto->isInstanceOf($proto))
00128 throw new WrongArgumentException(
00129 'target proto '.get_class($objectProto)
00130 .' is not a child of '.get_class($proto)
00131 );
00132
00133 $proto = $objectProto;
00134
00135 return $this->cloneBuilder($proto)->
00136 make($object);
00137 }
00138 }
00139
00140 if ($this->proto->isAbstract())
00141 throw new WrongArgumentException(
00142 'cannot make from abstract proto '
00143 .get_class($this->proto)
00144 );
00145
00146 return $this->compile($object, $recursive);
00147 }
00148
00149 public function compile($object, $recursive = true)
00150 {
00151 $result = $this->createEmpty();
00152
00153 $this->initialize($object, $result);
00154
00155 if ($recursive)
00156 $result = $this->upperMake($object, $result);
00157 else
00158 $result = $this->fillOwn($object, $result);
00159
00160 return $result;
00161 }
00162
00163 public function upperMake($object, &$result)
00164 {
00165 if ($this->proto->baseProto()) {
00166 $this->cloneBuilder($this->proto->baseProto())->
00167 upperMake($object, $result);
00168 }
00169
00170 return $this->fillOwn($object, $result);
00171 }
00172
00173 public function makeList($objectsList, $recursive = true)
00174 {
00175 if ($objectsList === null)
00176 return null;
00177
00178 Assert::isArray($objectsList);
00179
00180 $result = array();
00181
00182 foreach ($objectsList as $id => $object) {
00183 $result[$id] = $this->makeListItemBuilder($object)->
00184 make($object, $recursive);
00185 }
00186
00187 return $result;
00188 }
00189
00193 public function makeOwn($object, &$result)
00194 {
00195 return $this->fillOwn($object, $result);
00196 }
00197
00198 public function upperFill($object, &$result)
00199 {
00200 if ($this->proto->baseProto()) {
00201 $this->cloneBuilder($this->proto->baseProto())->
00202 upperFill($object, $result);
00203 }
00204
00205 return $this->fillOwn($object, $result);
00206 }
00207
00208 public function fillOwn($object, &$result)
00209 {
00210 if ($object === null)
00211 return $result;
00212
00213 $getter = $this->getGetter($object);
00214 $setter = $this->getSetter($result);
00215
00216 foreach ($this->getFormMapping() as $id => $primitive) {
00217
00218 $value = $getter->get($id);
00219
00220 if ($primitive instanceof PrimitiveFormsList) {
00221
00222 $setter->set(
00223 $id,
00224 $this->cloneInnerBuilder($id)->
00225 makeList($value)
00226 );
00227
00228 } elseif ($primitive instanceof PrimitiveForm) {
00229
00230 if (
00231 $primitive->isComposite()
00232 && ($previousValue = $setter->getGetter()->get($id))
00233 ) {
00234
00235 $this->cloneInnerBuilder($id)->
00236 upperFill($value, $previousValue);
00237
00238 } elseif ($value !== null || $primitive->isRequired()) {
00239
00240 $setter->set(
00241 $id,
00242 $this->cloneInnerBuilder($id)->
00243 make($value)
00244 );
00245 }
00246
00247 } else {
00248 $setter->set($id, $value);
00249 }
00250 }
00251
00252 return $result;
00253 }
00254
00255 protected function initialize($object, &$result)
00256 {
00257 return $this;
00258 }
00259
00260 protected function getFormMapping()
00261 {
00262 $protoMapping = $this->proto->getFormMapping();
00263
00264 if ($this->limitedPropertiesList === null)
00265 return $protoMapping;
00266
00267 $result = array();
00268
00269 foreach ($protoMapping as $id => $value) {
00270 if (!isset($this->limitedPropertiesList[$id]))
00271 continue;
00272
00273 $result[$id] = $value;
00274 }
00275
00276 return $result;
00277 }
00278 }
00279 ?>