TYPO3 CMS  TYPO3_6-2
DependencyUtility.php
Go to the documentation of this file.
1 <?php
3 
21 
28 
33  protected $objectManager;
34 
40 
45  protected $listUtility;
46 
51  protected $emConfUtility;
52 
57  protected $managementService;
58 
62  protected $availableExtensions = array();
63 
67  protected $localExtensionStorage = '';
68 
72  protected $dependencyErrors = array();
73 
77  protected $skipSystemDependencyCheck = FALSE;
78 
84  $this->localExtensionStorage = $localExtensionStorage;
85  }
86 
93  protected function setAvailableExtensions() {
94  $this->availableExtensions = $this->listUtility->getAvailableExtensions();
95  }
96 
101  public function setSkipSystemDependencyCheck($skipSpecialDependencyCheck) {
102  $this->skipSystemDependencyCheck = $skipSpecialDependencyCheck;
103  }
104 
111  public function checkDependencies(Extension $extension) {
112  $this->dependencyErrors = array();
113  $dependencies = $extension->getDependencies();
114  foreach ($dependencies as $dependency) {
116  $identifier = strtolower($dependency->getIdentifier());
117  try {
118  if (in_array($identifier, Dependency::$specialDependencies)) {
119  if (!$this->skipSystemDependencyCheck) {
120  $methodName = 'check' . ucfirst($identifier) . 'Dependency';
121  $this->{$methodName}($dependency);
122  }
123  } else {
124  if ($dependency->getType() === 'depends') {
125  $this->checkExtensionDependency($dependency);
126  }
127  }
128  } catch (Exception\UnresolvedDependencyException $e) {
129  if (in_array($identifier, Dependency::$specialDependencies)) {
130  $extensionKey = $extension->getExtensionKey();
131  } else {
132  $extensionKey = $identifier;
133  }
134  if (!isset($this->dependencyErrors[$extensionKey])) {
135  $this->dependencyErrors[$extensionKey] = array();
136  }
137  $this->dependencyErrors[$extensionKey][] = array(
138  'code' => $e->getCode(),
139  'message' => $e->getMessage()
140  );
141  }
142  }
143  }
144 
150  public function hasDependencyErrors() {
151  return !empty($this->dependencyErrors);
152  }
153 
159  public function getDependencyErrors() {
161  }
162 
170  protected function checkTypo3Dependency(Dependency $dependency) {
171  $lowerCaseIdentifier = strtolower($dependency->getIdentifier());
172  if ($lowerCaseIdentifier === 'typo3') {
173  if (!($dependency->getLowestVersion() === '') && version_compare(VersionNumberUtility::getNumericTypo3Version(), $dependency->getLowestVersion()) === -1) {
175  'Your TYPO3 version is lower than this extension requires. It requires TYPO3 versions ' . $dependency->getLowestVersion() . ' - ' . $dependency->getHighestVersion(),
176  1399144499
177  );
178  }
179  if (!($dependency->getHighestVersion() === '') && version_compare($dependency->getHighestVersion(), VersionNumberUtility::getNumericTypo3Version()) === -1) {
181  'Your TYPO3 version is higher than this extension requires. It requires TYPO3 versions ' . $dependency->getLowestVersion() . ' - ' . $dependency->getHighestVersion(),
182  1399144521
183  );
184  }
185  } else {
187  'checkTypo3Dependency can only check TYPO3 dependencies. Found dependency with identifier "' . $dependency->getIdentifier() . '"',
188  1399144551
189  );
190  }
191  return TRUE;
192  }
193 
201  protected function checkPhpDependency(Dependency $dependency) {
202  $lowerCaseIdentifier = strtolower($dependency->getIdentifier());
203  if ($lowerCaseIdentifier === 'php') {
204  if (!($dependency->getLowestVersion() === '') && version_compare(PHP_VERSION, $dependency->getLowestVersion()) === -1) {
206  'Your PHP version is lower than necessary. You need at least PHP version ' . $dependency->getLowestVersion(),
207  1377977857
208  );
209  }
210  if (!($dependency->getHighestVersion() === '') && version_compare($dependency->getHighestVersion(), PHP_VERSION) === -1) {
212  'Your PHP version is higher than allowed. You can use PHP versions ' . $dependency->getLowestVersion() . ' - ' . $dependency->getHighestVersion(),
213  1377977856
214  );
215  }
216  } else {
218  'checkPhpDependency can only check PHP dependencies. Found dependency with identifier "' . $dependency->getIdentifier() . '"',
219  1377977858
220  );
221  }
222  return TRUE;
223  }
224 
237  protected function checkExtensionDependency(Dependency $dependency) {
238  $extensionKey = $dependency->getIdentifier();
239  $extensionIsLoaded = $this->isDependentExtensionLoaded($extensionKey);
240  if ($extensionIsLoaded === TRUE) {
241  $isLoadedVersionCompatible = $this->isLoadedVersionCompatible($dependency);
242  if ($isLoadedVersionCompatible === TRUE) {
243  return TRUE;
244  }
245  $extension = $this->listUtility->getExtension($extensionKey);
246  $loadedVersion = $extension->getPackageMetaData()->getVersion();
247  if (version_compare($loadedVersion, $dependency->getHighestVersion()) === -1) {
248  try {
249  $this->getExtensionFromRepository($extensionKey, $dependency);
250  } catch (Exception\UnresolvedDependencyException $e) {
252  'The extension ' . $extensionKey . ' is installed in version ' . $loadedVersion
253  . ' but needed in version ' . $dependency->getLowestVersion() . ' - ' . $dependency->getHighestVersion() . ' and could not be fetched from TER',
254  1396302624
255  );
256  }
257  } else {
259  'The extension ' . $extensionKey . ' is installed in version ' . $loadedVersion .
260  ' but needed in version ' . $dependency->getLowestVersion() . ' - ' . $dependency->getHighestVersion(),
261  1430561927
262  );
263  }
264  } else {
265  $extensionIsAvailable = $this->isDependentExtensionAvailable($extensionKey);
266  if ($extensionIsAvailable === TRUE) {
267  $isAvailableVersionCompatible = $this->isAvailableVersionCompatible($dependency);
268  if ($isAvailableVersionCompatible) {
269  $unresolvedDependencyErrors = $this->dependencyErrors;
270  $this->managementService->markExtensionForInstallation($extensionKey);
271  $this->dependencyErrors = array_merge($unresolvedDependencyErrors, $this->dependencyErrors);
272  } else {
273  $extension = $this->listUtility->getExtension($extensionKey);
274  $availableVersion = $extension->getPackageMetaData()->getVersion();
275  if (version_compare($availableVersion, $dependency->getHighestVersion()) === -1) {
276  try {
277  $this->getExtensionFromRepository($extensionKey, $dependency);
278  } catch (Exception\MissingExtensionDependencyException $e) {
280  'The extension ' . $extensionKey . ' is available in version ' . $availableVersion
281  . ' but is needed in version ' . $dependency->getLowestVersion() . ' - ' . $dependency->getHighestVersion() . ' and could not be fetched from TER',
282  1430560390
283  );
284  }
285  } else {
287  'The extension ' . $extensionKey . ' is available in version ' . $availableVersion
288  . ' but is needed in version ' . $dependency->getLowestVersion() . ' - ' . $dependency->getHighestVersion(),
289  1430562374
290  );
291  }
292  }
293  } else {
294  $unresolvedDependencyErrors = $this->dependencyErrors;
295  $this->getExtensionFromRepository($extensionKey, $dependency);
296  $this->dependencyErrors = array_merge($unresolvedDependencyErrors, $this->dependencyErrors);
297  }
298  }
299  return FALSE;
300  }
301 
311  protected function getExtensionFromRepository($extensionKey, Dependency $dependency) {
312  if (!$this->getExtensionFromInExtensionRepository($extensionKey, $dependency)) {
313  $this->getExtensionFromTer($extensionKey, $dependency);
314  }
315  }
316 
324  protected function getExtensionFromInExtensionRepository($extensionKey) {
325  if ($this->localExtensionStorage !== '' && is_dir($this->localExtensionStorage)) {
326  $extList = \TYPO3\CMS\Core\Utility\GeneralUtility::get_dirs($this->localExtensionStorage);
327  if (in_array($extensionKey, $extList)) {
328  $this->managementService->markExtensionForCopy($extensionKey, $this->localExtensionStorage);
329  return TRUE;
330  }
331  }
332  return FALSE;
333  }
334 
344  protected function getExtensionFromTer($extensionKey, Dependency $dependency) {
345  $isExtensionDownloadableFromTer = $this->isExtensionDownloadableFromTer($extensionKey);
346  if (!$isExtensionDownloadableFromTer) {
347  if (!$this->skipSystemDependencyCheck) {
348  if ($this->extensionRepository->countAll() > 0) {
350  'The extension ' . $extensionKey . ' is not available from TER.',
351  1399161266
352  );
353  } else {
355  'The extension ' . $extensionKey . ' could not be checked. Please update your Extension-List from TYPO3 Extension Repository (TER).',
356  1430580308
357  );
358  }
359  }
360  return;
361  }
362 
363  $isDownloadableVersionCompatible = $this->isDownloadableVersionCompatible($dependency);
364  if (!$isDownloadableVersionCompatible) {
365  if (!$this->skipSystemDependencyCheck) {
367  'No compatible version found for extension ' . $extensionKey,
368  1399161284
369  );
370  }
371  return;
372  }
373 
374  $latestCompatibleExtensionByIntegerVersionDependency = $this->getLatestCompatibleExtensionByIntegerVersionDependency($dependency);
375  if (!$latestCompatibleExtensionByIntegerVersionDependency instanceof Extension) {
376  if (!$this->skipSystemDependencyCheck) {
378  'Could not resolve dependency for "' . $dependency->getIdentifier() . '"',
379  1399161302
380  );
381  }
382  return;
383  }
384 
385  if ($this->isDependentExtensionLoaded($extensionKey)) {
386  $this->managementService->markExtensionForUpdate($latestCompatibleExtensionByIntegerVersionDependency);
387  } else {
388  $this->managementService->markExtensionForDownload($latestCompatibleExtensionByIntegerVersionDependency);
389  }
390  }
391 
396  protected function isDependentExtensionLoaded($extensionKey) {
397  return ExtensionManagementUtility::isLoaded($extensionKey);
398  }
399 
404  protected function isLoadedVersionCompatible(Dependency $dependency) {
405  $extensionVersion = ExtensionManagementUtility::getExtensionVersion($dependency->getIdentifier());
406  return $this->isVersionCompatible($extensionVersion, $dependency);
407  }
408 
414  protected function isVersionCompatible($version, Dependency $dependency) {
415  if (!($dependency->getLowestVersion() === '') && version_compare($version, $dependency->getLowestVersion()) === -1) {
416  return FALSE;
417  }
418  if (!($dependency->getHighestVersion() === '') && version_compare($dependency->getHighestVersion(), $version) === -1) {
419  return FALSE;
420  }
421  return TRUE;
422  }
423 
431  protected function isDependentExtensionAvailable($extensionKey) {
432  $this->setAvailableExtensions();
433  return array_key_exists($extensionKey, $this->availableExtensions);
434  }
435 
442  protected function isAvailableVersionCompatible(Dependency $dependency) {
443  $this->setAvailableExtensions();
444  $extensionData = $this->emConfUtility->includeEmConf($this->availableExtensions[$dependency->getIdentifier()]);
445  return $this->isVersionCompatible($extensionData['version'], $dependency);
446  }
447 
454  protected function isExtensionDownloadableFromTer($extensionKey) {
455  return $this->extensionRepository->countByExtensionKey($extensionKey) > 0;
456  }
457 
464  protected function isDownloadableVersionCompatible(Dependency $dependency) {
465  $versions = $this->getLowestAndHighestIntegerVersions($dependency);
466  $count = $this->extensionRepository->countByVersionRangeAndExtensionKey(
467  $dependency->getIdentifier(), $versions['lowestIntegerVersion'], $versions['highestIntegerVersion']
468  );
469  return !empty($count);
470  }
471 
480  $versions = $this->getLowestAndHighestIntegerVersions($dependency);
481  $compatibleDataSets = $this->extensionRepository->findByVersionRangeAndExtensionKeyOrderedByVersion(
482  $dependency->getIdentifier(),
483  $versions['lowestIntegerVersion'],
484  $versions['highestIntegerVersion']
485  );
486  return $compatibleDataSets->getFirst();
487  }
488 
495  protected function getLowestAndHighestIntegerVersions(Dependency $dependency) {
496  $lowestVersion = $dependency->getLowestVersion();
497  $lowestVersionInteger = $lowestVersion ? VersionNumberUtility::convertVersionNumberToInteger($lowestVersion) : 0;
498  $highestVersion = $dependency->getHighestVersion();
499  $highestVersionInteger = $highestVersion ? VersionNumberUtility::convertVersionNumberToInteger($highestVersion) : 0;
500  return array(
501  'lowestIntegerVersion' => $lowestVersionInteger,
502  'highestIntegerVersion' => $highestVersionInteger
503  );
504  }
505 
506  public function findInstalledExtensionsThatDependOnMe($extensionKey) {
507  $availableAndInstalledExtensions = $this->listUtility->getAvailableAndInstalledExtensionsWithAdditionalInformation();
508  $dependentExtensions = array();
509  foreach ($availableAndInstalledExtensions as $availableAndInstalledExtensionKey => $availableAndInstalledExtension) {
510  if (isset($availableAndInstalledExtension['installed']) && $availableAndInstalledExtension['installed'] === TRUE) {
511  if (is_array($availableAndInstalledExtension['constraints']) && is_array($availableAndInstalledExtension['constraints']['depends']) && array_key_exists($extensionKey, $availableAndInstalledExtension['constraints']['depends'])) {
512  $dependentExtensions[] = $availableAndInstalledExtensionKey;
513  }
514  }
515  }
516  return $dependentExtensions;
517  }
518 
519 }
getExtensionFromRepository($extensionKey, Dependency $dependency)
getExtensionFromTer($extensionKey, Dependency $dependency)
isVersionCompatible($version, Dependency $dependency)
getLatestCompatibleExtensionByIntegerVersionDependency(Dependency $dependency)