/** * [generateClassType description]. * * @param string $properties elementi possibili 'fields', 'extend', 'implements' * @param array $typesReference [description] * @param array $typesDescription [description] * @param ClassConfig $config [description] */ public function generateClassType(array $properties, $typesReference, $typesDescription, ClassConfig $config) { $phpNamespace = $this->currentClass->getNamespace(); if ($config->isInterface) { $this->info('Passo a interfaccia', [$this->currentClass->getName()]); $docs = $this->currentClass->getComment(); $this->currentClass = $this->currentFile->addInterface($phpNamespace->getName() . '\\' . ucfirst($this->currentClass->getName())); $this->currentClass->setComment($docs); $this->info('Check haveConstructor, in caso metto a false', [$config->haveConstructor]); $config->haveConstructor = false; } $this->info('Generate', ['class' => $this->currentClass->getName(), 'namespace' => $phpNamespace->getName(), 'comment' => $this->currentClass->getComment(), 'properties' => $properties]); // extend class if (array_key_exists('extend', $properties)) { $extendClassName = $properties['extend']; $this->info('Aggiungo extend', ['class' => $this->currentClass->getName(), 'extend' => $extendClassName]); $this->currentClass->setExtends($extendClassName); $this->currentClass->getNamespace()->addUse($extendClassName); } // implements class if (array_key_exists('implements', $properties)) { $implementsList = []; if (!is_array($properties['implements'])) { $implementsList[] = $properties['implements']; } else { $implementsList = array_merge($implementsList, $properties['implements']); } $this->currentClass->setImplements($implementsList); foreach ($implementsList as $implementUse) { $this->info('Aggiungo implement', ['class' => $this->currentClass->getName(), 'implements' => $implementUse]); $this->currentClass->getNamespace()->addUse($implementUse); } } // traits if (array_key_exists('traits', $properties)) { if (is_array($properties['traits'])) { foreach ($properties['traits'] as $trait) { $this->addTrait($trait, $typesReference); } } else { $traitObject = $properties['traits']; $this->addTrait($traitObject, $typesReference); } } if ($config->isFinalClass) { $this->currentClass->setFinal(true); } $first = true; if (array_key_exists('fields', $properties)) { /** @var $methodConstructor \Nette\PhpGenerator\Method */ $methodConstructor = null; if ($config->haveConstructor) { $methodConstructor = $this->addConstructor(); } $body = ''; foreach ($properties['fields'] as $name => $fieldProperties) { $isStatic = false; $isAutoinizialize = false; $defaultValue = null; if (array_key_exists('static', $fieldProperties)) { $isStatic = $fieldProperties['static']; } if (array_key_exists('autoinizialize', $fieldProperties)) { $isAutoinizialize = boolval($fieldProperties['autoinizialize']); } if (array_key_exists('default', $fieldProperties)) { $defaultValue = $fieldProperties['default']; } if (!$isAutoinizialize) { if (null != $defaultValue) { //TODO: usare "primitive type per determinare il corretto IF" //FARE UN TEST PER I BOOLEAN //@see https://www.virendrachandak.com/techtalk/php-isset-vs-empty-vs-is_null/ $body .= 'if ( empty($' . $name . ') ) { ' . "\n"; if ($isStatic) { $body .= ' self::$'; } else { $body .= ' $this->'; } $body .= $name . ' = ' . $defaultValue . ';' . "\n"; $body .= '} else {'; if ($isStatic) { $body .= ' self::$'; } else { $body .= ' $this->'; } $body .= $name . ' = $' . $name . ';' . "\n"; $body .= '}' . "\n"; } else { if (!$isStatic) { $body .= ' $this->' . $name . ' = $' . $name . ';' . "\n"; } } } else { if (!empty($defaultValue) || is_int($defaultValue)) { if (substr(rtrim($defaultValue), -1) == ';') { $this->error('autoinizialize for ' . $name . ' on class ' . $this->currentClass->getName() . ' have default with ";" please remove!'); $defaultValue = substr($defaultValue, 0, strlen($defaultValue) - 1); } if (!$isStatic) { if ($isAutoinizialize) { $body .= '// autoinizialize' . "\n"; $body .= '$this->' . $name . ' = ' . $defaultValue . ';' . "\n"; } else { if ($defaultValue) { $body .= 'if ( !is_null($' . $name . ') ) {' . "\n"; $body .= ' $this->' . $name . ' = $' . $name . ';' . "\n"; $body .= '} else {' . "\n"; $body .= ' $this->' . $name . ' = ' . $defaultValue . ';' . "\n"; $body .= '}' . "\n"; // $body .= '$this->'.$name.' = '.$defaultValue.';'."\n"; } else { $body .= 'if ( is_null($' . $name . ') ) {' . "\n"; $body .= ' $this->' . $name . ' = ' . $defaultValue . ';' . "\n"; $body .= '}' . "\n"; } } } } else { $this->error('autoinizialize for ' . $name . ' not defined on element ' . $this->currentClass->getName()); $this->errors[] = 'autoinizialize for ' . $name . ' not defined on element ' . $this->currentClass->getName(); } } $fieldClassFull = ''; if (array_key_exists('class', $fieldProperties)) { $fieldClassName = ucfirst($fieldProperties['class']); if (array_key_exists($fieldClassName, $typesReference)) { $fieldNamespace = $typesReference[$fieldClassName]; $fieldClassFull = $fieldNamespace . '\\' . $fieldClassName; $this->info('Trovato field namespace tra le reference', ['class' => $this->currentClass->getName(), 'field' => $fieldClassName, 'className' => $fieldClassFull]); } else { //FIXME: strpos is better if ($fieldClassName[0] == '\\') { //Class: \DateTime $fieldClassFull = $fieldClassName; } else { $fieldClassFull = $phpNamespace->getName() . '\\' . $fieldClassName; $this->info('Uso class for field same namespace', ['class' => $this->currentClass->getName(), 'field' => $fieldClassName, 'className' => $fieldClassFull]); } } if ($config->haveConstructor && !$isStatic) { $parameter = null; if (!$isAutoinizialize) { $this->info('Aggiungo parametro al costruttore', ['class' => $this->currentClass->getName(), 'parameter' => $name, 'className' => $fieldClassFull, 'default' => $defaultValue, 'autoinizialize' => $isAutoinizialize]); if (!$first) { $parameter = $methodConstructor->addParameter($name, null); //solo i primitivi hanno un default, gli altri null come object $parameter->setTypeHint($fieldClassFull); } else { $parameter = $methodConstructor->addParameter($name); $parameter->setTypeHint($fieldClassFull); } } else { $this->info('Skip parametro al costruttore -> autoinizialize true', ['class' => $this->currentClass->getName(), 'parameter' => $name, 'className' => $fieldClassFull, 'default' => $defaultValue, 'autoinizialize' => $isAutoinizialize]); } } if (array_key_exists($fieldClassName, $typesReference)) { $this->info('Add field type class with namespace', ['class' => $this->currentClass->getName(), 'field' => $fieldClassName, 'className' => $fieldClassFull]); $this->currentClass->getNamespace()->addUse($fieldClassFull); } } else { //tipo primitivo $fieldClassName = $fieldProperties['primitive']; $fieldNamespace = null; $fieldClassFull = $fieldProperties['primitive']; if ($config->haveConstructor && !$isStatic) { //FIXME: se sono in php7 ho anche gli altri elementi primitivi //@see: http://php.net/manual/en/functions.arguments.php#functions.arguments.type-declaration $parameter = null; if (!$isAutoinizialize) { if (is_null($defaultValue)) { $this->info('Aggiungo parametro al costruttore', ['class' => $this->currentClass->getName(), 'parameter' => $name, 'className' => $fieldClassFull, 'default' => $defaultValue, 'autoinizialize' => $isAutoinizialize]); //PHP7 ONLY // if ($fieldClassFull == 'int') { // $parameter->setTypeHint('int'); // } if (!$first) { $parameter = $methodConstructor->addParameter($name, null); } else { $parameter = $methodConstructor->addParameter($name); } if ($fieldClassFull == 'array') { $parameter->setTypeHint('array'); } else { if ($defaultValue != null) { /* @var $parameter \Nette\PhpGenerator\Parameter */ $parameter->setDefaultValue('' . $defaultValue); } } } } } } $this->info('Check autoinizialize field', ['class' => $this->currentClass->getName(), 'field' => $name, 'autoinizialize' => $isAutoinizialize, 'default' => $defaultValue]); $comment = 'no description available'; if (array_key_exists('description', $fieldProperties)) { $comment = $fieldProperties['description']; } else { if (!is_null($typesDescription) && array_key_exists($fieldClassName, $typesDescription)) { $comment = $typesDescription[$fieldClassName]; } } if (!$config->isInterface) { /** $field @var \Nette\PhpGenerator\Property */ $field = $this->currentClass->addProperty($name); $field->setStatic($isStatic); if ($config->isEnum) { $field->setVisibility('protected'); } else { $field->setVisibility('private'); } $field->addComment($comment)->addComment('@var ' . $fieldClassFull); } $createSetter = $config->haveSetter; if (array_key_exists('setter', $fieldProperties)) { $createSetter = $fieldProperties['setter']; } $createGetter = $config->haveGetter; if (array_key_exists('getter', $fieldProperties)) { $createGetter = $fieldProperties['getter']; } if ($config->isInterface) { if ($createGetter) { $this->addGetter($name, $fieldClassFull, $isStatic, false); } if ($createSetter) { $this->addSetter($name, $fieldClassFull, $isStatic, false); } } else { if ($createGetter) { $this->addGetter($name, $fieldClassFull, $isStatic, true); } if ($createSetter) { $this->addSetter($name, $fieldClassFull, $isStatic, true); } } if (!$isAutoinizialize) { $first = false; } } if ($config->haveConstructor) { $methodConstructor->setBody($body, []); } } //end fields if (array_key_exists('methods', $properties)) { $body = ''; foreach ($properties['methods'] as $methodName => $methodsProperties) { $this->info('Aggiungo method', ['class' => $this->currentClass->getName(), 'methodName' => $methodName, 'methodProp' => $methodsProperties]); /** $newMethodCall @var \Nette\PhpGenerator\Method */ $newMethodCall = $this->currentClass->addMethod($methodName); $newMethodCall->setFinal(true); $newMethodCall->setStatic(false); if (array_key_exists('static', $methodsProperties)) { $newMethodCall->setStatic($methodsProperties['static']); } if (array_key_exists('description', $methodsProperties)) { $newMethodCall->setVisibility($methodsProperties['visibility']); } else { $newMethodCall->setVisibility('public'); } if (array_key_exists('description', $methodsProperties)) { $newMethodCall->addComment($methodsProperties['description']); } else { $returnType = 'void'; if (array_key_exists('@return', $methodsProperties)) { $returnType = $methodsProperties['@return']; //TODO: .'|null' va messo in quale condizione? $newMethodCall->addComment('@return ' . $returnType); } else { //NOPE } } if (array_key_exists('params', $methodsProperties)) { foreach ($methodsProperties['params'] as $paramName => $paramProp) { if (array_key_exists('class', $paramProp)) { $newMethodCall->addParameter($paramName)->setTypeHint($paramProp['class']); } if (array_key_exists('primitive', $paramProp)) { $newMethodCall->addParameter($paramName); } } } $body = ' // FIMXE: da implementare '; if (array_key_exists('body', $methodsProperties)) { $body = $methodsProperties['body']; } $newMethodCall->setBody($body); } } if ($config->isEnum) { $this->currentClass->setAbstract(true); $this->addSingleton('Singleton instance for enum', false); $this->addParseString(); } if ($config->isSingleton) { $this->addSingleton('Singleton instance', true); } }