An error occurred while loading the file. Please try again.
-
Guillaume Perréal authored0168fd0c
<?php declare(strict_types=1);
/*
* This file is part of "irstea/ng-model-generator-bundle".
*
* "irstea/ng-model-generator-bundle" generates Typescript interfaces for Angular using api-platform metadata.
* Copyright (C) 2018-2019 IRSTEA
*
* This program is free software: you can redistribute it and/or modify it under
* the terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
* PARTICULAR PURPOSE. See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License and the GNU
* Lesser General Public License along with this program. If not, see
* <https://www.gnu.org/licenses/>.
*/
namespace Irstea\NgModelGeneratorBundle\Models;
use Irstea\NgModelGeneratorBundle\Exceptions\DomainException;
use Irstea\NgModelGeneratorBundle\Metadata\PropertyMetadata;
/**
* Class ClassInfo.
*/
final class ClassInfo implements ClassName
{
public const UNDEFINED = 'UNDEFINED';
public const IRI = 'IRI';
public const UNION = 'UNION';
public const INTERFACE = 'INTERFACE';
/** @var ClassName */
private $class;
/** @var self|false|null */
private $parent = false;
/** @var PropertyMetadata[] */
private $virtualProperties = [];
/** @var PropertyMetadata[] */
private $concreteProperties = [];
/** @var self[] */
private $children = [];
/** @var string */
private $type = self::UNDEFINED;
/** @var bool */
private $abstract;
/** @var bool */
private $resource;
/**
* ClassInfo constructor.
*
* @param ClassName $class
* @param PropertyMetadata[] $properties
* @param bool $abstract
* @param bool $resource
*/
public function __construct(ClassName $class, array $properties = [], bool $abstract = false, bool $resource = false)
{
7172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140
$this->class = $class;
$this->abstract = $abstract;
foreach ($properties as $property) {
$this->virtualProperties[$property->getName()] = $property;
}
$this->concreteProperties = $abstract ? [] : $this->virtualProperties;
$this->resource = $resource;
}
/**
* {@inheritdoc}
*/
public function getNamespace(): string
{
return $this->class->getNamespace();
}
/**
* {@inheritdoc}
*/
public function getBaseName(): string
{
return $this->class->getBaseName();
}
/**
* {@inheritdoc}
*/
public function getFullName(): string
{
return $this->class->getFullName();
}
/**
* Get properties.
*
* @return PropertyMetadata[]
*/
public function getVirtualProperties(): array
{
return $this->virtualProperties;
}
/**
* Get properties.
*
* @return PropertyMetadata[]
*/
public function getConcreteProperties(): array
{
return $this->concreteProperties;
}
/**
* Get abstract.
*
* @return bool
*/
public function isAbstract(): bool
{
return $this->abstract;
}
/**
* Get resource.
*
* @return bool
*/
public function isResource(): bool
141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210
{
return $this->resource;
}
/**
* Get parent.
*
* @return ClassInfo|null
*/
public function getParent(): ?ClassInfo
{
return $this->parent ?: null;
}
/**
* Set parent.
*
* @param ClassInfo|null $parent
*/
public function setParent(?ClassInfo $parent): void
{
if ($parent === $this->parent) {
return;
}
if ($parent === $this) {
throw new DomainException('A class cannot be its own parent');
}
if ($this->parent !== false) {
throw new DomainException('Can only set parent once');
}
$this->parent = $parent;
if ($parent) {
$parent->addChild($this);
}
}
/**
* Get children.
*
* @return ClassInfo[]
*/
public function getChildren(): array
{
return $this->children;
}
/**
* @param ClassInfo $child
*
* @SuppressWarnings(PHPMD.UnusedPrivateMethod)
*/
private function addChild(ClassInfo $child): void
{
if (\in_array($child, $this->children, true)) {
return;
}
$this->children[] = $child;
$child->setParent($this);
}
/**
* Test type.
*
* @param string $type
*
* @return bool
*/
public function isType(string $type): bool
{
return $this->type === $type;
211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280
}
/**
* @return bool
*/
public function isInterface(): bool
{
return $this->isType(self::INTERFACE);
}
/**
* @return bool
*/
public function isUnion(): bool
{
return $this->isType(self::UNION);
}
/**
* @return bool
*/
public function isUndefined(): bool
{
return $this->isType(self::UNDEFINED);
}
/**
* @return bool
*/
public function isIRI(): bool
{
return $this->isType(self::IRI);
}
/**
* {@inheritdoc}
*/
public function jsonSerialize()
{
return [
'class' => $this->class->getFullName(),
'type' => $this->type,
'abstract' => $this->abstract,
'parent' => $this->parent ? $this->parent->getFullName() : null,
'children' => array_map(
function (ClassInfo $ci) {
return $ci->getFullName();
},
$this->children
),
'virtualProperties' => $this->virtualProperties,
'concreteProperties' => $this->concreteProperties,
];
}
/**
* @return self[]|\Generator
*/
public function iterateConcreteDescendants(): \Generator
{
if (!$this->abstract) {
yield $this;
}
foreach ($this->children as $child) {
yield from $child->iterateConcreteDescendants();
}
}
/**
* @return self[]|\Generator
281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350
*/
public function iterateInterfaceDescendants(): \Generator
{
if ($this->isInterface()) {
yield $this;
}
foreach ($this->children as $child) {
yield from $child->iterateInterfaceDescendants();
}
}
/**
* @return string
*/
public function __toString()
{
return $this->getFullName();
}
/**
* Fait remonter les propriétés communes des sous-classes.
*/
public function rearrangeHiearchy(): void
{
if ($this->parent) {
return;
}
$this->bubbleUpProperties();
$this->sinkDownProperties();
}
private function bubbleUpProperties(): void
{
if (!$this->children) {
return;
}
$classProperties = [];
if (!$this->abstract) {
$classProperties[] = $this->virtualProperties;
}
foreach ($this->children as $child) {
$child->bubbleUpProperties();
$classProperties[] = $child->virtualProperties;
}
switch (\count($classProperties)) {
case 0:
return;
case 1:
$commonProperties = array_shift($classProperties);
break;
default:
$commonProperties = array_intersect_key(...$classProperties);
}
if (!$commonProperties) {
return;
}
$this->virtualProperties = array_replace($this->virtualProperties, $commonProperties);
}
/**
* @return bool
*/
private function sinkDownProperties(): bool
{
if ($this->parent) {
$this->virtualProperties = array_replace($this->parent->virtualProperties, $this->virtualProperties);