[TASK] Use Environment API in documentation extension
[Packages/TYPO3.CMS.git] / typo3 / sysext / documentation / Classes / Domain / Repository / DocumentRepository.php
1 <?php
2 namespace TYPO3\CMS\Documentation\Domain\Repository;
3
4 /*
5 * This file is part of the TYPO3 CMS project.
6 *
7 * It is free software; you can redistribute it and/or modify it under
8 * the terms of the GNU General Public License, either version 2
9 * of the License, or any later version.
10 *
11 * For the full copyright and license information, please read the
12 * LICENSE.txt file that was distributed with this source code.
13 *
14 * The TYPO3 project - inspiring people to share!
15 */
16
17 use TYPO3\CMS\Core\Core\Environment;
18 use TYPO3\CMS\Core\Localization\Locales;
19 use TYPO3\CMS\Core\Utility\ExtensionManagementUtility;
20 use TYPO3\CMS\Core\Utility\GeneralUtility;
21 use TYPO3\CMS\Core\Utility\PathUtility;
22 use TYPO3\CMS\Documentation\Domain\Model\Document;
23 use TYPO3\CMS\Documentation\Domain\Model\DocumentFormat;
24 use TYPO3\CMS\Documentation\Domain\Model\DocumentTranslation;
25 use TYPO3\CMS\Documentation\Utility\MiscUtility;
26 use TYPO3\CMS\Extbase\Object\ObjectManagerInterface;
27 use TYPO3\CMS\Extbase\Persistence\ObjectStorage;
28
29 /**
30 * An extension helper repository to be used in ext:documentation context
31 */
32 class DocumentRepository
33 {
34 /**
35 * @var \TYPO3\CMS\Extbase\Object\ObjectManagerInterface
36 */
37 protected $objectManager;
38
39 /**
40 * @param \TYPO3\CMS\Extbase\Object\ObjectManagerInterface $objectManager
41 */
42 public function injectObjectManager(ObjectManagerInterface $objectManager)
43 {
44 $this->objectManager = $objectManager;
45 }
46
47 /**
48 * Finds all documents.
49 *
50 * @return \TYPO3\CMS\Documentation\Domain\Model\Document[]
51 */
52 public function findAll()
53 {
54 $documents = $this->findSphinxDocuments();
55 $openOfficeDocuments = $this->findOpenOfficeDocuments();
56
57 // Add OpenOffice documents if there is not already an existing, non OpenOffice version
58 foreach ($openOfficeDocuments as $documentKey => $document) {
59 if (!isset($documents[$documentKey])) {
60 $documents[$documentKey] = $document;
61 }
62 }
63
64 return $documents;
65 }
66
67 /**
68 * Finds documents by language, always falls back to 'default' (English).
69 *
70 * @param string $language
71 * @return \TYPO3\CMS\Documentation\Domain\Model\Document[]
72 */
73 public function findByLanguage($language)
74 {
75 $allDocuments = $this->findAll();
76
77 // Initialize the dependency of languages
78 $languageDependencies = [];
79 /** @var $locales \TYPO3\CMS\Core\Localization\Locales */
80 $locales = GeneralUtility::makeInstance(Locales::class);
81 // Language is found. Configure it:
82 $shortLanguage = $language;
83 if (!in_array($shortLanguage, $locales->getLocales()) && strpos($shortLanguage, '_') !== false) {
84 list($shortLanguage, $_) = explode('_', $shortLanguage);
85 }
86 if (in_array($shortLanguage, $locales->getLocales())) {
87 $languageDependencies[] = $language;
88 if ($language !== $shortLanguage) {
89 $languageDependencies[] = $shortLanguage;
90 }
91 foreach ($locales->getLocaleDependencies($shortLanguage) as $languageDependency) {
92 $languageDependencies[] = $languageDependency;
93 }
94 }
95 if ($language !== 'default') {
96 $languageDependencies[] = 'default';
97 }
98
99 foreach ($allDocuments as $document) {
100 // Remove every unwanted translation
101 $selectedTranslation = null;
102 $highestPriorityLanguageIndex = count($languageDependencies);
103
104 $translations = $document->getTranslations();
105 foreach ($translations as $translation) {
106 $languageIndex = array_search($translation->getLanguage(), $languageDependencies);
107 if ($languageIndex !== false) {
108 if ($languageIndex < $highestPriorityLanguageIndex) {
109 $selectedTranslation = $translation;
110 $highestPriorityLanguageIndex = $languageIndex;
111 }
112 } else {
113 // No exact translation found, perhaps another locale would fit as well. E.g., when requesting
114 // a documentation as fr_CA but only fr_FR exists
115 if (strpos($translation->getLanguage(), '_') !== false) {
116 list($translationLanguage, $_) = explode('_', $translation->getLanguage());
117 $languageIndex = array_search($translationLanguage, $languageDependencies);
118 if ($languageIndex !== false && $languageIndex < $highestPriorityLanguageIndex) {
119 $selectedTranslation = $translation;
120 $highestPriorityLanguageIndex = $languageIndex;
121 }
122 }
123 }
124 }
125
126 $newTranslations = new ObjectStorage();
127 $document->setTranslations($newTranslations);
128 if ($selectedTranslation !== null) {
129 $document->addTranslation($selectedTranslation);
130 }
131 }
132
133 return $allDocuments;
134 }
135
136 /**
137 * Retrieves Sphinx documents.
138 *
139 * @return array
140 */
141 protected function findSphinxDocuments()
142 {
143 $basePath = 'typo3conf/Documentation/';
144
145 $documents = [];
146 $documentKeys = GeneralUtility::get_dirs(Environment::getPublicPath() . '/' . $basePath);
147 // Early return in case no document keys were found
148 if (!is_array($documentKeys)) {
149 return $documents;
150 }
151
152 foreach ($documentKeys as $documentKey) {
153 $icon = MiscUtility::getIcon($documentKey);
154
155 /** @var \TYPO3\CMS\Documentation\Domain\Model\Document $document */
156 $document = $this->objectManager->get(Document::class)
157 ->setPackageKey($documentKey)
158 ->setIcon($icon);
159
160 $languagePath = $basePath . $documentKey . '/';
161 $languages = GeneralUtility::get_dirs(Environment::getPublicPath() . '/' . $languagePath);
162 foreach ($languages as $language) {
163 $metadata = $this->getMetadata($documentKey, $language);
164 if (!empty($metadata['extensionKey'])) {
165 $document->setExtensionKey($metadata['extensionKey']);
166 }
167
168 /** @var \TYPO3\CMS\Documentation\Domain\Model\DocumentTranslation $documentTranslation */
169 $documentTranslation = $this->objectManager->get(DocumentTranslation::class)
170 ->setLanguage($language)
171 ->setTitle($metadata['title'])
172 ->setDescription($metadata['description']);
173
174 $formatPath = $languagePath . $language . '/';
175 $formats = GeneralUtility::get_dirs(Environment::getPublicPath() . '/' . $formatPath);
176 foreach ($formats as $format) {
177 $documentFile = '';
178 switch ($format) {
179 case 'html':
180 // Try to find a valid index file
181 $indexFiles = ['Index.html', 'index.html', 'index.htm'];
182 foreach ($indexFiles as $indexFile) {
183 if (file_exists(Environment::getPublicPath() . '/' . $formatPath . $format . '/' . $indexFile)) {
184 $documentFile = $indexFile;
185 break;
186 }
187 }
188 break;
189 case 'pdf':
190 // Retrieve first PDF
191 $files = GeneralUtility::getFilesInDir(Environment::getPublicPath() . '/' . $formatPath . $format, 'pdf');
192 if (is_array($files) && !empty($files)) {
193 $documentFile = current($files);
194 }
195 break;
196 }
197 if (!empty($documentFile)) {
198 /** @var \TYPO3\CMS\Documentation\Domain\Model\DocumentFormat $documentFormat */
199 $documentFormat = $this->objectManager->get(DocumentFormat::class)
200 ->setFormat($format)
201 ->setPath($formatPath . $format . '/' . $documentFile);
202
203 $documentTranslation->addFormat($documentFormat);
204 }
205 }
206
207 if (!empty($documentTranslation->getFormats())) {
208 $document->addTranslation($documentTranslation);
209 $documents[$documentKey] = $document;
210 }
211 }
212 }
213
214 return $documents;
215 }
216
217 /**
218 * Retrieves OpenOffice documents (manual.sxw).
219 *
220 * @return array
221 */
222 protected function findOpenOfficeDocuments()
223 {
224 $documents = [];
225 $language = 'default';
226
227 foreach (array_keys($GLOBALS['TYPO3_LOADED_EXT']) as $extensionKey) {
228 $path = GeneralUtility::getFileAbsFileName('EXT:' . $extensionKey . '/doc/');
229 if (is_file($path . 'manual.sxw')) {
230 $documentKey = 'typo3cms.extensions.' . $extensionKey;
231 $icon = MiscUtility::getIcon($documentKey);
232
233 /** @var \TYPO3\CMS\Documentation\Domain\Model\Document $document */
234 $document = $this->objectManager->get(Document::class)
235 ->setPackageKey($documentKey)
236 ->setExtensionKey($extensionKey)
237 ->setIcon($icon);
238
239 $metadata = $this->getMetadata($documentKey, $language);
240 /** @var \TYPO3\CMS\Documentation\Domain\Model\DocumentTranslation $documentTranslation */
241 $documentTranslation = $this->objectManager->get(DocumentTranslation::class)
242 ->setLanguage($language)
243 ->setTitle($metadata['title'])
244 ->setDescription($metadata['description']);
245
246 /** @var \TYPO3\CMS\Documentation\Domain\Model\DocumentFormat $documentFormat */
247 $documentFormat = $this->objectManager->get(DocumentFormat::class)
248 ->setFormat('sxw')
249 ->setPath(PathUtility::stripPathSitePrefix($path . 'manual.sxw'));
250
251 $documentTranslation->addFormat($documentFormat);
252 $document->addTranslation($documentTranslation);
253 $documents[$documentKey] = $document;
254 }
255 }
256
257 return $documents;
258 }
259
260 /**
261 * Returns metadata associated to a given document key.
262 *
263 * @param string $documentKey
264 * @param string $language
265 * @return array
266 */
267 protected function getMetadata($documentKey, $language)
268 {
269 $documentPath = Environment::getPublicPath() . '/typo3conf/Documentation/' . $documentKey . '/' . $language . '/';
270 $metadata = [
271 'title' => $documentKey,
272 'description' => '',
273 ];
274 if (GeneralUtility::isFirstPartOfStr($documentKey, 'typo3cms.extensions.')) {
275 $extensionKey = substr($documentKey, 20);
276 if (ExtensionManagementUtility::isLoaded($extensionKey)) {
277 $metadata = MiscUtility::getExtensionMetaData($extensionKey);
278 }
279 } elseif (is_file($documentPath . 'composer.json')) {
280 $info = json_decode(file_get_contents($documentPath . 'composer.json'), true);
281 if (is_array($info)) {
282 $metadata['title'] = $info['name'];
283 $metadata['description'] = $info['description'];
284 }
285 }
286 return $metadata;
287 }
288 }