Issue #3483: parent_id not always available as index
[civicrm-core.git] / CRM / Extension / Upgrades.php
index d26a266ff6e9d9fa254a5b9165c720708a60f95a..6d5991fa55b1a87cab6c6dd9ccee299b14f5bd31 100644 (file)
@@ -69,9 +69,27 @@ class CRM_Extension_Upgrades {
 
     CRM_Utils_Hook::upgrade('enqueue', $queue);
 
+    // dev/core#1618 When Extension Upgrades are run reconcile log tables
+    $task = new CRM_Queue_Task(
+      [__CLASS__, 'upgradeLogTables'],
+      [],
+      ts('Update log tables')
+    );
+    // Set weight low so that it will be run last.
+    $queue->createItem($task, -2);
+
     return $queue;
   }
 
+  /**
+   * Update log tables following execution of extension upgrades
+   */
+  public static function upgradeLogTables() {
+    $logging = new CRM_Logging_Schema();
+    $logging->fixSchemaDifferences();
+    return TRUE;
+  }
+
   /**
    * @return array
    *   Array(string $extKey => CRM_Extension_Upgrader_Interface $upgrader)
@@ -109,7 +127,10 @@ class CRM_Extension_Upgrades {
   }
 
   /**
+   * Sorts active extensions according to their dependencies
+   *
    * @param string[] $keys
+   *   Names of all active modules
    *
    * @return string[]
    * @throws \CRM_Extension_Exception
@@ -119,30 +140,25 @@ class CRM_Extension_Upgrades {
   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();