These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more
1 | <?php |
||
2 | |||
3 | /* |
||
4 | * This file is part of the puli/repository package. |
||
5 | * |
||
6 | * (c) Bernhard Schussek <[email protected]> |
||
7 | * |
||
8 | * For the full copyright and license information, please view the LICENSE |
||
9 | * file that was distributed with this source code. |
||
10 | */ |
||
11 | |||
12 | namespace Puli\Repository; |
||
13 | |||
14 | use Puli\Repository\Api\EditableRepository; |
||
15 | use Puli\Repository\Api\Resource\FilesystemResource; |
||
16 | use Webmozart\Glob\Glob; |
||
17 | use Webmozart\PathUtil\Path; |
||
18 | |||
19 | /** |
||
20 | * A repository backed by a JSON file optimized for reading. |
||
21 | * |
||
22 | * The generated JSON file is described by res/schema/repository-schema-1.0.json. |
||
23 | * |
||
24 | * Resources can be added with the method {@link add()}: |
||
25 | * |
||
26 | * ```php |
||
27 | * use Puli\Repository\OptimizedJsonRepository; |
||
28 | * |
||
29 | * $repo = new OptimizedJsonRepository('/path/to/repository.json', '/path/to/project'); |
||
30 | * $repo->add('/css', new DirectoryResource('/path/to/project/res/css')); |
||
31 | * ``` |
||
32 | * |
||
33 | * When adding a resource, the added filesystem path is stored in the JSON file |
||
34 | * under the key of the Puli path. The path is stored relatively to the base |
||
35 | * directory passed to the constructor. Directories will be expanded and all |
||
36 | * nested files will be added to the mapping file as well: |
||
37 | * |
||
38 | * ```json |
||
39 | * { |
||
40 | * "/css": "res/css", |
||
41 | * "/css/style.css": "res/css/style.css" |
||
42 | * } |
||
43 | * ``` |
||
44 | * |
||
45 | * Mapped resources can be read with the method {@link get()}: |
||
46 | * |
||
47 | * ```php |
||
48 | * $cssPath = $repo->get('/css')->getFilesystemPath(); |
||
49 | * ``` |
||
50 | * |
||
51 | * You can also access nested files: |
||
52 | * |
||
53 | * ```php |
||
54 | * echo $repo->get('/css/style.css')->getBody(); |
||
55 | * ``` |
||
56 | * |
||
57 | * Since nested files are searched during {@link add()} and added to the JSON |
||
58 | * file, this repository does not detect any files that you add to a directory |
||
59 | * after adding that directory to the repository. This means that accessing |
||
60 | * files is very fast, but also that the usage of this repository implementation |
||
61 | * can be cumbersome in development environments. There you are recommended to |
||
62 | * use {@link JsonRepository} instead. |
||
63 | * |
||
64 | * @since 1.0 |
||
65 | * |
||
66 | * @author Bernhard Schussek <[email protected]> |
||
67 | * @author Titouan Galopin <[email protected]> |
||
68 | */ |
||
69 | class OptimizedJsonRepository extends AbstractJsonRepository implements EditableRepository |
||
70 | { |
||
71 | /** |
||
72 | * {@inheritdoc} |
||
73 | */ |
||
74 | 6 | public function clear() |
|
75 | { |
||
76 | 6 | if (null === $this->json) { |
|
77 | 2 | $this->load(); |
|
78 | } |
||
79 | |||
80 | // Subtract root which is not deleted |
||
81 | 6 | $removed = count($this->json) - 1; |
|
82 | |||
83 | 6 | $this->json = array(); |
|
84 | |||
85 | 6 | $this->flush(); |
|
86 | |||
87 | 6 | $this->clearVersions(); |
|
88 | 6 | $this->storeVersion($this->get('/')); |
|
89 | |||
90 | 6 | return $removed; |
|
91 | } |
||
92 | |||
93 | /** |
||
94 | * {@inheritdoc} |
||
95 | */ |
||
96 | 166 | protected function insertReference($path, $reference) |
|
97 | { |
||
98 | 166 | $this->json[$path] = $reference; |
|
99 | 166 | } |
|
100 | |||
101 | /** |
||
102 | * {@inheritdoc} |
||
103 | */ |
||
104 | 20 | protected function removeReferences($glob) |
|
105 | { |
||
106 | 20 | $removed = 0; |
|
107 | |||
108 | 20 | foreach ($this->getReferencesForGlob($glob.'{,/**/*}') as $path => $reference) { |
|
109 | 20 | ++$removed; |
|
110 | |||
111 | 20 | $this->removeVersions($path); |
|
112 | |||
113 | 20 | unset($this->json[$path]); |
|
114 | } |
||
115 | |||
116 | 20 | return $removed; |
|
117 | } |
||
118 | |||
119 | /** |
||
120 | * {@inheritdoc} |
||
121 | */ |
||
122 | 108 | protected function getReferencesForPath($path) |
|
123 | { |
||
124 | 108 | if (!array_key_exists($path, $this->json)) { |
|
125 | 26 | return array(); |
|
126 | } |
||
127 | |||
128 | 100 | $reference = $this->json[$path]; |
|
129 | |||
130 | // We're only interested in the first entry of eventual arrays |
||
131 | 100 | if (is_array($reference)) { |
|
132 | $reference = reset($reference); |
||
133 | } |
||
134 | |||
135 | 100 | View Code Duplication | if ($this->isFilesystemReference($reference)) { |
0 ignored issues
–
show
|
|||
136 | 90 | $absoluteReference = Path::makeAbsolute($reference, $this->baseDirectory); |
|
137 | |||
138 | 90 | if (!file_exists($absoluteReference)) { |
|
139 | 2 | $this->logReferenceNotFound($path, $reference, $absoluteReference); |
|
140 | |||
141 | 2 | return array(); |
|
142 | } |
||
143 | |||
144 | 88 | $reference = $absoluteReference; |
|
145 | } |
||
146 | |||
147 | 98 | return array($path => $reference); |
|
148 | } |
||
149 | |||
150 | /** |
||
151 | * {@inheritdoc} |
||
152 | */ |
||
153 | 48 | View Code Duplication | protected function getReferencesForGlob($glob, $flags = 0) |
0 ignored issues
–
show
This method seems to be duplicated in your project.
Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation. You can also find more detailed suggestions in the “Code” section of your repository.
Loading history...
|
|||
154 | { |
||
155 | 48 | if (!Glob::isDynamic($glob)) { |
|
156 | 26 | return $this->getReferencesForPath($glob); |
|
157 | } |
||
158 | |||
159 | 36 | return $this->getReferencesForRegex( |
|
160 | 36 | Glob::getStaticPrefix($glob), |
|
161 | 36 | Glob::toRegEx($glob), |
|
162 | $flags |
||
163 | ); |
||
164 | } |
||
165 | |||
166 | /** |
||
167 | * {@inheritdoc} |
||
168 | */ |
||
169 | 62 | protected function getReferencesForRegex($staticPrefix, $regex, $flags = 0) |
|
170 | { |
||
171 | 62 | $result = array(); |
|
172 | 62 | $foundMappingsWithPrefix = false; |
|
173 | |||
174 | 62 | foreach ($this->json as $path => $reference) { |
|
175 | 62 | if (0 === strpos($path, $staticPrefix)) { |
|
176 | 54 | $foundMappingsWithPrefix = true; |
|
177 | |||
178 | 54 | if (!preg_match($regex, $path)) { |
|
179 | 16 | continue; |
|
180 | } |
||
181 | |||
182 | // We're only interested in the first entry of eventual arrays |
||
183 | 52 | if (is_array($reference)) { |
|
184 | $reference = reset($reference); |
||
185 | } |
||
186 | |||
187 | 52 | View Code Duplication | if ($this->isFilesystemReference($reference)) { |
0 ignored issues
–
show
This code seems to be duplicated across your project.
Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation. You can also find more detailed suggestions in the “Code” section of your repository.
Loading history...
|
|||
188 | 52 | $absoluteReference = Path::makeAbsolute($reference, $this->baseDirectory); |
|
189 | |||
190 | 52 | if (!file_exists($absoluteReference)) { |
|
191 | 8 | $this->logReferenceNotFound($path, $reference, $absoluteReference); |
|
192 | |||
193 | 8 | continue; |
|
194 | } |
||
195 | |||
196 | 44 | $reference = $absoluteReference; |
|
197 | } |
||
198 | |||
199 | 44 | $result[$path] = $reference; |
|
200 | |||
201 | 44 | if ($flags & self::STOP_ON_FIRST) { |
|
202 | 8 | return $result; |
|
203 | } |
||
204 | |||
205 | 38 | continue; |
|
206 | } |
||
207 | |||
208 | // We did not find anything but previously found mappings with the |
||
209 | // static prefix |
||
210 | // The mappings are sorted alphabetically, so we can safely abort |
||
211 | 56 | if ($foundMappingsWithPrefix) { |
|
212 | 56 | break; |
|
213 | } |
||
214 | } |
||
215 | |||
216 | 60 | return $result; |
|
217 | } |
||
218 | |||
219 | /** |
||
220 | * {@inheritdoc} |
||
221 | */ |
||
222 | 26 | View Code Duplication | protected function getReferencesInDirectory($path, $flags = 0) |
0 ignored issues
–
show
This method seems to be duplicated in your project.
Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation. You can also find more detailed suggestions in the “Code” section of your repository.
Loading history...
|
|||
223 | { |
||
224 | 26 | $basePath = rtrim($path, '/'); |
|
225 | |||
226 | 26 | return $this->getReferencesForRegex( |
|
227 | 26 | $basePath.'/', |
|
228 | 26 | '~^'.preg_quote($basePath, '~').'/[^/]+$~', |
|
229 | $flags |
||
230 | ); |
||
231 | } |
||
232 | |||
233 | /** |
||
234 | * {@inheritdoc} |
||
235 | */ |
||
236 | 166 | protected function addFilesystemResource($path, FilesystemResource $resource) |
|
237 | { |
||
238 | // Read children before attaching the resource to this repository |
||
239 | 166 | $children = $resource->listChildren(); |
|
240 | |||
241 | 166 | parent::addFilesystemResource($path, $resource); |
|
242 | |||
243 | // Recursively add all child resources |
||
244 | 166 | $basePath = '/' === $path ? $path : $path.'/'; |
|
245 | |||
246 | 166 | foreach ($children as $name => $child) { |
|
247 | 72 | $this->addFilesystemResource($basePath.$name, $child); |
|
248 | } |
||
249 | 166 | } |
|
250 | } |
||
251 |
Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.
You can also find more detailed suggestions in the “Code” section of your repository.