/**
* [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);
}
}