00001 <?php
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00018 class LightMetaProperty implements Stringable
00019 {
00020 const UNSIGNED_FLAG = 0x1000;
00021
00022 private static $limits = array(
00023 0x0002 => array(
00024 PrimitiveInteger::SIGNED_SMALL_MIN,
00025 PrimitiveInteger::SIGNED_SMALL_MAX
00026 ),
00027 0x1002 => array(
00028 0,
00029 PrimitiveInteger::UNSIGNED_SMALL_MAX
00030 ),
00031 0x0004 => array(
00032 PrimitiveInteger::SIGNED_MIN,
00033 PrimitiveInteger::SIGNED_MAX
00034 ),
00035 0x1004 => array(
00036 0,
00037 PrimitiveInteger::UNSIGNED_MAX
00038 ),
00039 0x0008 => array(
00040 PrimitiveInteger::SIGNED_BIG_MIN,
00041 PrimitiveInteger::SIGNED_BIG_MAX
00042 ),
00043 0x1008 => array(
00044 0,
00045 null
00046 )
00047 );
00048
00049 private $name = null;
00050 private $columnName = null;
00051
00052 private $type = null;
00053 private $className = null;
00054
00055 private $size = null;
00056
00057 private $min = null;
00058 private $max = null;
00059
00060 private $required = false;
00061 private $generic = false;
00062 private $inner = false;
00063
00065 private $relationId = null;
00066
00068 private $strategyId = null;
00069
00070 private $getter = null;
00071 private $setter = null;
00072 private $dropper = null;
00073
00074 private $identifier = null;
00075
00079 public static function create()
00080 {
00081 return new self;
00082 }
00083
00089 public static function fill(
00090 LightMetaProperty $property,
00091 $name, $columnName, $type, $className, $size,
00092 $required, $generic, $inner, $relationId, $strategyId
00093 )
00094 {
00095 $property->name = $name;
00096
00097 $methodSuffix = ucfirst($name);
00098 $property->getter = 'get'.$methodSuffix;
00099 $property->setter = 'set'.$methodSuffix;
00100 $property->dropper = 'drop'.$methodSuffix;
00101
00102 if ($columnName)
00103 $property->columnName = $columnName;
00104 else
00105 $property->columnName = $name;
00106
00107 $property->type = $type;
00108 $property->className = $className;
00109
00110 if ($size) {
00111 if (
00112 ($type == 'integer')
00113 || ($type == 'identifier')
00114 || ($type == 'integerIdentifier')
00115 || ($type == 'enumeration')
00116 ) {
00117 $property->min = self::$limits[$size][0];
00118 $property->max = self::$limits[$size][1];
00119 } elseif ($type == 'scalarIdentifier') {
00120
00121 } elseif ($type != 'float') {
00122 $property->max = $size;
00123 }
00124
00125 $property->size = $size;
00126 }
00127
00128 $property->required = $required;
00129 $property->generic = $generic;
00130 $property->inner = $inner;
00131
00132 $property->relationId = $relationId;
00133 $property->strategyId = $strategyId;
00134
00135 $property->identifier =
00136 $generic && $required && (
00137 ($type == 'identifier')
00138 || ($type == 'integerIdentifier')
00139 || ($type == 'scalarIdentifier')
00140 );
00141
00142 return $property;
00143 }
00144
00145 public function getName()
00146 {
00147 return $this->name;
00148 }
00149
00150 public function getColumnName()
00151 {
00152 return $this->columnName;
00153 }
00154
00155 public function getGetter()
00156 {
00157 return $this->getter;
00158 }
00159
00160 public function getSetter()
00161 {
00162 return $this->setter;
00163 }
00164
00165 public function getDropper()
00166 {
00167 return $this->dropper;
00168 }
00169
00173 public function setColumnName($name)
00174 {
00175 $this->columnName = $name;
00176
00177 return $this;
00178 }
00179
00180 public function getClassName()
00181 {
00182 return $this->className;
00183 }
00184
00185 public function getMin()
00186 {
00187 return $this->min;
00188 }
00189
00190 public function getMax()
00191 {
00192 return $this->max;
00193 }
00194
00195 public function getType()
00196 {
00197 return $this->type;
00198 }
00199
00200 public function isRequired()
00201 {
00202 return $this->required;
00203 }
00204
00208 public function setRequired($yrly)
00209 {
00210 $this->required = $yrly;
00211
00212 return $this;
00213 }
00214
00215 public function isGenericType()
00216 {
00217 return $this->generic;
00218 }
00219
00220 public function isInner()
00221 {
00222 return $this->inner;
00223 }
00224
00225 public function getRelationId()
00226 {
00227 return $this->relationId;
00228 }
00229
00230 public function getFetchStrategyId()
00231 {
00232 return $this->strategyId;
00233 }
00234
00238 public function setFetchStrategy(FetchStrategy $strategy)
00239 {
00240 $this->strategyId = $strategy->getId();
00241
00242 return $this;
00243 }
00244
00248 public function dropFetchStrategy()
00249 {
00250 $this->strategyId = null;
00251
00252 return $this;
00253 }
00254
00255 public function getContainerName($holderName)
00256 {
00257 return $holderName.ucfirst($this->getName()).'DAO';
00258 }
00259
00260 public function isBuildable($array, $prefix = null)
00261 {
00262 $column = $prefix.$this->columnName;
00263 $exists = isset($array[$column]);
00264
00265 if (
00266 $this->relationId
00267 || $this->generic
00268 ) {
00269
00270 if (
00271 ($this->relationId <> MetaRelation::ONE_TO_ONE)
00272 && !$this->generic
00273 )
00274 return false;
00275
00276 if ($this->required) {
00277 Assert::isTrue(
00278 $exists,
00279 'required property not found: '.$this->name
00280 );
00281 } elseif (!$exists) {
00282 return false;
00283 }
00284 }
00285
00286 return true;
00287 }
00288
00292 public function makePrimitive($name)
00293 {
00294 $prm =
00295 call_user_func(
00296 array('Primitive', $this->type),
00297 $name
00298 );
00299
00300 if (null !== ($min = $this->getMin()))
00301 $prm->setMin($min);
00302
00303 if (null !== ($max = $this->getMax()))
00304 $prm->setMax($max);
00305
00306 if ($prm instanceof IdentifiablePrimitive)
00307 $prm->of($this->className);
00308
00309 if ($this->required)
00310 $prm->required();
00311
00312 return $prm;
00313 }
00314
00315 public function fillMapping(array $mapping)
00316 {
00317 if (
00318 !$this->relationId
00319 || (
00320 $this->relationId
00321 == MetaRelation::ONE_TO_ONE
00322 ) || (
00323 $this->strategyId
00324 == FetchStrategy::LAZY
00325 )
00326 ) {
00327 $mapping[$this->name] = $this->columnName;
00328 }
00329
00330 return $mapping;
00331 }
00332
00336 public function fillForm(Form $form, $prefix = null)
00337 {
00338 return $form->add(
00339 $this->makePrimitive($prefix.$this->name)
00340 );
00341 }
00342
00346 public function fillQuery(
00347 InsertOrUpdateQuery $query,
00348 Prototyped $object
00349 )
00350 {
00351 if (
00352 $this->relationId
00353 || $this->generic
00354 ) {
00355
00356 if (
00357 ($this->relationId <> MetaRelation::ONE_TO_ONE)
00358 && !$this->generic
00359 )
00360 return $query;
00361
00362 $value = $object->{$this->getter}();
00363
00364 if ($this->type == 'binary') {
00365 $query->set($this->columnName, new DBBinary($value));
00366 } else {
00367 $query->lazySet($this->columnName, $value);
00368 }
00369 }
00370
00371 return $query;
00372 }
00373
00374 public function toValue(ProtoDAO $dao = null, $array, $prefix = null)
00375 {
00376 $raw = $array[$prefix.$this->columnName];
00377
00378 if ($this->type == 'binary') {
00379 return DBPool::getByDao($dao)->getDialect()->unquoteBinary($raw);
00380 }
00381
00382 if ($this->className == 'HttpUrl') {
00383 return HttpUrl::create()->parse($raw);
00384 }
00385
00386 if (
00387 !$this->identifier
00388 && $this->generic
00389 && $this->className
00390 ) {
00391 return call_user_func(array($this->className, 'create'), $raw);
00392 } elseif (
00393 !$this->identifier
00394 && $this->className
00395 ) {
00396
00397 Assert::classExists($this->className);
00398
00399 if (!is_subclass_of($this->className, 'Enumeration')) {
00400 $remoteDao = call_user_func(array($this->className, 'dao'));
00401
00402 $joinPrefix = $remoteDao->getJoinPrefix(
00403 $this->columnName,
00404 $prefix
00405 );
00406
00407 $joined = (
00408 ($this->strategyId == FetchStrategy::JOIN)
00409 || isset($array[$joinPrefix.$remoteDao->getIdName()])
00410 );
00411
00412 if ($joined) {
00413 return $remoteDao->makeObject($array, $joinPrefix);
00414 } else {
00415
00416
00417 $object = new $this->className;
00418 $object->setId($raw);
00419
00420 return $object;
00421 }
00422 } else {
00423 return new $this->className($raw);
00424 }
00425 }
00426
00427
00428
00429 if ($this->type == 'boolean') {
00430 return (bool) strtr($raw, array('f' => null));
00431 }
00432
00433 return $raw;
00434 }
00435
00436 public function isIdentifier()
00437 {
00438 return $this->identifier;
00439 }
00440
00441 final public function toString()
00442 {
00443 return
00444 get_class($this).'::fill('
00445 .'new '.get_class($this).'(), '
00446 ."'{$this->name}', "
00447 .(
00448 ($this->columnName <> $this->name)
00449 ? "'{$this->columnName}'"
00450 : 'null'
00451 )
00452 .', '
00453 ."'{$this->type}', "
00454 .(
00455 $this->className
00456 ? "'{$this->className}'"
00457 : 'null'
00458 )
00459 .', '
00460 .(
00461 $this->size
00462 ? $this->size
00463 : 'null'
00464 )
00465 .', '
00466 .(
00467 $this->required
00468 ? 'true'
00469 : 'false'
00470 )
00471 .', '
00472 .(
00473 $this->generic
00474 ? 'true'
00475 : 'false'
00476 )
00477 .', '
00478 .(
00479 $this->inner
00480 ? 'true'
00481 : 'false'
00482 )
00483 .', '
00484 .(
00485 $this->relationId
00486 ? $this->relationId
00487 : 'null'
00488 )
00489 .', '
00490 .(
00491 $this->strategyId
00492 ? $this->strategyId
00493 : 'null'
00494 )
00495 .')';
00496 }
00497
00498 public function isFormless()
00499 {
00500
00501 return ($this->type == 'enumeration');
00502 }
00503 }
00504 ?>