You are here

protected static function RevisionTreeIndex::doBuildTree in Multiversion 8

Same name and namespace in other branches
  1. 8.2 src/Entity/Index/RevisionTreeIndex.php \Drupal\multiversion\Entity\Index\RevisionTreeIndex::doBuildTree()

Recursive helper method to build the revision tree.

@todo: {@link https://www.drupal.org/node/2597430 Implement 'deleted_conflicts'.}

Return value

array Returns an array containing the built tree, open revisions, default revision, default branch and conflicts.

1 call to RevisionTreeIndex::doBuildTree()
RevisionTreeIndex::buildTree in src/Entity/Index/RevisionTreeIndex.php
Helper method to build the revision tree.

File

src/Entity/Index/RevisionTreeIndex.php, line 302

Class

RevisionTreeIndex
The revision tree index.

Namespace

Drupal\multiversion\Entity\Index

Code

protected static function doBuildTree($uuid, $revs, $revs_info, $parse = 0, &$tree = [], &$open_revs = [], &$conflicts = []) {
  foreach ($revs as $rev => $parent_revs) {
    foreach ($parent_revs as $parent_rev) {
      if ($rev == 0) {
        continue;
      }
      if ($parent_rev == $parse) {

        // Avoid bad data to cause endless loops.
        // @todo: {@link https://www.drupal.org/node/2597434 Needs test.}
        if ($rev == $parse) {
          throw new \InvalidArgumentException('Child and parent revision can not be the same value.');
        }

        // Build an element structure compatible with Drupal's Render API.
        $i = count($tree);
        $tree[$i] = [
          '#type' => 'rev',
          '#uuid' => $uuid,
          '#rev' => $rev,
          '#rev_info' => [
            'status' => isset($revs_info["{$uuid}:{$rev}"]['status']) ? $revs_info["{$uuid}:{$rev}"]['status'] : 'missing',
            'default' => FALSE,
            'open_rev' => FALSE,
            'conflict' => FALSE,
          ],
          'children' => [],
        ];

        // Recurse down through the children.
        self::doBuildTree($uuid, $revs, $revs_info, $rev, $tree[$i]['children'], $open_revs, $conflicts);

        // Find open revisions and conflicts. Only revisions with no children,
        // and that are not missing can be an open revision or a conflict.
        if (empty($tree[$i]['children']) && $tree[$i]['#rev_info']['status'] != 'missing') {
          $tree[$i]['#rev_info']['open_rev'] = TRUE;
          $open_revs[$rev] = $tree[$i];

          // All open revisions, except deleted and default revisions, are
          // conflicts by definition. We will revert the conflict flag when we
          // find the default revision later on.
          if ($tree[$i]['#rev_info']['status'] != 'deleted') {
            $tree[$i]['#rev_info']['conflict'] = TRUE;
            $conflicts[$rev] = $tree[$i];
          }
        }
      }
    }
  }

  // Now when the full tree is built we'll find the default revision and
  // its branch.
  if ($parse == 0) {
    $default_rev = 0;
    uasort($open_revs, [
      __CLASS__,
      'sortRevisions',
    ]);
    $default_rev = reset($open_revs);

    // Remove the default revision from the conflicts array and sort it.
    unset($conflicts[$default_rev['#rev']]);
    uasort($conflicts, [
      __CLASS__,
      'sortRevisions',
    ]);

    // Update the default revision in the tree and sort it.
    self::updateDefaultRevision($tree, $default_rev);
    self::sortTree($tree);

    // Find the branch of the default revision.
    $default_branch = [];
    $rev = $default_rev['#rev'];
    while ($rev != 0) {
      $default_branch[$rev] = isset($revs_info["{$uuid}:{$rev}"]['status']) ? $revs_info["{$uuid}:{$rev}"]['status'] : 'missing';

      // Only the first parent gets included in the default branch.
      $rev = $revs[$rev][0];
    }
    return [
      'tree' => $tree,
      'default_rev' => $default_rev,
      'default_branch' => array_reverse($default_branch),
      'open_revs' => $open_revs,
      'conflicts' => $conflicts,
    ];
  }
}