Completed
Push — master ( 2a01c3...ac0864 )
by
unknown
14:49 queued 11s
created

getLatestCompatibleExtensionByIntegerVersionDependency()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 9
Code Lines 6

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 6
nc 1
nop 1
dl 0
loc 9
rs 10
c 0
b 0
f 0
1
<?php
2
3
/*
4
 * This file is part of the TYPO3 CMS project.
5
 *
6
 * It is free software; you can redistribute it and/or modify it under
7
 * the terms of the GNU General Public License, either version 2
8
 * of the License, or any later version.
9
 *
10
 * For the full copyright and license information, please read the
11
 * LICENSE.txt file that was distributed with this source code.
12
 *
13
 * The TYPO3 project - inspiring people to share!
14
 */
15
16
namespace TYPO3\CMS\Extensionmanager\Utility;
17
18
use TYPO3\CMS\Core\SingletonInterface;
19
use TYPO3\CMS\Core\Utility\ExtensionManagementUtility;
20
use TYPO3\CMS\Core\Utility\GeneralUtility;
21
use TYPO3\CMS\Core\Utility\VersionNumberUtility;
22
use TYPO3\CMS\Extensionmanager\Domain\Model\Dependency;
23
use TYPO3\CMS\Extensionmanager\Domain\Model\Extension;
24
use TYPO3\CMS\Extensionmanager\Domain\Repository\ExtensionRepository;
25
use TYPO3\CMS\Extensionmanager\Exception;
26
use TYPO3\CMS\Extensionmanager\Exception\MissingExtensionDependencyException;
27
use TYPO3\CMS\Extensionmanager\Exception\MissingVersionDependencyException;
28
use TYPO3\CMS\Extensionmanager\Exception\UnresolvedDependencyException;
29
use TYPO3\CMS\Extensionmanager\Exception\UnresolvedPhpDependencyException;
30
use TYPO3\CMS\Extensionmanager\Exception\UnresolvedTypo3DependencyException;
31
use TYPO3\CMS\Extensionmanager\Service\ExtensionManagementService;
32
33
/**
34
 * Utility for dealing with dependencies
35
 * @internal This class is a specific ExtensionManager implementation and is not part of the Public TYPO3 API.
36
 */
