Reference.php 3.56 KB
Newer Older
1
2
<?php declare(strict_types=1);
/*
Guillaume Perréal's avatar
Guillaume Perréal committed
3
4
5
 * This file is part of "irstea/ng-model-generator-bundle".
 *
 * "irstea/ng-model-generator-bundle" generates Typescript interfaces for Angular using api-platform metadata.
Guillaume Perréal's avatar
CS.    
Guillaume Perréal committed
6
 * Copyright (C) 2018-2019 IRSTEA
7
8
9
10
11
12
13
14
15
16
17
18
19
 *
 * 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/>.
20
21
 */

Guillaume Perréal's avatar
Guillaume Perréal committed
22
namespace Irstea\NgModelGeneratorBundle\Models\Types;
23
24

/**
Guillaume Perréal's avatar
Guillaume Perréal committed
25
 * Class Ref.
26
 */
27
class Reference extends AbstractType implements Deferred
28
{
29
30
31
32
    private const UNRESOLVED = 0;
    private const RESOLVING = 1;
    private const RESOLVED = 2;

33
34
    /** @var Type */
    private $target;
Guillaume Perréal's avatar
Guillaume Perréal committed
35

36
37
38
39
40
41
    /** @var string */
    private $name;

    /** @var bool */
    private $state = self::UNRESOLVED;

42
    /**
Guillaume Perréal's avatar
Guillaume Perréal committed
43
44
     * Reference constructor.
     *
45
     * @param string $name
46
     */
47
    public function __construct(string $name = 'anonymous reference')
48
    {
49
50
        $this->name = $name;
        $this->target = Unresolved::get();
51
52
53
54
55
56
57
58
59
60
61
62
63
    }

    /**
     * Get target.
     *
     * @return Type
     */
    public function getTarget(): Type
    {
        return $this->target;
    }

    /**
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
     * {@inheritdoc}
     */
    public function resolveWith(callable $callback): Type
    {
        switch ($this->state) {
            case self::UNRESOLVED:
                $this->state = self::RESOLVING;

                return $this->resolve($callback());
            case self::RESOLVING:
                return $this;
            case self::RESOLVED:
                return $this->target;
        }
    }

    /**
     * {@inheritdoc}
82
     */
83
    public function resolve(Type $result): Type
84
    {
85
86
87
88
89
90
        if ($this->state !== self::RESOLVED) {
            $this->state = self::RESOLVED;
            $this->target = $result;
        }

        return $this->target;
91
92
93
94
95
    }

    /**
     * {@inheritdoc}
     */
96
    private function dereference(): Type
97
    {
98
        return $this->target instanceof Reference ? $this->target->dereference() : $this->target;
Guillaume Perréal's avatar
Guillaume Perréal committed
99
100
101
102
103
104
105
    }

    /**
     * {@inheritdoc}
     */
    public function getUsage(): string
    {
106
107
108
        return $this->dereference()->getUsage();
    }

109
110
111
112
113
114
115
116
117
118
119
    /**
     * {@inheritdoc}
     */
    public function castToStringOrStringArray(string $expr): string
    {
        return $this->dereference()->castToStringOrStringArray($expr);
    }

    /**
     * {@inheritdoc}
     */
120
    public function checkType(string $expr, bool $explicit = false): string
121
    {
122
        return $this->dereference()->checkType($expr, $explicit);
123
124
    }

125
126
127
128
129
130
    /**
     * {@inheritdoc}
     */
    public function getIterator()
    {
        yield $this->target;
131
    }
132

133
134
135
136
137
    /**
     * @return mixed
     */
    public function jsonSerialize()
    {
138
        return \spl_object_hash($this);
139
140
    }

141
142
143
144
145
    /**
     * {@inheritdoc}
     */
    public function __toString()
    {
146
        return '&' . $this->name;
147
    }
148
149

    /**
150
     * {@inheritdoc}
151
     */
152
    public function findType(string $typeClass): ?Type
153
    {
154
        return parent::findType($typeClass) ?: $this->target->findType($typeClass);
155
    }
156
}