# LightMetaProperty.class.php

Go to the documentation of this file.

    00001 <?php
    00002 /***************************************************************************
    00003  *   Copyright (C) 2006-2009 by Konstantin V. Arkhipov                     *
    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
    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') // obsoleted
    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                     // supported only in master
    00121                 } elseif ($type != 'float') { // string
    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') // obsoleted
    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                 // skip collections
    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                 // skip collections
    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                 // BOVM: prevents segfault on >=php-5.2.5
    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                         // will be fetched later
    00416                         // by AbstractProtoClass::fetchEncapsulants
    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             // veeeeery "special" handling, by tradition.
    00428             // MySQL returns 0/1, others - t/f
    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             // NOTE: enum here formless types
    00501             return ($this->type == 'enumeration');
    00502         }
    00503     }
    00504 ?>