37
class DependencyUtility implements SingletonInterface
38
{
39
    /**
40
     * @var ExtensionRepository
41
     */
42
    protected $extensionRepository;
43
44
    /**
45
     * @var ListUtility
46
     */
47
    protected $listUtility;
48
49
    /**
50
     * @var EmConfUtility
51
     */
52
    protected $emConfUtility;
53
54
    /**
55
     * @var ExtensionManagementService
56
     */
57
    protected $managementService;
58
59
    /**
60
     * @var array
61
     */
62
    protected $availableExtensions = [];
63
64
    /**
65
     * @var string
66
     */
67
    protected $localExtensionStorage = '';
68
69
    /**
70
     * @var array
71
     */
72
    protected $dependencyErrors = [];
73
74
    /**
75
     * @var bool
76
     */
77
    protected $skipDependencyCheck = false;
78
79
    /**
80
     * @param ExtensionRepository $extensionRepository
81
     */
82
    public function injectExtensionRepository(ExtensionRepository $extensionRepository)
83
    {
84
        $this->extensionRepository = $extensionRepository;
85
    }
86
87
    /**
88
     * @param ListUtility $listUtility
89
     */
90
    public function injectListUtility(ListUtility $listUtility)
91
    {
92
        $this->listUtility = $listUtility;
93
    }
94
95
    /**
96
     * @param EmConfUtility $emConfUtility
97
     */
98
    public function injectEmConfUtility(EmConfUtility $emConfUtility)
99
    {
100
        $this->emConfUtility = $emConfUtility;
101
    }
102
103
    /**
104
     * @param ExtensionManagementService $managementService
105
     */
106
    public function injectManagementService(ExtensionManagementService $managementService)
107
    {
108
        $this->managementService = $managementService;
109
    }
110
111
    /**
112
     * @param string $localExtensionStorage
113
     */
114
    public function setLocalExtensionStorage($localExtensionStorage)
115
    {
116
        $this->localExtensionStorage = $localExtensionStorage;
117
    }
118
119
    /**
120
     * Setter for available extensions
121
     * gets available extensions from list utility if not already done
122
     */
123
    protected function setAvailableExtensions()
124
    {
125
        $this->availableExtensions = $this->listUtility->getAvailableExtensions();
126
    }
127
128
    /**
129
     * @param bool $skipDependencyCheck
130
     */
131
    public function setSkipDependencyCheck($skipDependencyCheck)
132
    {
133
        $this->skipDependencyCheck = $skipDependencyCheck;
134
    }
135
136
    /**
137
     * Checks dependencies for special cases (currently typo3 and php)
138
     *
139
     * @param Extension $extension
140
     */
141
    public function checkDependencies(Extension $extension)
142
    {
143
        $this->dependencyErrors = [];
144
        $dependencies = $extension->getDependencies();
145
        foreach ($dependencies as $dependency) {
146
            /** @var Dependency $dependency */
147
            $identifier = strtolower($dependency->getIdentifier());
148
            try {
149
                if (in_array($identifier, Dependency::$specialDependencies)) {
150
                    if (!$this->skipDependencyCheck) {
151
                        $methodName = 'check' . ucfirst($identifier) . 'Dependency';
152
                        $this->{$methodName}($dependency);
153
                    }
154
                } else {
155
                    if ($dependency->getType() === 'depends') {
156
                        $this->checkExtensionDependency($dependency);
157
                    }
158
                }
159
            } catch (UnresolvedDependencyException $e) {
160
                if (in_array($identifier, Dependency::$specialDependencies)) {
161
                    $extensionKey = $extension->getExtensionKey();
162
                } else {
163
                    $extensionKey = $identifier;
164
                }
165
                if (!isset($this->dependencyErrors[$extensionKey])) {
166
                    $this->dependencyErrors[$extensionKey] = [];
167
                }
168
                $this->dependencyErrors[$extensionKey][] = [
169
                    'code' => $e->getCode(),
170
                    'message' => $e->getMessage()
171
                ];
172
            }
173
        }
174
    }
175
176
    /**
177
     * Returns TRUE if a dependency error was found
178
     *
179
     * @return bool
180
     */
181
    public function hasDependencyErrors()
182
    {
183
        return !empty($this->dependencyErrors);
184
    }
185
186
    /**
187
     * Return the dependency errors
188
     *
189
     * @return array
190
     */
191
    public function getDependencyErrors()
192
    {
193
        return $this->dependencyErrors;
194
    }
195
196
    /**
197
     * Returns true if current TYPO3 version fulfills extension requirements
198
     *
199
     * @param Dependency $dependency
200
     * @throws Exception\UnresolvedTypo3DependencyException
201
     * @return bool
202
     */
203
    protected function checkTypo3Dependency(Dependency $dependency)
204
    {
205
        $lowerCaseIdentifier = strtolower($dependency->getIdentifier());
206
        if ($lowerCaseIdentifier === 'typo3') {
207
            if (!($dependency->getLowestVersion() === '') && version_compare(VersionNumberUtility::getNumericTypo3Version(), $dependency->getLowestVersion()) === -1) {
208
                throw new UnresolvedTypo3DependencyException(
209
                    'Your TYPO3 version is lower than this extension requires. It requires TYPO3 versions ' . $dependency->getLowestVersion() . ' - ' . $dependency->getHighestVersion(),
210
                    1399144499
211
                );
212
            }
213
            if (!($dependency->getHighestVersion() === '') && version_compare($dependency->getHighestVersion(), VersionNumberUtility::getNumericTypo3Version()) === -1) {
214
                throw new UnresolvedTypo3DependencyException(
215
                    'Your TYPO3 version is higher than this extension requires. It requires TYPO3 versions ' . $dependency->getLowestVersion() . ' - ' . $dependency->getHighestVersion(),
216
                    1399144521
217
                );
218
            }
219
        } else {
220
            throw new UnresolvedTypo3DependencyException(
221
                'checkTypo3Dependency can only check TYPO3 dependencies. Found dependency with identifier "' . $dependency->getIdentifier() . '"',
222
                1399144551
223
            );
224
        }
225
        return true;
226
    }
227
228
    /**
229
     * Returns true if current php version fulfills extension requirements
230
     *
231
     * @param Dependency $dependency
232
     * @throws Exception\UnresolvedPhpDependencyException
233
     * @return bool
234
     */
235
    protected function checkPhpDependency(Dependency $dependency)
236
    {
237
        $lowerCaseIdentifier = strtolower($dependency->getIdentifier());
238
        if ($lowerCaseIdentifier === 'php') {
239
            if (!($dependency->getLowestVersion() === '') && version_compare(PHP_VERSION, $dependency->getLowestVersion()) === -1) {
240
                throw new UnresolvedPhpDependencyException(
241
                    'Your PHP version is lower than necessary. You need at least PHP version ' . $dependency->getLowestVersion(),
242
                    1377977857
243
                );
244
            }
245
            if (!($dependency->getHighestVersion() === '') && version_compare($dependency->getHighestVersion(), PHP_VERSION) === -1) {
246
                throw new UnresolvedPhpDependencyException(
247
                    'Your PHP version is higher than allowed. You can use PHP versions ' . $dependency->getLowestVersion() . ' - ' . $dependency->getHighestVersion(),
248
                    1377977856
249
                );
250
            }
251
        } else {
252
            throw new UnresolvedPhpDependencyException(
253
                'checkPhpDependency can only check PHP dependencies. Found dependency with identifier "' . $dependency->getIdentifier() . '"',
254
                1377977858
255
            );
256
        }
257
        return true;
258
    }
259
260
    /**
261
     * Main controlling function for checking dependencies
262
     * Dependency check is done in the following way:
263
     * - installed extension in matching version ? - return true
264
     * - available extension in matching version ? - mark for installation
265
     * - remote (TER) extension in matching version? - mark for download
266
     *
267
     * @todo handle exceptions / markForUpload
268
     * @param Dependency $dependency
269
     * @throws Exception\MissingVersionDependencyException
270
     * @return bool
271
     */
272
    protected function checkExtensionDependency(Dependency $dependency)
273
    {
274
        $extensionKey = $dependency->getIdentifier();
275
        $extensionIsLoaded = $this->isDependentExtensionLoaded($extensionKey);
276
        if ($extensionIsLoaded === true) {
277
            $isLoadedVersionCompatible = $this->isLoadedVersionCompatible($dependency);
278
            if ($isLoadedVersionCompatible === true || $this->skipDependencyCheck) {
279
                return true;
280
            }
281
            $extension = $this->listUtility->getExtension($extensionKey);
282
            $loadedVersion = $extension->getPackageMetaData()->getVersion();
283
            if (version_compare($loadedVersion, $dependency->getHighestVersion()) === -1) {
284
                try {
285
                    $this->getExtensionFromRepository($extensionKey, $dependency);
286
                } catch (UnresolvedDependencyException $e) {
287
                    throw new MissingVersionDependencyException(
288
                        'The extension ' . $extensionKey . ' is installed in version ' . $loadedVersion
289
                            . ' but needed in version ' . $dependency->getLowestVersion() . ' - ' . $dependency->getHighestVersion() . ' and could not be fetched from TER',
290
                        1396302624
291
                    );
292
                }
293
            } else {
294
                throw new MissingVersionDependencyException(
295
                    'The extension ' . $extensionKey . ' is installed in version ' . $loadedVersion .
296
                    ' but needed in version ' . $dependency->getLowestVersion() . ' - ' . $dependency->getHighestVersion(),
297
                    1430561927
298
                );
299
            }
300
        } else {
301
            $extensionIsAvailable = $this->isDependentExtensionAvailable($extensionKey);
302
            if ($extensionIsAvailable === true) {
303
                $isAvailableVersionCompatible = $this->isAvailableVersionCompatible($dependency);
304
                if ($isAvailableVersionCompatible) {
305
                    $unresolvedDependencyErrors = $this->dependencyErrors;
306
                    $this->managementService->markExtensionForInstallation($extensionKey);
307
                    $this->dependencyErrors = array_merge($unresolvedDependencyErrors, $this->dependencyErrors);
308
                } else {
309
                    $extension = $this->listUtility->getExtension($extensionKey);
310
                    $availableVersion = $extension->getPackageMetaData()->getVersion();
311
                    if (version_compare($availableVersion, $dependency->getHighestVersion()) === -1) {
312
                        try {
313
                            $this->getExtensionFromRepository($extensionKey, $dependency);
314
                        } catch (MissingExtensionDependencyException $e) {
315
                            if (!$this->skipDependencyCheck) {
316
                                throw new MissingVersionDependencyException(
317
                                    'The extension ' . $extensionKey . ' is available in version ' . $availableVersion
318
                                    . ' but is needed in version ' . $dependency->getLowestVersion() . ' - ' . $dependency->getHighestVersion() . ' and could not be fetched from TER',
319
                                    1430560390
320
                                );
321
                            }
322
                        }
323
                    } else {
324
                        if (!$this->skipDependencyCheck) {
325
                            throw new MissingVersionDependencyException(
326
                                'The extension ' . $extensionKey . ' is available in version ' . $availableVersion
327
                                . ' but is needed in version ' . $dependency->getLowestVersion() . ' - ' . $dependency->getHighestVersion(),
328
                                1430562374
329
                            );
330
                        }
331
                        // Dependency check is skipped and the local version has to be installed
332
                        $this->managementService->markExtensionForInstallation($extensionKey);
333
                    }
334
                }
335
            } else {
336
                $unresolvedDependencyErrors = $this->dependencyErrors;
337
                $this->getExtensionFromRepository($extensionKey, $dependency);
338
                $this->dependencyErrors = array_merge($unresolvedDependencyErrors, $this->dependencyErrors);
339
            }
340
        }
341
342
        return false;
343
    }
344
345
    /**
346
     * Get an extension from a repository
347
     * (might be in the extension itself or the TER)
348
     *
349
     * @param string $extensionKey
350
     * @param Dependency $dependency
351
     * @throws Exception\UnresolvedDependencyException
352
     */
353
    protected function getExtensionFromRepository($extensionKey, Dependency $dependency)
354
    {
355
        if (!$this->getExtensionFromInExtensionRepository($extensionKey)) {
356
            $this->getExtensionFromTer($extensionKey, $dependency);
357
        }
358
    }
359
360
    /**
361
     * Gets an extension from the in extension repository
362
     * (the local extension storage)
363
     *
364
     * @param string $extensionKey
365
     * @return bool
366
     */
367
    protected function getExtensionFromInExtensionRepository($extensionKey)
368
    {
369
        if ($this->localExtensionStorage !== '' && is_dir($this->localExtensionStorage)) {
370
            $extList = GeneralUtility::get_dirs($this->localExtensionStorage);
371
            if (in_array($extensionKey, $extList)) {
0 ignored issues
show
Bug introduced by
$extList of type null|string is incompatible with the type array expected by parameter $haystack of in_array(). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

371
            if (in_array($extensionKey, /** @scrutinizer ignore-type */ $extList)) {
Loading history...
372
                $this->managementService->markExtensionForCopy($extensionKey, $this->localExtensionStorage);
373
                return true;
374
            }
375
        }
376
        return false;
377
    }
378
379
    /**
380
     * Handles checks to find a compatible extension version from TER to fulfill given dependency
381
     *
382
     * @todo unit tests
383
     * @param string $extensionKey
384
     * @param Dependency $dependency
385
     * @throws Exception\UnresolvedDependencyException
386
     */
387
    protected function getExtensionFromTer($extensionKey, Dependency $dependency)
388
    {
389
        $isExtensionDownloadableFromTer = $this->isExtensionDownloadableFromTer($extensionKey);
390
        if (!$isExtensionDownloadableFromTer) {
391
            if (!$this->skipDependencyCheck) {
392
                if ($this->extensionRepository->countAll() > 0) {
393
                    throw new MissingExtensionDependencyException(
394
                        'The extension ' . $extensionKey . ' is not available from TER.',
395
                        1399161266
396
                    );
397
                }
398
                throw new MissingExtensionDependencyException(
399
                    'The extension ' . $extensionKey . ' could not be checked. Please update your Extension-List from TYPO3 Extension Repository (TER).',
400
                    1430580308
401
                );
402
            }
403
            return;
404
        }
405
406
        $isDownloadableVersionCompatible = $this->isDownloadableVersionCompatible($dependency);
407
        if (!$isDownloadableVersionCompatible) {
408
            if (!$this->skipDependencyCheck) {
409
                throw new MissingVersionDependencyException(
410
                    'No compatible version found for extension ' . $extensionKey,
411
                    1399161284
412
                );
413
            }
414
            return;
415
        }
416
417
        $latestCompatibleExtensionByIntegerVersionDependency = $this->getLatestCompatibleExtensionByIntegerVersionDependency($dependency);
418
        if (!$latestCompatibleExtensionByIntegerVersionDependency instanceof Extension) {
0 ignored issues
show
introduced by
$latestCompatibleExtensi...ntegerVersionDependency is always a sub-type of TYPO3\CMS\Extensionmanager\Domain\Model\Extension.
Loading history...
419
            if (!$this->skipDependencyCheck) {
420
                throw new MissingExtensionDependencyException(
421
                    'Could not resolve dependency for "' . $dependency->getIdentifier() . '"',
422
                    1399161302
423
                );
424
            }
425
            return;
426
        }
427
428
        if ($this->isDependentExtensionLoaded($extensionKey)) {
429
            $this->managementService->markExtensionForUpdate($latestCompatibleExtensionByIntegerVersionDependency);
430
        } else {
431
            $this->managementService->markExtensionForDownload($latestCompatibleExtensionByIntegerVersionDependency);
432
        }
433
    }
434
435
    /**
436
     * @param string $extensionKey
437
     * @return bool
438
     */
439
    protected function isDependentExtensionLoaded($extensionKey)
440
    {
441
        return ExtensionManagementUtility::isLoaded($extensionKey);
442
    }
443
444
    /**
445
     * @param Dependency $dependency
446
     * @return bool
447
     */
448
    protected function isLoadedVersionCompatible(Dependency $dependency)
449
    {
450
        $extensionVersion = ExtensionManagementUtility::getExtensionVersion($dependency->getIdentifier());
451
        return $this->isVersionCompatible($extensionVersion, $dependency);
452
    }
453
454
    /**
455
     * @param string $version
456
     * @param Dependency $dependency
457
     * @return bool
458
     */
459
    protected function isVersionCompatible($version, Dependency $dependency)
460
    {
461
        if (!($dependency->getLowestVersion() === '') && version_compare($version, $dependency->getLowestVersion()) === -1) {
462
            return false;
463
        }
464
        if (!($dependency->getHighestVersion() === '') && version_compare($dependency->getHighestVersion(), $version) === -1) {
465
            return false;
466
        }
467
        return true;
468
    }
469
470
    /**
471
     * Checks whether the needed extension is available
472
     * (not necessarily installed, but present in system)
473
     *
474
     * @param string $extensionKey
475
     * @return bool
476
     */
477
    protected function isDependentExtensionAvailable($extensionKey)
478
    {
479
        $this->setAvailableExtensions();
480
        return array_key_exists($extensionKey, $this->availableExtensions);
481
    }
482
483
    /**
484
     * Checks whether the available version is compatible
485
     *
486
     * @param Dependency $dependency
487
     * @return bool
488
     */
489
    protected function isAvailableVersionCompatible(Dependency $dependency)
490
    {
491
        $this->setAvailableExtensions();
492
        $extensionData = $this->emConfUtility->includeEmConf(
493
            $dependency->getIdentifier(),
494
            $this->availableExtensions[$dependency->getIdentifier()]
495
        );
496
        return $this->isVersionCompatible($extensionData['version'], $dependency);
497
    }
498
499
    /**
500
     * Checks whether a ter extension with $extensionKey exists
501
     *
502
     * @param string $extensionKey
503
     * @return bool
504
     */
505
    protected function isExtensionDownloadableFromTer($extensionKey)
506
    {
507
        return $this->extensionRepository->countByExtensionKey($extensionKey) > 0;
0 ignored issues
show
Bug introduced by
The method countByExtensionKey() does not exist on TYPO3\CMS\Extensionmanag...ory\ExtensionRepository. Since you implemented __call, consider adding a @method annotation. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

507
        return $this->extensionRepository->/** @scrutinizer ignore-call */ countByExtensionKey($extensionKey) > 0;
Loading history...
508
    }
509
510
    /**
511
     * Checks whether a compatible version of the extension exists in TER
512
     *
513
     * @param Dependency $dependency
514
     * @return bool
515
     */
516
    protected function isDownloadableVersionCompatible(Dependency $dependency)
517
    {
518
        $versions = $this->getLowestAndHighestIntegerVersions($dependency);
519
        $count = $this->extensionRepository->countByVersionRangeAndExtensionKey(
520
            $dependency->getIdentifier(),
521
            $versions['lowestIntegerVersion'],
522
            $versions['highestIntegerVersion']
523
        );
524
        return !empty($count);
525
    }
526
527
    /**
528
     * Get the latest compatible version of an extension that's
529
     * compatible with the current core and PHP version.
530
     *
531
     * @param iterable $extensions
532
     * @return Extension|null
533
     */
534
    protected function getCompatibleExtension(iterable $extensions): ?Extension
535
    {
536
        foreach ($extensions as $extension) {
537
            /** @var Extension $extension */
538
            $this->checkDependencies($extension);
539
            $extensionKey = $extension->getExtensionKey();
540
541
            if (isset($this->dependencyErrors[$extensionKey])) {
542
                // reset dependencyErrors and continue with next version
543
                unset($this->dependencyErrors[$extensionKey]);
544
                continue;
545
            }
546
547
            return $extension;
548
        }
549
550
        return null;
551
    }
552
553
    /**
554
     * Get the latest compatible version of an extension that
555
     * fulfills the given dependency from TER
556
     *
557
     * @param Dependency $dependency
558
     * @return Extension
559
     */
560
    protected function getLatestCompatibleExtensionByIntegerVersionDependency(Dependency $dependency)
561
    {
562
        $versions = $this->getLowestAndHighestIntegerVersions($dependency);
563
        $compatibleDataSets = $this->extensionRepository->findByVersionRangeAndExtensionKeyOrderedByVersion(
564
            $dependency->getIdentifier(),
565
            $versions['lowestIntegerVersion'],
566
            $versions['highestIntegerVersion']
567
        );
568
        return $this->getCompatibleExtension($compatibleDataSets);
569
    }
570
571
    /**
572
     * Return array of lowest and highest version of dependency as integer
573
     *
574
     * @param Dependency $dependency
575
     * @return array
576
     */
577
    protected function getLowestAndHighestIntegerVersions(Dependency $dependency)
578
    {
579
        $lowestVersion = $dependency->getLowestVersion();
580
        $lowestVersionInteger = $lowestVersion ? VersionNumberUtility::convertVersionNumberToInteger($lowestVersion) : 0;
581
        $highestVersion = $dependency->getHighestVersion();
582
        $highestVersionInteger = $highestVersion ? VersionNumberUtility::convertVersionNumberToInteger($highestVersion) : 0;
583
        return [
584
            'lowestIntegerVersion' => $lowestVersionInteger,
585
            'highestIntegerVersion' => $highestVersionInteger
586
        ];
587
    }
588
589
    /**
590
     * @param string $extensionKey
591
     * @return array
592
     */
593
    public function findInstalledExtensionsThatDependOnMe($extensionKey)
594
    {
595
        $availableAndInstalledExtensions = $this->listUtility->getAvailableAndInstalledExtensionsWithAdditionalInformation();
596
        $dependentExtensions = [];
597
        foreach ($availableAndInstalledExtensions as $availableAndInstalledExtensionKey => $availableAndInstalledExtension) {
598
            if (isset($availableAndInstalledExtension['installed']) && $availableAndInstalledExtension['installed'] === true) {
599
                if (is_array($availableAndInstalledExtension['constraints']) && is_array($availableAndInstalledExtension['constraints']['depends']) && array_key_exists($extensionKey, $availableAndInstalledExtension['constraints']['depends'])) {
600
                    $dependentExtensions[] = $availableAndInstalledExtensionKey;
601
                }
602
            }
603
        }
604
        return $dependentExtensions;
605
    }
606
607
    /**
608
     * Get extensions (out of a given list) that are suitable for the current TYPO3 version
609
     *
610
     * @param \TYPO3\CMS\Extbase\Persistence\QueryResultInterface|array $extensions List of extensions to check
611
     * @return array List of extensions suitable for current TYPO3 version
612
     */
613
    public function getExtensionsSuitableForTypo3Version($extensions)
614
    {
615
        $suitableExtensions = [];
616
        /** @var Extension $extension */
617
        foreach ($extensions as $extension) {
618
            /** @var Dependency $dependency */
619
            foreach ($extension->getDependencies() as $dependency) {
620
                if ($dependency->getIdentifier() === 'typo3') {
621
                    try {
622
                        if ($this->checkTypo3Dependency($dependency)) {
623
                            $suitableExtensions[] = $extension;
624
                        }
625
                    } catch (UnresolvedTypo3DependencyException $e) {
0 ignored issues
show
Coding Style Comprehensibility introduced by
Consider adding a comment why this CATCH block is empty.
Loading history...
626
                    }
627
                    break;
628
                }
629
            }
630
        }
631
        return $suitableExtensions;
632
    }
633
634
    /**
635
     * Gets a list of various extensions in various versions and returns
636
     * a filtered list containing the extension-version combination with
637
     * the highest version number.
638
     *
639
     * @param Extension[] $extensions
640
     * @param bool $showUnsuitable
641
     *
642
     * @return Extension[]
643
     */
644
    public function filterYoungestVersionOfExtensionList(array $extensions, $showUnsuitable)
645
    {
646
        if (!$showUnsuitable) {
647
            $extensions = $this->getExtensionsSuitableForTypo3Version($extensions);
648
        }
649
        $filteredExtensions = [];
650
        foreach ($extensions as $extension) {
651
            $extensionKey = $extension->getExtensionKey();
652
            if (!array_key_exists($extensionKey, $filteredExtensions)) {
653
                $filteredExtensions[$extensionKey] = $extension;
654
                continue;
655
            }
656
            $currentVersion = $filteredExtensions[$extensionKey]->getVersion();
657
            $newVersion = $extension->getVersion();
658
            if (version_compare($newVersion, $currentVersion, '>')) {
659
                $filteredExtensions[$extensionKey] = $extension;
660
            }
661
        }
662
        return $filteredExtensions;
663
    }
664
}
665