}
/**
+ * Sorts active extensions according to their dependencies
+ *
* @param string[] $keys
+ * Names of all active modules
*
* @return string[]
* @throws \CRM_Extension_Exception
protected static function sortKeys($keys) {
$infos = CRM_Extension_System::singleton()->getMapper()->getAllInfos();
- // Start with our inputs in a normalized form.
+ // Ensure a stable starting order.
$todoKeys = array_unique($keys);
sort($todoKeys);
- // Goal: Add all active items to $sorter and flag $doneKeys['org.example.foobar']=1.
- $doneKeys = [];
$sorter = new \MJS\TopSort\Implementations\FixedArraySort();
- while (!empty($todoKeys)) {
- $key = array_shift($todoKeys);
- if (isset($doneKeys[$key])) {
- continue;
- }
- $doneKeys[$key] = 1;
-
+ foreach ($todoKeys as $key) {
/** @var CRM_Extension_Info $info */
- $info = @$infos[$key];
+ $info = $infos[$key] ?? NULL;
- if ($info && $info->requires) {
- $sorter->add($key, $info->requires);
- $todoKeys = array_merge($todoKeys, $info->requires);
+ // Add dependencies
+ if ($info) {
+ // Filter out missing dependencies; missing modules cannot be upgraded
+ $requires = array_intersect($info->requires ?? [], $keys);
+ $sorter->add($key, $requires);
}
+ // This shouldn't ever happen if this function is being passed a list of active extensions.
else {
- $sorter->add($key, []);
+ throw new CRM_Extension_Exception('Invalid extension key: "' . $key . '"');
}
}
return $sorter->sort();