1<?php declare(strict_types=1);
2
3namespace PhpParser\Builder;
4
5use PhpParser;
6use PhpParser\BuilderHelpers;
7use PhpParser\Node\Name;
8use PhpParser\Node\Stmt;
9
10class Class_ extends Declaration
11{
12    protected $name;
13
14    protected $extends = null;
15    protected $implements = [];
16    protected $flags = 0;
17
18    protected $uses = [];
19    protected $constants = [];
20    protected $properties = [];
21    protected $methods = [];
22
23    /**
24     * Creates a class builder.
25     *
26     * @param string $name Name of the class
27     */
28    public function __construct(string $name) {
29        $this->name = $name;
30    }
31
32    /**
33     * Extends a class.
34     *
35     * @param Name|string $class Name of class to extend
36     *
37     * @return $this The builder instance (for fluid interface)
38     */
39    public function extend($class) {
40        $this->extends = BuilderHelpers::normalizeName($class);
41
42        return $this;
43    }
44
45    /**
46     * Implements one or more interfaces.
47     *
48     * @param Name|string ...$interfaces Names of interfaces to implement
49     *
50     * @return $this The builder instance (for fluid interface)
51     */
52    public function implement(...$interfaces) {
53        foreach ($interfaces as $interface) {
54            $this->implements[] = BuilderHelpers::normalizeName($interface);
55        }
56
57        return $this;
58    }
59
60    /**
61     * Makes the class abstract.
62     *
63     * @return $this The builder instance (for fluid interface)
64     */
65    public function makeAbstract() {
66        $this->flags = BuilderHelpers::addModifier($this->flags, Stmt\Class_::MODIFIER_ABSTRACT);
67
68        return $this;
69    }
70
71    /**
72     * Makes the class final.
73     *
74     * @return $this The builder instance (for fluid interface)
75     */
76    public function makeFinal() {
77        $this->flags = BuilderHelpers::addModifier($this->flags, Stmt\Class_::MODIFIER_FINAL);
78
79        return $this;
80    }
81
82    /**
83     * Adds a statement.
84     *
85     * @param Stmt|PhpParser\Builder $stmt The statement to add
86     *
87     * @return $this The builder instance (for fluid interface)
88     */
89    public function addStmt($stmt) {
90        $stmt = BuilderHelpers::normalizeNode($stmt);
91
92        $targets = [
93            Stmt\TraitUse::class    => &$this->uses,
94            Stmt\ClassConst::class  => &$this->constants,
95            Stmt\Property::class    => &$this->properties,
96            Stmt\ClassMethod::class => &$this->methods,
97        ];
98
99        $class = \get_class($stmt);
100        if (!isset($targets[$class])) {
101            throw new \LogicException(sprintf('Unexpected node of type "%s"', $stmt->getType()));
102        }
103
104        $targets[$class][] = $stmt;
105
106        return $this;
107    }
108
109    /**
110     * Returns the built class node.
111     *
112     * @return Stmt\Class_ The built class node
113     */
114    public function getNode() : PhpParser\Node {
115        return new Stmt\Class_($this->name, [
116            'flags' => $this->flags,
117            'extends' => $this->extends,
118            'implements' => $this->implements,
119            'stmts' => array_merge($this->uses, $this->constants, $this->properties, $this->methods),
120        ], $this->attributes);
121    }
122}
123