Passed
Push — master ( b2175e...d070b7 )
by Julius
02:17
created

ApiDocBuilder::buildNamespaceIndexes()   B

Complexity

Conditions 3
Paths 4

Size

Total Lines 38
Code Lines 26

Duplication

Lines 10
Ratio 26.32 %

Importance

Changes 0
Metric Value
cc 3
eloc 26
nc 4
nop 1
dl 10
loc 38
rs 8.8571
c 0
b 0
f 0

1 Method

Rating   Name   Duplication   Size   Complexity  
A ApiDocBuilder::buildToc() 0 19 2
1
<?php
2
/**
3
 * @copyright Copyright (c) 2017 Julius Härtl <[email protected]>
4
 *
5
 * @author Julius Härtl <[email protected]>
6
 *
7
 * @license GNU AGPL version 3 or any later version
8
 *
9
 *  This program is free software: you can redistribute it and/or modify
10
 *  it under the terms of the GNU Affero General Public License as
11
 *  published by the Free Software Foundation, either version 3 of the
12
 *  License, or (at your option) any later version.
13
 *
14
 *  This program is distributed in the hope that it will be useful,
15
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
16
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17
 *  GNU Affero General Public License for more details.
18
 *
19
 *  You should have received a copy of the GNU Affero General Public License
20
 *  along with this program. If not, see <http://www.gnu.org/licenses/>.
21
 *
22
 */
23
24
namespace JuliusHaertl\PHPDocToRst;
25
26
use phpDocumentor\Reflection\File\LocalFile;
27
use phpDocumentor\Reflection\Php\Namespace_;
28
use phpDocumentor\Reflection\Php\Project;
29
use phpDocumentor\Reflection\Php\ProjectFactory;
30
use JuliusHaertl\PHPDocToRst\Builder\MainIndexBuilder;
31
use JuliusHaertl\PHPDocToRst\Builder\NamespaceIndexBuilder;
32
use JuliusHaertl\PHPDocToRst\Extension\Extension;
33
use JuliusHaertl\PHPDocToRst\Builder\ClassBuilder;
34
use JuliusHaertl\PHPDocToRst\Builder\InterfaceBuilder;
35
36
class ApiDocBuilder {
37
38
    /** @var Project */
39
    private $project;
40
    /** @var array */
41
    private $docFiles = [];
42
    /** @var Extension[] */
43
    private $extensions;
44
    /** @var string|string[] */
45
    private $srcDir;
46
    /** @var string */
47
    private $dstDir;
48
49
50
    public function __construct($srcDir, $dstDir) {
51
        $this->dstDir = $dstDir;
52
        $this->srcDir = $srcDir;
53
        $this->setupReflection();
54
    }
55
56
    public function build() {
57
        $this->createDirectoryStructure();
58
        $this->parseFiles();
59
        $this->buildToc();
60
    }
61
62
    /**
63
     * @throws \Exception
64
     */
65
    private function setupReflection() {
66
        if (!is_array($this->srcDir)) {
67
            $this->srcDir = [$this->srcDir];
68
        }
69
        $interfaceList = [];
70
71
        foreach ($this->srcDir as $srcDir) {
72
            $dir = new \RecursiveDirectoryIterator($srcDir);
73
            $files = new \RecursiveIteratorIterator($dir);
74
75
            foreach ($files as $file) {
76
                if ($file->isDir()) continue;
77
                try {
78
                    $interfaceList[] = new LocalFile($file->getPathname());
79
                } catch (\Exception $e) {
80
                    echo "Failed to load " . $file->getPathname() . "\n";
81
                }
82
            }
83
        }
84
85
        $projectFactory = ProjectFactory::createInstance();
86
        $this->project = $projectFactory->create('MyProject', $interfaceList);
87
    }
88
89
    /**
90
     * @param string $class name of the extension class
91
     * @throws \Exception
92
     */
93
    public function addExtension($class) {
94
        $extension = new $class($this->project);
95
        if (!is_subclass_of($extension, Extension::class)) {
96
            throw new \Exception('Extension must be an instance of JuliusHaertl\PHPDocToRst\Extension\Extension');
97
        }
98
        $this->extensions[] = $extension;
99
    }
100
101
    /**
102
     * Create directory structure for the rst output
103
     */
104
    public function createDirectoryStructure() {
105
        foreach ($this->project->getNamespaces() as $namespace) {
106
            $namespaceDir = $this->dstDir . str_replace("\\", "/", $namespace->getFqsen());
107
            if (is_dir($namespaceDir))
108
                continue;
109
            if (!mkdir($namespaceDir, 0755, true)) {
110
                throw new \Exception('Could not create directory '. $namespaceDir);
111
            }
112
        }
113
    }
114
115
    public function parseFiles() {
116
        /** @var Extension $extension */
117
        foreach ($this->extensions as $extension) {
118
            $extension->prepare();
119
        }
120
        foreach ($this->project->getFiles() as $file) {
121
            /**
122
             * Go though interfaces/classes/functions of files and build documentation
123
             */
124
            foreach ($file->getInterfaces() as $interface) {
125
                $builder = new InterfaceBuilder($file, $interface, $this->extensions);
126
                $filename = $this->dstDir . str_replace("\\", "/", $interface->getFqsen()) . '.rst';
127
                file_put_contents($filename, $builder->getContent());
128
                $this->docFiles[(string)$interface->getFqsen()] = str_replace("\\", "/", $interface->getFqsen());
129
            }
130
131
            foreach ($file->getClasses() as $class) {
132
                $builder = new ClassBuilder($file, $class, $this->extensions);
133
                $filename = $this->dstDir . str_replace("\\", "/", $class->getFqsen()) . '.rst';
134
                file_put_contents($filename, $builder->getContent());
135
                $this->docFiles[(string)$class->getFqsen()] = str_replace("\\", "/", $class->getFqsen());
136
137
                // also build root namespace
138
                if (strpos((string)substr($class->getFqsen(), 1), '\\') === false) {
139
                    $this->project->getRootNamespace()->addClass($class->getFqsen());
140
                }
141
            }
142
143
            // FIXME: traits
144
145
        }
146
    }
147
148
    public function buildToc() {
149
        $namespaces = $this->project->getNamespaces();
150
        $namespaces['\\'] = $this->project->getRootNamespace();
151
        usort($namespaces, function (Namespace_ $a, Namespace_ $b) {
152
            return strcmp($a->getFqsen(), $b->getFqsen());
153
        });
154
        /** @var Namespace_ $namespace */
155
        foreach ($namespaces as $namespace) {
156
            $builder = new NamespaceIndexBuilder($namespaces, $namespace);
157
            $builder->render();
158
            $path = $this->dstDir . str_replace("\\", "/", $namespace->getFqsen()) . '/index.rst';
159
            echo $path . PHP_EOL;
160
            file_put_contents($path, $builder->getContent());
161
        }
162
163
        $builder = new MainIndexBuilder($namespaces);
164
        $builder->render();
165
        $path = $this->dstDir . '/index-namespaces-all.rst';
166
        file_put_contents($path, $builder->getContent());
167
    }
168
}
169