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 ?>