/** * Get extensions wich do not claim to be compatible in their ext_emconf.php * * Note that we are ignoring open ended comatibility here. These are the * cases where the version requirements have a 0.0.0 at the end. This is * because we assume that extension creators that care about compatibilty * will specify the maximum supported version instead of providing a 0.0.0 * as upper limit. * * @param string $version The version to check against * @param boolean $ignoreOpenEnd Should we ignore open ended requirements? * * @return array Array of compatible extension keys and their version ranges */ public static function getIncompatibleExtensions($version = NULL, $ignoreOpenEnd = TRUE) { if ($version === NULL) { $version = self::CURRENT_LTS_VERSION; } $extensions = array(); $list = self::getInstalledExtensions(); if (t3lib_div::int_from_ver(TYPO3_version) < 6002000) { foreach ($list as $extensionName => $extensionData) { if (is_array($extensionData) && isset($extensionData['EM_CONF']['constraints']['depends']['typo3'])) { $versionRange = tx_em_Tools::splitVersionRange($extensionData['EM_CONF']['constraints']['depends']['typo3']); if ((bool) $ignoreOpenEnd) { $upperBound = $versionRange[1] !== '0.0.0' && version_compare($version, $versionRange[1], '>'); } else { $upperBound = $versionRange[1] === '0.0.0' || version_compare($version, $versionRange[1], '>'); } if ($versionRange[0] !== '0.0.0' && version_compare($version, $versionRange[0], '<=') || $upperBound) { $extensions[$extensionName] = $versionRange; } } } } else { /** @var \TYPO3\CMS\Extensionmanager\Utility\EmConfUtility $emConfUtility */ $emConfUtility = \TYPO3\CMS\Core\Utility\GeneralUtility::makeInstance('\\TYPO3\\CMS\\Extensionmanager\\Utility\\EmConfUtility'); foreach ($list as $extensionName => $extensionData) { if (is_array($extensionData) && isset($extensionData['EM_CONF']['constraints']['depends']['typo3'])) { $extensionData = array(); // FIXME . . . use \TYPO3\CMS\Core\Package\PackageManager $versionRange = tx_em_Tools::splitVersionRange($extensionData['EM_CONF']['constraints']['depends']['typo3']); if ((bool) $ignoreOpenEnd) { $upperBound = $versionRange[1] !== '0.0.0' && version_compare($version, $versionRange[1], '>'); } else { $upperBound = $versionRange[1] === '0.0.0' || version_compare($version, $versionRange[1], '>'); } if ($versionRange[0] !== '0.0.0' && version_compare($version, $versionRange[0], '<=') || $upperBound) { $extensions[$extensionName] = $versionRange; } } } } return $extensions; }
/** *Check extension dependencies * * @param string $extKey * @param array $conf * @param array $instExtInfo * @return array */ function checkDependencies($extKey, $conf, $instExtInfo) { $content = ''; $depError = false; $depIgnore = false; $msg = array(); $depsolver = t3lib_div::_POST('depsolver'); if (isset($conf['constraints']['depends']) && is_array($conf['constraints']['depends'])) { foreach ($conf['constraints']['depends'] as $depK => $depV) { if ($depsolver['ignore'][$depK]) { $msg[] = '<br />' . sprintf($GLOBALS['LANG']->getLL('checkDependencies_ignored'), $depK) . ' <input type="hidden" value="1" name="depsolver[ignore][' . $depK . ']" />'; $depIgnore = true; continue; } if ($depK == 'php') { if (!$depV) { continue; } $versionRange = tx_em_Tools::splitVersionRange($depV); $phpv = strstr(PHP_VERSION, '-') ? substr(PHP_VERSION, 0, strpos(PHP_VERSION, '-')) : PHP_VERSION; // Linux distributors like to add suffixes, like in 5.1.2-1. Those must be ignored! if ($versionRange[0] != '0.0.0' && version_compare($phpv, $versionRange[0], '<')) { $msg[] = '<br />' . sprintf($GLOBALS['LANG']->getLL('checkDependencies_php_too_low'), $phpv, $versionRange[0]); $msg[] = ' <input type="checkbox" value="1" name="depsolver[ignore][' . $depK . ']" id="checkIgnore_' . $depK . '" /> <label for="checkIgnore_' . $depK . '">' . $GLOBALS['LANG']->getLL('checkDependencies_ignore_requirement') . '</label>'; $depError = true; continue; } elseif ($versionRange[1] != '0.0.0' && version_compare($phpv, $versionRange[1], '>')) { $msg[] = '<br />' . sprintf($GLOBALS['LANG']->getLL('checkDependencies_php_too_high'), $phpv, $versionRange[1]); $msg[] = ' <input type="checkbox" value="1" name="depsolver[ignore][' . $depK . ']" id="checkIgnore_' . $depK . '" /> <label for="checkIgnore_' . $depK . '">' . $GLOBALS['LANG']->getLL('checkDependencies_ignore_requirement') . '</label>'; $depError = true; continue; } } elseif ($depK == 'typo3') { if (!$depV) { continue; } // if the current TYPO3 version is a development version (like TYPO3 4.4-dev), // then it should behave like TYPO3 4.4.0 $t3version = TYPO3_version; if (stripos($t3version, '-dev') || stripos($t3version, '-alpha') || stripos($t3version, '-beta') || stripos($t3version, '-RC')) { // find the last occurence of "-" and replace that part with a ".0" $t3version = substr($t3version, 0, strrpos($t3version, '-')) . '.0'; } $versionRange = tx_em_Tools::splitVersionRange($depV); if ($versionRange[0] != '0.0.0' && version_compare($t3version, $versionRange[0], '<')) { $msg[] = '<br />' . sprintf($GLOBALS['LANG']->getLL('checkDependencies_typo3_too_low'), $t3version, $versionRange[0]); $msg[] = ' <input type="checkbox" value="1" name="depsolver[ignore][' . $depK . ']" id="checkIgnore_' . $depK . '" /> <label for="checkIgnore_' . $depK . '">' . $GLOBALS['LANG']->getLL('checkDependencies_ignore_requirement') . '</label>'; $depError = true; continue; } elseif ($versionRange[1] != '0.0.0' && version_compare($t3version, $versionRange[1], '>')) { $msg[] = '<br />' . sprintf($GLOBALS['LANG']->getLL('checkDependencies_typo3_too_high'), $t3version, $versionRange[1]); $msg[] = ' <input type="checkbox" value="1" name="depsolver[ignore][' . $depK . ']" id="checkIgnore_' . $depK . '" /> <label for="checkIgnore_' . $depK . '">' . $GLOBALS['LANG']->getLL('checkDependencies_ignore_requirement') . '</label>'; $depError = true; continue; } } elseif (strlen($depK) && !t3lib_extMgm::isLoaded($depK)) { // strlen check for braindead empty dependencies coming from extensions... if (!isset($instExtInfo[$depK])) { $msg[] = '<br />' . sprintf($GLOBALS['LANG']->getLL('checkDependencies_ext_not_available'), $depK); $msg[] = ' ' . t3lib_iconWorks::getSpriteIcon('actions-system-extension-import', array('title' => $GLOBALS['LANG']->getLL('checkDependencies_import_ext'))) . ' <a href="' . t3lib_div::linkThisUrl($this->parentObject->script, array('CMD[importExt]' => $depK, 'CMD[loc]' => 'L', 'CMD[standAlone]' => 1)) . '" target="_blank">' . $GLOBALS['LANG']->getLL('checkDependencies_import_now') . '</a>'; $msg[] = ' <input type="checkbox" value="1" name="depsolver[ignore][' . $depK . ']" id="checkIgnore_' . $depK . '" /> <label for="checkIgnore_' . $depK . '">' . $GLOBALS['LANG']->getLL('checkDependencies_ignore_ext_requirement') . '</label>'; } else { $msg[] = '<br />' . sprintf($GLOBALS['LANG']->getLL('checkDependencies_ext_not_installed'), $depK, $instExtInfo[$depK]['EM_CONF']['title']); $msg[] = ' ' . tx_em_Tools::installButton() . ' <a href="' . t3lib_div::linkThisUrl($this->parentObject->script, array('CMD[showExt]' => $depK, 'CMD[load]' => 1, 'CMD[clrCmd]' => 1, 'CMD[standAlone]' => 1, 'SET[singleDetails]' => 'info')) . '" target="_blank">' . $GLOBALS['LANG']->getLL('checkDependencies_install_now') . '</a>'; $msg[] = ' <input type="checkbox" value="1" name="depsolver[ignore][' . $depK . ']" id="checkIgnore_' . $depK . '" /> <label for="checkIgnore_' . $depK . '">' . $GLOBALS['LANG']->getLL('checkDependencies_ignore_ext_requirement') . '</label>'; } $depError = true; } else { $versionRange = tx_em_Tools::splitVersionRange($depV); if ($versionRange[0] != '0.0.0' && version_compare($instExtInfo[$depK]['EM_CONF']['version'], $versionRange[0], '<')) { $msg[] = '<br />' . sprintf($GLOBALS['LANG']->getLL('checkDependencies_ext_too_low'), $depK, $instExtInfo[$depK]['EM_CONF']['version'], $versionRange[0]); $msg[] = ' <input type="checkbox" value="1" name="depsolver[ignore][' . $depK . ']" id="checkIgnore_' . $depK . '" /> <label for="checkIgnore_' . $depK . '">' . $GLOBALS['LANG']->getLL('checkDependencies_ignore_requirement') . '</label>'; $depError = true; continue; } elseif ($versionRange[1] != '0.0.0' && version_compare($instExtInfo[$depK]['EM_CONF']['version'], $versionRange[1], '>')) { $msg[] = '<br />' . sprintf($GLOBALS['LANG']->getLL('checkDependencies_ext_too_high'), $depK, $instExtInfo[$depK]['EM_CONF']['version'], $versionRange[1]); $msg[] = ' <input type="checkbox" value="1" name="depsolver[ignore][' . $depK . ']" id="checkIgnore_' . $depK . '" /> <label for="checkIgnore_' . $depK . '">' . $GLOBALS['LANG']->getLL('checkDependencies_ignore_requirement') . '</label>'; $depError = true; continue; } } } } if (($depError || $depIgnore) && $this->parentObject instanceof SC_mod_tools_em_index) { $content .= $this->parentObject->doc->section($GLOBALS['LANG']->getLL('removeExtFromList_dependency_error'), implode('<br />', $msg), 0, 1, 2); } // Check conflicts with other extensions: $conflictError = false; $conflictIgnore = false; $msg = array(); if (isset($conf['constraints']['conflicts']) && is_array($conf['constraints']['conflicts'])) { foreach ((array) $conf['constraints']['conflicts'] as $conflictK => $conflictV) { if ($depsolver['ignore'][$conflictK]) { $msg[] = '<br />' . sprintf($GLOBALS['LANG']->getLL('checkDependencies_conflict_ignored'), $conflictK) . ' <input type="hidden" value="1" name="depsolver[ignore][' . $conflictK . ']" />'; $conflictIgnore = true; continue; } if (t3lib_extMgm::isLoaded($conflictK)) { $versionRange = tx_em_Tools::splitVersionRange($conflictV); if ($versionRange[0] != '0.0.0' && version_compare($instExtInfo[$conflictK]['EM_CONF']['version'], $versionRange[0], '<')) { continue; } elseif ($versionRange[1] != '0.0.0' && version_compare($instExtInfo[$conflictK]['EM_CONF']['version'], $versionRange[1], '>')) { continue; } $msg[] = sprintf($GLOBALS['LANG']->getLL('checkDependencies_conflict_remove'), $extKey, $conflictK, $instExtInfo[$conflictK]['EM_CONF']['title'], $conflictK, $extKey); $msg[] = ' ' . tx_em_Tools::removeButton() . ' <a href="' . htmlspecialchars(t3lib_div::linkThisScript(array('CMD[showExt]' => $conflictK, 'CMD[remove]' => 1, 'CMD[clrCmd]' => 1, 'CMD[standAlone]' => 1, 'SET[singleDetails]' => 'info'))) . '" target="_blank">' . $GLOBALS['LANG']->getLL('checkDependencies_remove_now') . '</a>'; $msg[] = ' <input type="checkbox" value="1" name="depsolver[ignore][' . $conflictK . ']" id="checkIgnore_' . $conflictK . '" /> <label for="checkIgnore_' . $conflictK . '">' . $GLOBALS['LANG']->getLL('checkDependencies_ignore_conflict') . '</label>'; $conflictError = true; } } } if ($conflictError || $conflictIgnore) { $content .= $this->parentObject->doc->section($GLOBALS['LANG']->getLL('checkDependencies_conflict_error'), implode('<br />', $msg), 0, 1, 2); } // Check suggests on other extensions: if (isset($conf['constraints']['suggests']) && is_array($conf['constraints']['suggests'])) { $suggestion = false; $suggestionIgnore = false; $msg = array(); foreach ($conf['constraints']['suggests'] as $suggestK => $suggestV) { if ($depsolver['ignore'][$suggestK]) { $msg[] = '<br />' . sprintf($GLOBALS['LANG']->getLL('checkDependencies_suggestion_ignored'), $suggestK) . ' <input type="hidden" value="1" name="depsolver[ignore][' . $suggestK . ']" />'; $suggestionIgnore = true; continue; } if (!t3lib_extMgm::isLoaded($suggestK)) { if (!isset($instExtInfo[$suggestK])) { $msg[] = sprintf($GLOBALS['LANG']->getLL('checkDependencies_suggest_import'), $suggestK); $msg[] = ' ' . t3lib_iconWorks::getSpriteIcon('actions-system-extension-import', array('title' => $GLOBALS['LANG']->getLL('checkDependencies_import_ext'))) . ' <a href="' . t3lib_div::linkThisScript(array('CMD[importExt]' => $suggestK, 'CMD[loc]' => 'L', 'CMD[standAlone]' => 1)) . '" target="_blank">' . $GLOBALS['LANG']->getLL('checkDependencies_import_now') . '</a>'; $msg[] = ' <input type="checkbox" value="1" name="depsolver[ignore][' . $suggestK . ']" id="checkIgnore_' . $suggestK . '" /> <label for="checkIgnore_' . $suggestK . '">' . $GLOBALS['LANG']->getLL('checkDependencies_ignore_suggestion') . '</label>'; } else { $msg[] = sprintf($GLOBALS['LANG']->getLL('checkDependencies_suggest_installation'), $suggestK, $instExtInfo[$suggestK]['EM_CONF']['title']); $msg[] = ' ' . tx_em_Tools::installButton() . ' <a href="' . htmlspecialchars(t3lib_div::linkThisScript(array('CMD[showExt]' => $suggestK, 'CMD[load]' => 1, 'CMD[clrCmd]' => 1, 'CMD[standAlone]' => 1, 'SET[singleDetails]' => 'info'))) . '" target="_blank">' . $GLOBALS['LANG']->getLL('checkDependencies_install_now') . '</a>'; $msg[] = ' <input type="checkbox" value="1" name="depsolver[ignore][' . $suggestK . ']" id="checkIgnore_' . $suggestK . '" /> <label for="checkIgnore_' . $suggestK . '">' . $GLOBALS['LANG']->getLL('checkDependencies_ignore_suggestion') . '</label>'; } $suggestion = true; } } if ($suggestion || $suggestionIgnore) { $content .= $this->parentObject->doc->section(sprintf($GLOBALS['LANG']->getLL('checkDependencies_exts_suggested_by_ext'), $extKey), implode('<br />', $msg), 0, 1, 1); } } if ($depError || $conflictError || $suggestion) { foreach ($this->parentObject->CMD as $k => $v) { $content .= '<input type="hidden" name="CMD[' . $k . ']" value="' . $v . '" />'; } $content .= '<br /><br /><input type="submit" value="' . $GLOBALS['LANG']->getLL('checkDependencies_try_again') . '" />'; if (t3lib_div::_GP('nodoc')) { $content .= '<input type="hidden" name="nodoc" value="1" />'; } return array('returnCode' => FALSE, 'html' => '<form action="' . $this->parentObject->script . '" method="post" name="depform">' . $content . '</form>'); } return array('returnCode' => TRUE); }