Duplicate code is one of the most pungent code smells. A rule that is often used is to re-structure code once it is duplicated in three or more places.
Common duplication problems, and corresponding solutions are:
Complex classes like Generator often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes. You can also have a look at the cohesion graph to spot any un-connected, or weakly-connected components.
Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.
While breaking up the class, it is a good idea to analyze how other classes use Generator, and based on these observations, apply Extract Interface, too.
| 1 | <?php |
||
| 22 | class Generator |
||
| 23 | { |
||
| 24 | /** @var DatabaseInterface */ |
||
| 25 | protected $database; |
||
| 26 | |||
| 27 | /** @var \samsonphp\generator\Generator */ |
||
| 28 | protected $generator; |
||
| 29 | |||
| 30 | /** @var Metadata[] Collection of entities metadata */ |
||
| 31 | protected $metadata; |
||
| 32 | |||
| 33 | /** |
||
| 34 | * Transliterate string to english. |
||
| 35 | * |
||
| 36 | * @param string $string Source string |
||
| 37 | * @return string Transliterated string |
||
| 38 | */ |
||
| 39 | protected function transliterated($string) |
||
| 40 | { |
||
| 41 | return str_replace( |
||
| 42 | ' ', |
||
| 43 | '', |
||
| 44 | ucwords(iconv("UTF-8", "UTF-8//IGNORE", strtr($string, array( |
||
| 45 | "'" => "", |
||
| 46 | "`" => "", |
||
| 47 | "-" => " ", |
||
| 48 | "_" => " ", |
||
| 49 | "а" => "a", "А" => "a", |
||
| 50 | "б" => "b", "Б" => "b", |
||
| 51 | "в" => "v", "В" => "v", |
||
| 52 | "г" => "g", "Г" => "g", |
||
| 53 | "д" => "d", "Д" => "d", |
||
| 54 | "е" => "e", "Е" => "e", |
||
| 55 | "ж" => "zh", "Ж" => "zh", |
||
| 56 | "з" => "z", "З" => "z", |
||
| 57 | "и" => "i", "И" => "i", |
||
| 58 | "й" => "y", "Й" => "y", |
||
| 59 | "к" => "k", "К" => "k", |
||
| 60 | "л" => "l", "Л" => "l", |
||
| 61 | "м" => "m", "М" => "m", |
||
| 62 | "н" => "n", "Н" => "n", |
||
| 63 | "о" => "o", "О" => "o", |
||
| 64 | "п" => "p", "П" => "p", |
||
| 65 | "р" => "r", "Р" => "r", |
||
| 66 | "с" => "s", "С" => "s", |
||
| 67 | "т" => "t", "Т" => "t", |
||
| 68 | "у" => "u", "У" => "u", |
||
| 69 | "ф" => "f", "Ф" => "f", |
||
| 70 | "х" => "h", "Х" => "h", |
||
| 71 | "ц" => "c", "Ц" => "c", |
||
| 72 | "ч" => "ch", "Ч" => "ch", |
||
| 73 | "ш" => "sh", "Ш" => "sh", |
||
| 74 | "щ" => "sch", "Щ" => "sch", |
||
| 75 | "ъ" => "", "Ъ" => "", |
||
| 76 | "ы" => "y", "Ы" => "y", |
||
| 77 | "ь" => "", "Ь" => "", |
||
| 78 | "э" => "e", "Э" => "e", |
||
| 79 | "ю" => "yu", "Ю" => "yu", |
||
| 80 | "я" => "ya", "Я" => "ya", |
||
| 81 | "і" => "i", "І" => "i", |
||
| 82 | "ї" => "yi", "Ї" => "yi", |
||
| 83 | "є" => "e", "Є" => "e" |
||
| 84 | ) |
||
| 85 | ) |
||
| 86 | ) |
||
| 87 | ) |
||
| 88 | ); |
||
| 89 | } |
||
| 90 | |||
| 91 | /** |
||
| 92 | * Get class constant name by its value. |
||
| 93 | * |
||
| 94 | * @param string $value Constant value |
||
| 95 | * @param string $className Class name |
||
| 96 | * @return string Full constant name |
||
| 97 | */ |
||
| 98 | protected function constantNameByValue($value, $className = Field::ENTITY) |
||
| 99 | { |
||
| 100 | // Get array where class constants are values and their values are keys |
||
| 101 | $nameByValue = array_flip((new \ReflectionClass($className))->getConstants()); |
||
| 102 | |||
| 103 | // Try to find constant by its value |
||
| 104 | if (null !== $nameByValue[$value]) { |
||
| 105 | // Return constant name |
||
| 106 | return $nameByValue[$value]; |
||
| 107 | } |
||
| 108 | |||
| 109 | return ''; |
||
| 110 | } |
||
| 111 | |||
| 112 | /** |
||
| 113 | * Get correct entity name. |
||
| 114 | * |
||
| 115 | * @param string $navigationName Original navigation entity name |
||
| 116 | * @return string Correct PHP-supported entity name |
||
| 117 | */ |
||
| 118 | protected function entityName($navigationName) |
||
| 119 | { |
||
| 120 | return ucfirst($this->getValidName($this->transliterated($navigationName))); |
||
| 121 | } |
||
| 122 | |||
| 123 | /** |
||
| 124 | * Remove all wrong characters from entity name |
||
| 125 | * |
||
| 126 | * @param string $navigationName Original navigation entity name |
||
| 127 | * @return string Correct PHP-supported entity name |
||
| 128 | */ |
||
| 129 | protected function getValidName($navigationName) |
||
| 130 | { |
||
| 131 | return preg_replace('/(^\d*)|([^\w\d_])/', '', $navigationName); |
||
| 132 | } |
||
| 133 | |||
| 134 | /** |
||
| 135 | * Get correct full entity name with name space. |
||
| 136 | * |
||
| 137 | * @param string $navigationName Original navigation entity name |
||
| 138 | * @param string $namespace Namespace |
||
| 139 | * @return string Correct PHP-supported entity name |
||
| 140 | */ |
||
| 141 | protected function fullEntityName($navigationName, $namespace = __NAMESPACE__) |
||
| 142 | { |
||
| 143 | return '\\'.$namespace.'\\'.$this->entityName($navigationName); |
||
| 144 | } |
||
| 145 | |||
| 146 | /** |
||
| 147 | * Get correct field name. |
||
| 148 | * |
||
| 149 | * @param string $fieldName Original field name |
||
| 150 | * @return string Correct PHP-supported field name |
||
| 151 | */ |
||
| 152 | protected function fieldName($fieldName) |
||
| 153 | { |
||
| 154 | return $fieldName = lcfirst($this->transliterated($fieldName)); |
||
|
|
|||
| 155 | } |
||
| 156 | |||
| 157 | /** |
||
| 158 | * Get additional field type in form of Field constant name |
||
| 159 | * by database additional field type identifier. |
||
| 160 | * |
||
| 161 | * @param integer $fieldType Additional field type identifier |
||
| 162 | * @return string Additional field type constant |
||
| 163 | */ |
||
| 164 | protected function additionalFieldType($fieldType) |
||
| 165 | { |
||
| 166 | return 'Field::'.$this->constantNameByValue($fieldType); |
||
| 167 | } |
||
| 168 | |||
| 169 | /** |
||
| 170 | * Generate Query::where() analog for specific field. |
||
| 171 | * |
||
| 172 | * @param string $fieldName Field name |
||
| 173 | * @param string $fieldId Field primary identifier |
||
| 174 | * @param string $fieldType Field PHP type |
||
| 175 | * @return string Generated PHP method code |
||
| 176 | */ |
||
| 177 | View Code Duplication | protected function generateFieldConditionMethod($fieldName, $fieldId, $fieldType) |
|
| 178 | { |
||
| 179 | $code = "\n\t" . '/**'; |
||
| 180 | $code .= "\n\t" . ' * Add '.$fieldName.'(#' . $fieldId . ') field query condition.'; |
||
| 181 | $code .= "\n\t" . ' * @param '.Field::phpType($fieldType).' $value Field value'; |
||
| 182 | $code .= "\n\t" . ' * @return $this Chaining'; |
||
| 183 | $code .= "\n\t" . ' * @see Generic::where()'; |
||
| 184 | $code .= "\n\t" . ' */'; |
||
| 185 | $code .= "\n\t" . 'public function ' . $fieldName . '($value, $relation = ArgumentInterface::EQUAL)'; |
||
| 186 | $code .= "\n\t" . "{"; |
||
| 187 | $code .= "\n\t\t" . 'return $this->where("'.$fieldName.'", $value, $relation);'; |
||
| 188 | |||
| 189 | return $code . "\n\t" . "}"."\n"; |
||
| 190 | } |
||
| 191 | |||
| 192 | /** |
||
| 193 | * Generate Query::where() analog for specific field. |
||
| 194 | * |
||
| 195 | * @param string $fieldName Field name |
||
| 196 | * @param string $fieldId Field primary identifier |
||
| 197 | * @param string $fieldType Field PHP type |
||
| 198 | * @return string Generated PHP method code |
||
| 199 | */ |
||
| 200 | View Code Duplication | protected function generateLocalizedFieldConditionMethod($fieldName, $fieldId, $fieldType) |
|
| 201 | { |
||
| 202 | $code = "\n\t" . '/**'; |
||
| 203 | $code .= "\n\t" . ' * Add '.$fieldName.'(#' . $fieldId . ') field query condition.'; |
||
| 204 | $code .= "\n\t" . ' * @param '.Field::phpType($fieldType).' $value Field value'; |
||
| 205 | $code .= "\n\t" . ' * @return $this Chaining'; |
||
| 206 | $code .= "\n\t" . ' * @see Generic::where()'; |
||
| 207 | $code .= "\n\t" . ' */'; |
||
| 208 | $code .= "\n\t" . 'public function ' . $fieldName . '($value)'; |
||
| 209 | $code .= "\n\t" . "{"; |
||
| 210 | $code .= "\n\t\t" . 'return $this->where("'.$fieldName.'", $value);'; |
||
| 211 | |||
| 212 | return $code . "\n\t" . "}"."\n"; |
||
| 213 | } |
||
| 214 | |||
| 215 | /** |
||
| 216 | * Create entity PHP class code. |
||
| 217 | * |
||
| 218 | * @param Metadata $metadata Entity metadata |
||
| 219 | * @return string Generated entity query PHP class code |
||
| 220 | */ |
||
| 221 | protected function createEntityClass(Metadata $metadata) |
||
| 222 | { |
||
| 223 | $this->generator |
||
| 224 | ->multiComment(array('"'.$metadata->entityRealName.'" entity class')) |
||
| 225 | ->defClass($metadata->entity, null !== $metadata->parent ? $metadata->parent->className : 'Entity') |
||
| 226 | ->commentVar('string', '@deprecated Entity full class name, use ::class') |
||
| 227 | ->defClassConst('ENTITY', $metadata->className) |
||
| 228 | ->commentVar('string', 'Entity manager full class name') |
||
| 229 | ->defClassConst('MANAGER', $metadata->className.'Query') |
||
| 230 | ->commentVar('string', 'Entity database identifier') |
||
| 231 | ->defClassConst('IDENTIFIER', $metadata->entityID) |
||
| 232 | ->commentVar('string', 'Not transliterated entity name') |
||
| 233 | ->defClassVar('$viewName', 'protected static', $metadata->entityRealName); |
||
| 234 | |||
| 235 | foreach ($metadata->allFieldIDs as $fieldID => $fieldName) { |
||
| 236 | $this->generator |
||
| 237 | ->commentVar('string', $metadata->fieldDescriptions[$fieldID].' variable name') |
||
| 238 | ->defClassConst('F_' . $fieldName, $fieldName) |
||
| 239 | ->commentVar($metadata->allFieldTypes[$fieldID], $metadata->fieldDescriptions[$fieldID]) |
||
| 240 | ->defClassVar('$' . $fieldName, 'public'); |
||
| 241 | } |
||
| 242 | |||
| 243 | return $this->generator |
||
| 244 | ->defClassVar('$_sql_select', 'public static ', $metadata->arSelect) |
||
| 245 | ->defClassVar('$_attributes', 'public static ', $metadata->arAttributes) |
||
| 246 | ->defClassVar('$_map', 'public static ', $metadata->arMap) |
||
| 247 | ->defClassVar('$_sql_from', 'public static ', $metadata->arFrom) |
||
| 248 | ->defClassVar('$_own_group', 'public static ', $metadata->arGroup) |
||
| 249 | ->defClassVar('$_relation_alias', 'public static ', $metadata->arRelationAlias) |
||
| 250 | ->defClassVar('$_relation_type', 'public static ', $metadata->arRelationType) |
||
| 251 | ->defClassVar('$_relations', 'public static ', $metadata->arRelations) |
||
| 252 | ->endclass() |
||
| 253 | ->flush(); |
||
| 254 | } |
||
| 255 | |||
| 256 | /** |
||
| 257 | * Generate FieldsTable::values() analog for specific field. |
||
| 258 | * |
||
| 259 | * @param string $fieldName Field name |
||
| 260 | * @param string $fieldId Field primary identifier |
||
| 261 | * @param string $fieldType Field PHP type |
||
| 262 | * @return string Generated PHP method code |
||
| 263 | */ |
||
| 264 | protected function generateTableFieldMethod($fieldName, $fieldId, $fieldType) |
||
| 265 | { |
||
| 266 | $code = "\n\t" . '/**'; |
||
| 267 | $code .= "\n\t" . ' * Get table column '.$fieldName.'(#' . $fieldId . ') values.'; |
||
| 268 | $code .= "\n\t" . ' * @return array Collection('.Field::phpType($fieldType).') of table column values'; |
||
| 269 | $code .= "\n\t" . ' */'; |
||
| 270 | $code .= "\n\t" . 'public function ' . $fieldName . '()'; |
||
| 271 | $code .= "\n\t" . "{"; |
||
| 272 | $code .= "\n\t\t" . 'return $this->values('.$fieldId.');'; |
||
| 273 | |||
| 274 | return $code . "\n\t" . "}"."\n"; |
||
| 275 | } |
||
| 276 | |||
| 277 | /** |
||
| 278 | * Create fields table row PHP class code. |
||
| 279 | * |
||
| 280 | * @param string $navigationName Original entity name |
||
| 281 | * @param string $entityName PHP entity name |
||
| 282 | * @param array $navigationFields Collection of entity additional fields |
||
| 283 | * @return string Generated entity query PHP class code |
||
| 284 | */ |
||
| 285 | protected function createTableRowClass($navigationName, $entityName, $navigationFields) |
||
| 286 | { |
||
| 287 | $class = "\n"; |
||
| 288 | $class .= "\n" . '/**'; |
||
| 289 | $class .= "\n" . ' * Class for getting "'.$navigationName.'" fields table rows'; |
||
| 290 | $class .= "\n" . ' */'; |
||
| 291 | $class .= "\n" . 'class ' . $entityName . ' extends Row'; |
||
| 292 | $class .= "\n" . '{'; |
||
| 293 | |||
| 294 | // Iterate additional fields |
||
| 295 | $constants = ''; |
||
| 296 | $variables = ''; |
||
| 297 | foreach ($navigationFields as $fieldID => $fieldRow) { |
||
| 298 | $fieldName = $this->fieldName($fieldRow['Name']); |
||
| 299 | |||
| 300 | $constants .= "\n\t" . '/** ' . Field::phpType($fieldRow['Type']) . ' '.$fieldRow['Description'].' Field #' . $fieldID . ' variable name */'; |
||
| 301 | // Store original field name |
||
| 302 | $constants .= "\n\t" . 'const F_' . strtoupper($fieldName) . ' = "'.$fieldName.'";'; |
||
| 303 | |||
| 304 | $variables .= "\n\t" . '/** ' . Field::phpType($fieldRow['Type']) . ' '.$fieldRow['Description'].' Field #' . $fieldID . ' row value */'; |
||
| 305 | $variables .= "\n\t" . 'public $' . $fieldName . ';'; |
||
| 306 | } |
||
| 307 | |||
| 308 | $class .= $constants; |
||
| 309 | $class .= "\n\t"; |
||
| 310 | $class .= $variables; |
||
| 311 | $class .= "\n" . '}'; |
||
| 312 | |||
| 313 | return $class; |
||
| 314 | } |
||
| 315 | |||
| 316 | /** |
||
| 317 | * Create fields table PHP class code. |
||
| 318 | * |
||
| 319 | * @param integer $navigationID Entity navigation identifier |
||
| 320 | * @param string $navigationName Original entity name |
||
| 321 | * @param string $entityName PHP entity name |
||
| 322 | * @param array $navigationFields Collection of entity additional fields |
||
| 323 | * @param string $rowClassName Row class name |
||
| 324 | * |
||
| 325 | * @return string Generated entity query PHP class code |
||
| 326 | * @throws exception\AdditionalFieldTypeNotFound |
||
| 327 | */ |
||
| 328 | protected function createTableClass($navigationID, $navigationName, $entityName, $navigationFields, $rowClassName) |
||
| 329 | { |
||
| 330 | $this->generator |
||
| 331 | ->multiComment(array('Class for getting "'.$navigationName.'" fields table')) |
||
| 332 | ->defClass($entityName, 'FieldsTable'); |
||
| 333 | |||
| 334 | // Iterate additional fields |
||
| 335 | $fields = array(); |
||
| 336 | foreach ($navigationFields as $fieldID => $fieldRow) { |
||
| 337 | $fieldName = $this->fieldName($fieldRow['Name']); |
||
| 338 | |||
| 339 | $this->generator |
||
| 340 | ->text($this->generateTableFieldMethod( |
||
| 341 | $fieldName, |
||
| 342 | $fieldRow[Field::F_PRIMARY], |
||
| 343 | $fieldRow[Field::F_TYPE] |
||
| 344 | )) |
||
| 345 | ->commentVar(Field::phpType($fieldRow['Type']), $fieldRow['Description'] . ' Field #' . $fieldID . ' variable name') |
||
| 346 | ->defClassConst('F_' . $fieldName, $fieldName); |
||
| 347 | |||
| 348 | // Collection original to new one field names |
||
| 349 | $fields[$fieldRow['Name']] = $fieldName; |
||
| 350 | } |
||
| 351 | |||
| 352 | // TODO: Add generator method generation logic |
||
| 353 | $class = "\n\t".'/**'; |
||
| 354 | $class .= "\n\t".' * @param QueryInterface $query Database query instance'; |
||
| 355 | $class .= "\n\t".' * @param ViewInterface $renderer Rendering instance'; |
||
| 356 | $class .= "\n\t".' * @param integer $entityID Entity identifier to whom this table belongs'; |
||
| 357 | $class .= "\n\t".' * @param string $locale Localization identifier'; |
||
| 358 | $class .= "\n\t".' */'; |
||
| 359 | $class .= "\n\t".'public function __construct(QueryInterface $query, ViewInterface $renderer, $entityID, $locale = null)'; |
||
| 360 | $class .= "\n\t".'{'; |
||
| 361 | $class .= "\n\t\t".'parent::__construct($query, $renderer, static::$navigationIDs, $entityID, $locale);'; |
||
| 362 | $class .= "\n\t".'}'."\n"; |
||
| 363 | |||
| 364 | $this->generator->text($class); |
||
| 365 | |||
| 366 | return $this->generator |
||
| 367 | ->commentVar('array', 'Collection of real additional field names') |
||
| 368 | ->defClassVar('$fieldsRealNames', 'public static', $fields) |
||
| 369 | ->commentVar('array', 'Collection of navigation identifiers') |
||
| 370 | ->defClassVar('$navigationIDs', 'protected static', array($navigationID)) |
||
| 371 | ->commentVar('string', 'Row class name') |
||
| 372 | ->defClassVar('$identifier', 'protected', $this->fullEntityName($rowClassName)) |
||
| 373 | ->endClass() |
||
| 374 | ->flush(); |
||
| 375 | } |
||
| 376 | |||
| 377 | /** |
||
| 378 | * Create entity query PHP class code. |
||
| 379 | * |
||
| 380 | * @param integer $navigationID Entity navigation identifier |
||
| 381 | * @param string $navigationName Original entity name |
||
| 382 | * @param string $entityName PHP entity name |
||
| 383 | * @param array $navigationFields Collection of entity additional fields |
||
| 384 | * @param string $parentClass Parent entity class name |
||
| 385 | * @return string Generated entity query PHP class code |
||
| 386 | */ |
||
| 387 | View Code Duplication | protected function createCollectionClass($navigationID, $navigationName, $entityName, $navigationFields, $parentClass = '\samsoncms\api\renderable\Collection') |
|
| 388 | { |
||
| 389 | $this->generator |
||
| 390 | ->multiComment(array('Class for getting "'.$navigationName.'" instances from database',)) |
||
| 391 | ->defClass($entityName, $parentClass) |
||
| 392 | ; |
||
| 393 | |||
| 394 | // Iterate additional fields |
||
| 395 | $localizedFieldIDs = array(); |
||
| 396 | $notLocalizedFieldIDs = array(); |
||
| 397 | $allFieldIDs = array(); |
||
| 398 | $allFieldNames = array(); |
||
| 399 | $allFieldValueColumns = array(); |
||
| 400 | $realNames = array(); |
||
| 401 | foreach ($navigationFields as $fieldID => $fieldRow) { |
||
| 402 | $fieldName = $this->fieldName($fieldRow['Name']); |
||
| 403 | |||
| 404 | // TODO: Add different method generation depending on their field type |
||
| 405 | $this->generator->text($this->generateFieldConditionMethod( |
||
| 406 | $fieldName, |
||
| 407 | $fieldRow[Field::F_PRIMARY], |
||
| 408 | $fieldRow[Field::F_TYPE] |
||
| 409 | )); |
||
| 410 | |||
| 411 | // Store field metadata |
||
| 412 | $realNames[$fieldRow['Name']] = $fieldName; |
||
| 413 | $allFieldIDs[$fieldID] = $fieldName; |
||
| 414 | $allFieldNames[$fieldName] = $fieldID; |
||
| 415 | $allFieldValueColumns[$fieldID] = Field::valueColumn($fieldRow[Field::F_TYPE]); |
||
| 416 | if ($fieldRow[Field::F_LOCALIZED] == 1) { |
||
| 417 | $localizedFieldIDs[$fieldID] = $fieldName; |
||
| 418 | } else { |
||
| 419 | $notLocalizedFieldIDs[$fieldID] = $fieldName; |
||
| 420 | } |
||
| 421 | } |
||
| 422 | |||
| 423 | // TODO: Add generator method generation logic |
||
| 424 | $class = "\n\t".'/**'; |
||
| 425 | $class .= "\n\t".' * @param ViewInterface $renderer Rendering instance'; |
||
| 426 | $class .= "\n\t".' * @param QueryInterface $query Querying instance'; |
||
| 427 | $class .= "\n\t".' * @param string $locale Localization identifier'; |
||
| 428 | $class .= "\n\t".' */'; |
||
| 429 | $class .= "\n\t".'public function __construct(ViewInterface $renderer, QueryInterface $query = null, $locale = null)'; |
||
| 430 | $class .= "\n\t".'{'; |
||
| 431 | $class .= "\n\t\t".'parent::__construct($renderer, $query === null ? new dbQuery() : $query, $locale);'; |
||
| 432 | $class .= "\n\t".'}'."\n"; |
||
| 433 | |||
| 434 | return $this->generator |
||
| 435 | ->commentVar('array', 'Collection of real additional field names') |
||
| 436 | ->defClassVar('$fieldRealNames', 'public static', $realNames) |
||
| 437 | ->commentVar('array', 'Collection of navigation identifiers') |
||
| 438 | ->defClassVar('$navigationIDs', 'protected static', array($navigationID)) |
||
| 439 | ->commentVar('string', 'Not transliterated entity name') |
||
| 440 | ->defClassVar('$identifier', 'protected static', $this->fullEntityName($navigationName)) |
||
| 441 | ->commentVar('array', 'Collection of localized additional fields identifiers') |
||
| 442 | ->defClassVar('$localizedFieldIDs', 'protected static', $localizedFieldIDs) |
||
| 443 | ->commentVar('array', 'Collection of NOT localized additional fields identifiers') |
||
| 444 | ->defClassVar('$notLocalizedFieldIDs', 'protected static', $notLocalizedFieldIDs) |
||
| 445 | ->commentVar('array', 'Collection of localized additional fields identifiers') |
||
| 446 | ->defClassVar('$fieldIDs', 'protected static', $allFieldIDs) |
||
| 447 | ->commentVar('array', 'Collection of additional fields value column names') |
||
| 448 | ->defClassVar('$fieldValueColumns', 'protected static', $allFieldValueColumns) |
||
| 449 | ->commentVar('array', 'Collection of additional field names') |
||
| 450 | ->defClassVar('$fieldNames', 'public static', $allFieldNames) |
||
| 451 | ->text($class) |
||
| 452 | ->endClass() |
||
| 453 | ->flush() |
||
| 454 | ; |
||
| 455 | } |
||
| 456 | |||
| 457 | /** |
||
| 458 | * Create entity query PHP class code. |
||
| 459 | * |
||
| 460 | * @param integer $navigationID Entity navigation identifier |
||
| 461 | * @param string $navigationName Original entity name |
||
| 462 | * @param string $entityName PHP entity name |
||
| 463 | * @param array $navigationFields Collection of entity additional fields |
||
| 464 | * @param string $parentClass Parent entity class name |
||
| 465 | * @return string Generated entity query PHP class code |
||
| 466 | */ |
||
| 467 | View Code Duplication | protected function createQueryClass($navigationID, $navigationName, $entityName, $navigationFields, $parentClass = '\samsoncms\api\query\Entity') |
|
| 468 | { |
||
| 469 | $this->generator |
||
| 470 | ->multiComment(array('Class for getting "'.$navigationName.'" instances from database')) |
||
| 471 | ->defClass($entityName, $parentClass) |
||
| 472 | ; |
||
| 473 | |||
| 474 | // Iterate additional fields |
||
| 475 | $localizedFieldIDs = array(); |
||
| 476 | $notLocalizedFieldIDs = array(); |
||
| 477 | $allFieldIDs = array(); |
||
| 478 | $allFieldNames = array(); |
||
| 479 | $allFieldValueColumns = array(); |
||
| 480 | $realNames = array(); |
||
| 481 | foreach ($navigationFields as $fieldID => $fieldRow) { |
||
| 482 | $fieldName = $this->fieldName($fieldRow['Name']); |
||
| 483 | |||
| 484 | // TODO: Add different method generation depending on their field type |
||
| 485 | $this->generator->text($this->generateFieldConditionMethod( |
||
| 486 | $fieldName, |
||
| 487 | $fieldRow[Field::F_PRIMARY], |
||
| 488 | $fieldRow[Field::F_TYPE] |
||
| 489 | )); |
||
| 490 | |||
| 491 | // Store field metadata |
||
| 492 | $realNames[$fieldRow['Name']] = $fieldName; |
||
| 493 | $allFieldIDs[$fieldID] = $fieldName; |
||
| 494 | $allFieldNames[$fieldName] = $fieldID; |
||
| 495 | $allFieldValueColumns[$fieldID] = Field::valueColumn($fieldRow[Field::F_TYPE]); |
||
| 496 | if ($fieldRow[Field::F_LOCALIZED] == 1) { |
||
| 497 | $localizedFieldIDs[$fieldID] = $fieldName; |
||
| 498 | } else { |
||
| 499 | $notLocalizedFieldIDs[$fieldID] = $fieldName; |
||
| 500 | } |
||
| 501 | } |
||
| 502 | |||
| 503 | // TODO: Add generator method generation logic |
||
| 504 | $class = "\n\t".'/**'; |
||
| 505 | $class .= "\n\t".' * @param QueryInterface $query Rendering instance'; |
||
| 506 | $class .= "\n\t".' * @param string $locale Localization identifier'; |
||
| 507 | $class .= "\n\t".' */'; |
||
| 508 | $class .= "\n\t".'public function __construct(QueryInterface $query = null, $locale = null)'; |
||
| 509 | $class .= "\n\t".'{'; |
||
| 510 | $class .= "\n\t\t".'parent::__construct($query === null ? new dbQuery() : $query, $locale);'; |
||
| 511 | $class .= "\n\t".'}'."\n"; |
||
| 512 | |||
| 513 | return $this->generator |
||
| 514 | ->commentVar('array', 'Collection of real additional field names') |
||
| 515 | ->defClassVar('$fieldRealNames', 'public static', $realNames) |
||
| 516 | ->commentVar('array', 'Collection of navigation identifiers') |
||
| 517 | ->defClassVar('$navigationIDs', 'protected static', array($navigationID)) |
||
| 518 | ->commentVar('string', 'Not transliterated entity name') |
||
| 519 | ->defClassVar('$identifier', 'protected static', $this->fullEntityName($navigationName)) |
||
| 520 | ->commentVar('array', 'Collection of localized additional fields identifiers') |
||
| 521 | ->defClassVar('$localizedFieldIDs', 'protected static', $localizedFieldIDs) |
||
| 522 | ->commentVar('array', 'Collection of NOT localized additional fields identifiers') |
||
| 523 | ->defClassVar('$notLocalizedFieldIDs', 'protected static', $notLocalizedFieldIDs) |
||
| 524 | ->commentVar('array', 'Collection of localized additional fields identifiers') |
||
| 525 | ->defClassVar('$fieldIDs', 'protected static', $allFieldIDs) |
||
| 526 | ->commentVar('array', 'Collection of additional fields value column names') |
||
| 527 | ->defClassVar('$fieldValueColumns', 'protected static', $allFieldValueColumns) |
||
| 528 | ->commentVar('array', 'Collection of additional field names') |
||
| 529 | ->defClassVar('$fieldNames', 'public static', $allFieldNames) |
||
| 530 | ->text($class) |
||
| 531 | ->endClass() |
||
| 532 | ->flush() |
||
| 533 | ; |
||
| 534 | } |
||
| 535 | |||
| 536 | /** @return string Entity state hash */ |
||
| 537 | public function entityHash() |
||
| 538 | { |
||
| 539 | // Получим информацию о всех таблицах из БД |
||
| 540 | return md5(serialize($this->database->fetch( |
||
| 541 | 'SELECT `TABLES`.`TABLE_NAME` as `TABLE_NAME` |
||
| 542 | FROM `information_schema`.`TABLES` as `TABLES` |
||
| 543 | WHERE `TABLES`.`TABLE_SCHEMA`="' . $this->database->database() . '";' |
||
| 544 | ))); |
||
| 545 | } |
||
| 546 | |||
| 547 | /** |
||
| 548 | * Find entity parent. |
||
| 549 | * |
||
| 550 | * @param $entityID |
||
| 551 | * |
||
| 552 | * @return null|int Parent entity identifier |
||
| 553 | */ |
||
| 554 | public function entityParent($entityID) |
||
| 555 | { |
||
| 556 | $parentData = $this->database->fetch(' |
||
| 557 | SELECT * |
||
| 558 | FROM structure_relation as sm |
||
| 559 | JOIN structure as s ON s.StructureID = sm.parent_id |
||
| 560 | WHERE sm.child_id = "' . $entityID . '" |
||
| 561 | AND s.StructureID != "' . $entityID . '" |
||
| 562 | '); |
||
| 563 | |||
| 564 | // Get parent entity identifier |
||
| 565 | return count($parentData) ? $parentData[0]['StructureID'] : null; |
||
| 566 | } |
||
| 567 | |||
| 568 | /** @return array Get collection of navigation objects */ |
||
| 569 | protected function entityNavigations($type = 0) |
||
| 570 | { |
||
| 571 | return $this->database->fetch(' |
||
| 572 | SELECT * FROM `structure` |
||
| 573 | WHERE `Active` = "1" AND `Type` = "'.$type.'" |
||
| 574 | ORDER BY `ParentID` ASC |
||
| 575 | '); |
||
| 576 | } |
||
| 577 | |||
| 578 | /** @return array Collection of navigation additional fields */ |
||
| 579 | protected function navigationFields($navigationID) |
||
| 591 | |||
| 592 | /** |
||
| 593 | * Generate entity classes. |
||
| 594 | * |
||
| 595 | * @param string $namespace Base namespace for generated classes |
||
| 596 | * @return string Generated PHP code for entity classes |
||
| 597 | */ |
||
| 598 | public function createEntityClasses($namespace = __NAMESPACE__) |
||
| 599 | { |
||
| 600 | $classes = "\n" . 'namespace ' . $namespace . ';'; |
||
| 601 | $classes .= "\n"; |
||
| 602 | $classes .= "\n" . 'use '.$namespace.'\renderable\FieldsTable;'; |
||
| 603 | $classes .= "\n" . 'use '.$namespace.'\field\Row;'; |
||
| 604 | $classes .= "\n" . 'use \samsonframework\core\ViewInterface;'; |
||
| 605 | $classes .= "\n" . 'use \samsonframework\orm\ArgumentInterface;'; |
||
| 606 | $classes .= "\n" . 'use \samsonframework\orm\QueryInterface;'; |
||
| 607 | $classes .= "\n" . 'use \samson\activerecord\dbQuery;'; |
||
| 608 | $classes .= "\n"; |
||
| 609 | |||
| 736 | |||
| 737 | /** |
||
| 738 | * Generator constructor. |
||
| 739 | * @param DatabaseInterface $database Database instance |
||
| 740 | */ |
||
| 741 | public function __construct(DatabaseInterface $database) |
||
| 746 | } |
||
| 747 | |||
| 749 |
This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.
Both the
$myVarassignment in line 1 and the$higherassignment in line 2 are dead. The first because$myVaris never used and the second because$higheris always overwritten for every possible time line.