# MetaClassProperty.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
    00015     class MetaClassProperty
    00016     {
    00017         private $class      = null;
    00018
    00019         private $name       = null;
    00020         private $columnName = null;
    00021
    00022         private $type       = null;
    00023         private $size       = null;
    00024
    00025         private $required   = false;
    00026         private $identifier = false;
    00027
    00028         private $relation   = null;
    00029
    00030         private $strategy   = null;
    00031
    00032         public function __construct(
    00033             $name,
    00034             BasePropertyType $type,
    00035             MetaClass $class
    00036         )
    00037         {
    00038             $this->name = $name;
    00039
    00040             $this->type = $type;
    00041
    00042             $this->class = $class;
    00043         }
    00044
    00045         public function equals(MetaClassProperty $property)
    00046         {
    00047             return (
    00048                 ($property->getName() == $this->getName())
    00049                 && ($property->getColumnName() == $this->getColumnName())
    00050                 && ($property->getType() == $this->getType())
    00051                 && ($property->getSize() == $this->getSize())
    00052                 && ($property->getRelation() == $this->getRelation())
    00053                 && ($property->isRequired() == $this->isRequired())
    00054                 && ($property->isIdentifier() == $this->isIdentifier())
    00055             );
    00056         }
    00057
    00061         public function getClass()
    00062         {
    00063             return $this->class;
    00064         }
    00065
    00066         public function getName()
    00067         {
    00068             return $this->name;
    00069         }
    00070
    00074         public function setName($name)
    00075         {
    00076             $this->name = $name;
    00077
    00078             return $this;
    00079         }
    00080
    00081         public function getColumnName()
    00082         {
    00083             return $this->columnName;
    00084         }
    00085
    00089         public function setColumnName($name)
    00090         {
    00091             $this->columnName = $name;
    00092
    00093             return $this;
    00094         }
    00095
    00099         public function getConvertedName()
    00100         {
    00101             return strtolower(
    00102                 preg_replace(':([A-Z]):', '_\1', $this->name)
    00103             );
    00104         }
    00105
    00109         public function getType()
    00110         {
    00111             return $this->type;
    00112         }
    00113
    00114         public function getSize()
    00115         {
    00116             return $this->size;
    00117         }
    00118
    00123         public function setSize($size)
    00124         {
    00125             if ($this->type instanceof NumericType) {
    00126                 if (strpos($size, ',') !== false) {
    00127                     list($size, $precision) = explode(',', $size, 2);
    00128
    00129                     $this->type->setPrecision($precision);
    00130                 }
    00131             }
    00132
    00133             Assert::isInteger(
    00134                 $size,
    00135                 'only integers allowed in size parameter'
    00136             );
    00137
    00138             if ($this->type->isMeasurable()) {
    00139                 $this->size = $size;
    00140             } else
    00141                 throw new WrongArgumentException(
    00142                     "size not allowed for '"
    00143                     .$this->getName().'::'.get_class($this->type)
    00144                     ."' type"
    00145                 );
    00146
    00147             return $this;
    00148         }
    00149
    00150         public function isRequired()
    00151         {
    00152             return $this->required;
    00153         }
    00154
    00155         public function isOptional()
    00156         {
    00157             return !$this->required;
    00158         }
    00159
    00163         public function required()
    00164         {
    00165             $this->required = true;
    00166
    00167             return $this;
    00168         }
    00169
    00173         public function optional()
    00174         {
    00175             $this->required = false;
    00176
    00177             return $this;
    00178         }
    00179
    00180         public function isIdentifier()
    00181         {
    00182             return $this->identifier;
    00183         }
    00184
    00188         public function setIdentifier($really = false)
    00189         {
    00190             $this->identifier = ($really === true);
    00191
    00192             return $this;
    00193         }
    00194
    00198         public function getRelation()
    00199         {
    00200             return $this->relation;
    00201         }
    00202
    00203         public function getRelationId()
    00204         {
    00205             if ($this->relation)
    00206                 return $this->relation->getId();
    00207
    00208             return null;
    00209         }
    00210
    00214         public function setRelation(MetaRelation $relation)
    00215         {
    00216             $this->relation = $relation;
    00217
    00218             return $this;
    00219         }
    00220
    00224         public function setFetchStrategy(FetchStrategy $strategy)
    00225         {
    00226             $this->strategy = $strategy;
    00227
    00228             return $this;
    00229         }
    00230
    00234         public function getFetchStrategy()
    00235         {
    00236             return $this->strategy;
    00237         }
    00238
    00239         public function getFetchStrategyId()
    00240         {
    00241             if ($this->strategy)
    00242                 return $this->strategy->getId();
    00243             elseif (
    00244                 $this->getClass()->getFetchStrategyId()
    00245                 && ($this->getRelationId() == MetaRelation::ONE_TO_ONE)
    00246                 && ($this->getType() instanceof ObjectType)
    00247                 && (!$this->getType()->isGeneric())
    00248             )
    00249                 return $this->getClass()->getFetchStrategyId();
    00250
    00251             return null;
    00252         }
    00253
    00254         public function toMethods(
    00255             MetaClass $class,
    00256             MetaClassProperty $holder = null
    00257         )
    00258         {
    00259             return $this->type->toMethods($class, $this, $holder);
    00260         }
    00261
    00262         public function getRelationColumnName()
    00263         {
    00264             if ($this->type instanceof ObjectType && !$this->type->isGeneric()) {
    00265                 if ($this->relation->getId() == MetaRelation::MANY_TO_MANY)
    00266                     $columnName = $this->type->getClass()->getTableName().'_id';
    00267                 else
    00268                     $columnName = $this->getColumnName();
    00269             } elseif ($this->type instanceof InternalType) {
    00270                 $out = array();
    00271                 foreach ($this->type->getSuffixList() as $suffix) {
    00272                     $out[] = $this->getColumnName().'_'.$suffix;
    00273                 }
    00274                 return $out;
    00275             } else
    00276                 $columnName = $this->getColumnName();
    00277
    00278             return $columnName;
    00279         }
    00280
    00281         public function toColumn()
    00282         {
    00283             if (
    00284                 $this->getType() instanceof ObjectType
    00285                 && (
    00286                     ($this->getType() instanceof InternalType)
    00287                     || (
    00288                         !$this->getType()->isGeneric()
    00289                         && (
    00290                             $this->getType()->getClass()->getPattern()
    00291                                 instanceof ValueObjectPattern
    00292                         )
    00293                     )
    00294                 )
    00295             ) {
    00296                 $columns = array();
    00297
    00298                 $prefix =
    00299                     $this->getType() instanceof InternalType
    00300                         ? $this->getColumnName().'_'
    00301                         : null;
    00302
    00303                 $remote = $this->getType()->getClass();
    00304
    00305                 foreach ($remote->getAllProperties() as $property) {
    00306                     $columns[] = $property->buildColumn(
    00307                         $prefix.$property->getRelationColumnName()
    00308                     );
    00309                 }
    00310
    00311                 return $columns;
    00312             }
    00313
    00314             return $this->buildColumn($this->getRelationColumnName());
    00315         }
    00316
    00317         public function toLightProperty(MetaClass $holder)
    00318         {
    00319             $className = null;
    00320
    00321             if (
    00322                 ($this->getRelationId() == MetaRelation::ONE_TO_MANY)
    00323                 || ($this->getRelationId() == MetaRelation::MANY_TO_MANY)
    00324             ) {
    00325                 // collections
    00326                 $primitiveName = 'identifierList';
    00327             } elseif ($this->isIdentifier()) {
    00328                 if ($this->getType() instanceof IntegerType) {
    00329                     $primitiveName = 'integerIdentifier';
    00330                     $className = $holder->getName();
    00331                 } elseif ($this->getType() instanceof StringType) {
    00332                     $primitiveName = 'scalarIdentifier';
    00333                     $className = $holder->getName();
    00334                 } else
    00335                     $primitiveName = $this->getType()->getPrimitiveName();
    00336             } elseif (
    00337                 !$this->isIdentifier()
    00338                 && !$this->getType()->isGeneric()
    00339                 && ($this->getType() instanceof ObjectType)
    00340             ) {
    00341                 $pattern = $this->getType()->getClass()->getPattern();
    00342
    00343                 if ($pattern instanceof EnumerationClassPattern) {
    00344                     $primitiveName = 'enumeration';
    00345                 } elseif (
    00346                     $pattern instanceof DictionaryClassPattern
    00347                     && ($identifier = $this->getType()->getClass()->getIdentifier())
    00348                 ) {
    00349                     if ($identifier->getType() instanceof IntegerType) {
    00350                         $primitiveName = 'integerIdentifier';
    00351                     } elseif ($identifier->getType() instanceof StringType) {
    00352                         $primitiveName = 'scalarIdentifier';
    00353                     } else
    00354                         $primitiveName = $this->getType()->getPrimitiveName();
    00355                 } else
    00356                     $primitiveName = $this->getType()->getPrimitiveName();
    00357             } else
    00358                 $primitiveName = $this->getType()->getPrimitiveName();
    00359
    00360             $inner = false;
    00361
    00362             if ($this->getType() instanceof ObjectType) {
    00363                 $className = $this->getType()->getClassName();
    00364
    00365                 if (!$this->getType()->isGeneric()) {
    00366                     $class = $this->getType()->getClass();
    00367                     $pattern = $class->getPattern();
    00368
    00369                     if ($pattern instanceof InternalClassPattern)
    00370                         $className = $holder->getName();
    00371
    00372                     if (
    00373                         (
    00374                             ($pattern instanceof InternalClassPattern)
    00375                             || ($pattern instanceof ValueObjectPattern)
    00376                         ) && (
    00377                             $className <> $holder->getName()
    00378                         )
    00379                     ) {
    00380                         $inner = true;
    00381                     }
    00382                 }
    00383             }
    00384
    00385             $propertyClassName = (
    00386                 $inner
    00387                     ? 'InnerMetaProperty'
    00388                     : 'LightMetaProperty'
    00389             );
    00390
    00391             if (
    00392                 ($this->getType() instanceof IntegerType)
    00393             ) {
    00394                 $size = $this->getType()->getSize();
    00395             } elseif (
    00396                 ($this->getType() instanceof ObjectType)
    00397                 && ($this->getRelationId() == MetaRelation::ONE_TO_ONE)
    00398                 && ($identifier = $this->getType()->getClass()->getIdentifier())
    00399                 && ($this->getType()->isMeasurable())
    00400             ) {
    00401                 $size = $identifier->getType()->getSize();
    00402             } elseif ($this->getType()->isMeasurable()) {
    00403                 $size = $this->size;
    00404             } else {
    00405                 $size = null;
    00406             }
    00407
    00408             return
    00409                 call_user_func_array(
    00410                     array($propertyClassName, 'fill'),
    00411                     array(
    00412                         new $propertyClassName,
    00413                         $this->getName(),
    00414                         $this->getName() <> $this->getRelationColumnName()
    00415                             ? $this->getRelationColumnName()
    00416                             : null,
    00417                         $primitiveName,
    00418                         $className,
    00419                         $size,
    00420                         $this->isRequired(),
    00421                         $this->getType()->isGeneric(),
    00422                         $inner,
    00423                         $this->getRelationId(),
    00424                         $this->getFetchStrategyId()
    00425                     )
    00426                 );
    00427         }
    00428
    00429         private function buildColumn($columnName)
    00430         {
    00431             if (is_array($columnName)) {
    00432                 $out = array();
    00433
    00434                 foreach ($columnName as $name) {
    00435                     $out[] = $this->buildColumn($name);
    00436                 }
    00437
    00438                 return $out;
    00439             }
    00440
    00441             $column = <<<EOT
    00442 addColumn(
    00443     DBColumn::create(
    00444         {$this->type->toColumnType($this->size)}
    00445 EOT;
    00446
    00447             if ($this->required) {
    00448                 $column .= <<<EOT
    00449 ->
    00450 setNull(false)
    00451 EOT;
    00452             }
    00453
    00454             if ($this->size) {
    00455                 $column .= <<<EOT
    00456 ->
    00457 setSize({$this->size})
    00458 EOT;
    00459             }
    00460
    00461             if ($this->type instanceof NumericType) {
    00462                 $column .= <<<EOT
    00463 ->
    00464 setPrecision({$this->type->getPrecision()})
    00465 EOT;
    00466             }
    00467
    00468             $column .= <<<EOT
    00469 ,
    00470 '{$columnName}'
    00471 )
    00472 EOT;
    00473
    00474             if ($this->identifier) {
    00475                 $column .= <<<EOT
    00476 ->
    00477 setPrimaryKey(true)
    00478 EOT;
    00479
    00480                 if ($this->getType() instanceof IntegerType) {
    00481                     $column .= <<<EOT
    00482 ->
    00483 setAutoincrement(true)
    00484 EOT;
    00485                 }
    00486             }
    00487
    00488             if ($this->type->hasDefault()) {
    00489                 $default = $this->type->getDefault();
    00490
    00491                 if ($this->type instanceof BooleanType) {
    00492                     if ($default)
    00493                         $default = 'true';
    00494                     else
    00495                         $default = 'false';
    00496                 } elseif ($this->type instanceof StringType) {
    00497                     $default = "'{$default}'";
    00498                 }
    00499
    00500                 $column .= <<<EOT
    00501 ->
    00502 setDefault({$default})
    00503 EOT;
    00504             }
    00505
    00506             $column .= <<<EOT
    00507
    00508 )
    00509 EOT;
    00510
    00511             return $column;
    00512         }
    00513
    00514         private function toVarName($name)
    00515         {
    00516             return strtolower($name[0]).substr($name, 1);
    00517         }
    00518     }
    00519 ?>