• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

michalsn / codeigniter-markdown-pages / 6865294866

14 Nov 2023 02:49PM UTC coverage: 98.343%. First build
6865294866

push

github

michalsn
make classes API more consistent

25 of 26 new or added lines in 3 files covered. (96.15%)

178 of 181 relevant lines covered (98.34%)

11.16 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

97.33
/src/MarkdownPages.php
1
<?php
2

3
namespace Michalsn\CodeIgniterMarkdownPages;
4

5
use Michalsn\CodeIgniterMarkdownPages\Config\MarkdownPages as MarkdownPagesConfig;
6
use Michalsn\CodeIgniterMarkdownPages\Exceptions\MarkdownPagesException;
7
use Michalsn\CodeIgniterMarkdownPages\Pages\Dir;
8
use Michalsn\CodeIgniterMarkdownPages\Pages\File;
9
use Michalsn\CodeIgniterMarkdownPages\Search\Result;
10
use Michalsn\CodeIgniterMarkdownPages\Search\Results;
11
use Mni\FrontYAML\Parser;
12
use Myth\Collection\Collection;
13
use RecursiveDirectoryIterator;
14
use RecursiveIteratorIterator;
15

16
class MarkdownPages
17
{
18
    protected Collection $pages;
19
    protected int|array|null $depth     = null;
20
    protected string|array|null $parent = null;
21

22
    public function __construct(string $folderPath, protected MarkdownPagesConfig $config)
23
    {
24
        if (! file_exists($folderPath) || ! is_dir($folderPath)) {
24✔
25
            throw MarkdownPagesException::forIncorrectFolderPath();
1✔
26
        }
27

28
        // Parser
29
        $parser = new Parser(
23✔
30
            $config->yamlParser !== null ? new $config->yamlParser() : null,
23✔
31
            $config->markdownParser !== null ? new $config->markdownParser() : null
23✔
32
        );
23✔
33

34
        // Prepare folders and files
35
        $this->pages = new Collection([]);
23✔
36

37
        $iterator = new RecursiveIteratorIterator(
23✔
38
            new RecursiveDirectoryIterator($folderPath, RecursiveDirectoryIterator::SKIP_DOTS),
23✔
39
            RecursiveIteratorIterator::SELF_FIRST
23✔
40
        );
23✔
41

42
        foreach ($iterator as $file) {
23✔
43
            $subPath = $iterator->getSubPath();
23✔
44

45
            if ($file->isFile() && $subPath !== '') {
23✔
46
                continue;
23✔
47
            }
48

49
            $fileName = $file->getFilename();
23✔
50

51
            if ($file->isDir()) {
23✔
52
                $folder = $subPath === '' ? $fileName : $subPath . '/' . $fileName;
23✔
53
            } else {
54
                $folder = $subPath;
23✔
55
            }
56

57
            $this->pages->push(new Dir($folder, $folderPath, $config->fileExtension, $parser));
23✔
58
        }
59

60
        // Sort
61
        $this->pages = $this->pages->sort(static fn ($dir) => $dir->getDirName());
23✔
62
        $this->pages->each(static fn ($dir) => $dir->getFiles()->sort(static fn ($file) => $file->getFileName()));
23✔
63
    }
64

65
    /**
66
     * Prefilter folder depth.
67
     */
68
    public function depth(int|array $depth): static
69
    {
70
        $this->depth = $depth;
3✔
71

72
        return $this;
3✔
73
    }
74

75
    /**
76
     * Prefilter folder parent path.
77
     */
78
    public function parent(string|array $parent): static
79
    {
80
        $this->parent = $parent;
4✔
81

82
        return $this;
4✔
83
    }
84

85
    /**
86
     * Get dir based on value.
87
     */
88
    public function dir(string|array $path): ?Dir
89
    {
90
        $dirs = $this->dirs($path);
8✔
91

92
        if ($dirs->isEmpty()) {
8✔
93
            return null;
1✔
94
        }
95

96
        return $dirs->slice(0, 1)->first();
7✔
97
    }
98

99
    /**
100
     * Get dirs based on value.
101
     */
102
    public function dirs(string|array|null $path = null): Collection
103
    {
104
        $depth  = $this->depth;
22✔
105
        $parent = $this->parent;
22✔
106

107
        if ($path === null && $depth === null && $parent === null) {
22✔
108
            return $this->pages;
4✔
109
        }
110

111
        $collection = $this->pages->filter(static function ($item) use ($path, $depth, $parent) {
18✔
112
            if ($depth !== null && (is_array($depth) ?
18✔
113
                ! in_array($item->getDepth(), $depth, true) :
1✔
114
                $item->getDepth() > $depth)) {
18✔
115
                return false;
3✔
116
            }
117

118
            if ($parent !== null) {
18✔
119
                if (is_array($parent) && ! in_array($item->getParent(), $parent, true)) {
4✔
120
                    return false;
1✔
121
                }
122

123
                if (is_string($parent)) {
4✔
124
                    if (str_contains($parent, '*')) {
3✔
125
                        if (! str_starts_with((string) $item->getParent(), rtrim($parent, '*'))) {
1✔
126
                            return false;
1✔
127
                        }
128
                    } elseif ($item->getParent() !== $parent) {
2✔
129
                        return false;
2✔
130
                    }
131
                }
132
            }
133

134
            if ($path === null) {
18✔
135
                return true;
6✔
136
            }
137

138
            if (is_array($path)) {
12✔
139
                return in_array($item->getPath(), $path, true);
2✔
140
            }
141

142
            if (str_contains($path, '*')) {
10✔
143
                return str_starts_with((string) $item->getPath(), rtrim($path, '*'));
3✔
144
            }
145

146
            return $item->getPath() === $path;
7✔
147
        });
18✔
148

149
        // Reset options
150
        $this->resetOptions();
18✔
151

152
        return $collection;
18✔
153
    }
154

155
    /**
156
     * Get file based on value.
157
     */
158
    public function file(string $path): ?File
159
    {
160
        $segments = explode('/', $path);
4✔
161

162
        if (count($segments) === 1) {
4✔
NEW
163
            $dirPath = '';
×
164
        } else {
165
            $path    = array_pop($segments);
4✔
166
            $dirPath = implode('/', $segments);
4✔
167
        }
168

169
        if (! $dir = $this->dir($dirPath)) {
4✔
170
            return null;
×
171
        }
172

173
        return $dir->getFiles()->find(static fn ($item) => $item->getSlug() === $path);
4✔
174
    }
175

176
    /**
177
     * Search through the files.
178
     */
179
    public function search(string $query, string|array|null $path = null, array $metaKeys = []): Results
180
    {
181
        $search = new Results($query);
3✔
182

183
        foreach ($this->dirs($path)->items() as $dir) {
3✔
184
            foreach ($dir->getFiles()->items() as $file) {
3✔
185
                // Search content
186
                $score = $file->search($query, $metaKeys);
3✔
187
                if ($score > 0) {
3✔
188
                    $search->getResults()->push(new Result($file, $score));
2✔
189
                }
190
            }
191
        }
192

193
        return $search->sortByScore();
3✔
194
    }
195

196
    /**
197
     * Reset search dirs option.
198
     */
199
    protected function resetOptions(): void
200
    {
201
        $this->depth  = null;
18✔
202
        $this->parent = null;
18✔
203
    }
204
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc