/**
  * @param UUID[] $missing
  * @return PostRevision
  */
 protected function createFakePosts(array $missing)
 {
     $parents = $this->treeRepository->fetchParentMap($missing);
     $posts = array();
     foreach ($missing as $uuid) {
         $alpha = $uuid->getAlphadecimal();
         if (!isset($parents[$alpha])) {
             wfDebugLog('Flow', __METHOD__ . ": Unable not locate parent for postid {$alpha}");
             continue;
         }
         $content = wfMessage('flow-stub-post-content')->text();
         $username = wfMessage('flow-system-usertext')->text();
         $user = User::newFromName($username);
         // create a stub post instead of failing completely
         $post = PostRevision::newFromId($uuid, $user, $content, 'wikitext');
         $post->setReplyToId($parents[$alpha]);
         $posts[$alpha] = $post;
     }
     return $posts;
 }
 /**
  * @param UUID[] $topicIds
  * @return PostRevision[]
  * @throws InvalidDataException
  */
 public function getMulti(array $topicIds)
 {
     if (!$topicIds) {
         return array();
     }
     // load posts for all located post ids
     $allPostIds = $this->fetchRelatedPostIds($topicIds);
     $queries = array();
     foreach ($allPostIds as $postId) {
         $queries[] = array('rev_type_id' => $postId);
     }
     $found = $this->storage->findMulti('PostRevision', $queries, array('sort' => 'rev_id', 'order' => 'DESC', 'limit' => 1));
     /** @var PostRevision[] $posts */
     $posts = $children = array();
     foreach ($found as $indexResult) {
         $post = reset($indexResult);
         // limit => 1 means only 1 result per query
         if (isset($posts[$post->getPostId()->getAlphadecimal()])) {
             throw new InvalidDataException('Multiple results for id: ' . $post->getPostId()->getAlphadecimal(), 'fail-load-data');
         }
         $posts[$post->getPostId()->getAlphadecimal()] = $post;
     }
     $prettyPostIds = array();
     foreach ($allPostIds as $id) {
         $prettyPostIds[] = $id->getAlphadecimal();
     }
     $missing = array_diff($prettyPostIds, array_keys($posts));
     if ($missing) {
         // convert string uuid's into UUID objects
         /** @var UUID[] $missingUUID */
         $missingUUID = array_map(array('Flow\\Model\\UUID', 'create'), $missing);
         // we'll need to know parents to add stub post correctly in post hierarchy
         $parents = $this->treeRepo->fetchParentMap($missingUUID);
         $missingParents = array_diff($missing, array_keys($parents));
         if ($missingParents) {
             // if we can't fetch a post's original position in the tree
             // hierarchy, we can't create a stub post to display, so bail
             throw new InvalidDataException('Missing Posts & parents: ' . json_encode($missingParents), 'fail-load-data');
         }
         foreach ($missingUUID as $postId) {
             $content = wfMessage('flow-stub-post-content')->text();
             $username = wfMessage('flow-system-usertext')->text();
             $user = \User::newFromName($username);
             // create a stub post instead of failing completely
             $post = PostRevision::newFromId($postId, $user, $content, 'wikitext');
             $post->setReplyToId($parents[$postId->getAlphadecimal()]);
             $posts[$postId->getAlphadecimal()] = $post;
             wfWarn('Missing Posts: ' . FormatJson::encode($missing));
         }
     }
     // another helper to catch bugs in dev
     $extra = array_diff(array_keys($posts), $prettyPostIds);
     if ($extra) {
         throw new InvalidDataException('Found unrequested posts: ' . FormatJson::encode($extra), 'fail-load-data');
     }
     // populate array of children
     foreach ($posts as $post) {
         if ($post->getReplyToId()) {
             $children[$post->getReplyToId()->getAlphadecimal()][$post->getPostId()->getAlphadecimal()] = $post;
         }
     }
     $extraParents = array_diff(array_keys($children), $prettyPostIds);
     if ($extraParents) {
         throw new InvalidDataException('Found posts with unrequested parents: ' . FormatJson::encode($extraParents), 'fail-load-data');
     }
     foreach ($posts as $postId => $post) {
         $postChildren = array();
         $postDepth = 0;
         // link parents to their children
         if (isset($children[$postId])) {
             // sort children with oldest items first
             ksort($children[$postId]);
             $postChildren = $children[$postId];
         }
         // determine threading depth of post
         $replyToId = $post->getReplyToId();
         while ($replyToId && isset($children[$replyToId->getAlphadecimal()])) {
             $postDepth++;
             $replyToId = $posts[$replyToId->getAlphadecimal()]->getReplyToId();
         }
         $post->setChildren($postChildren);
         $post->setDepth($postDepth);
     }
     // return only the requested posts, rest are available as children.
     // Return in same order as requested
     /** @var PostRevision[] $roots */
     $roots = array();
     foreach ($topicIds as $id) {
         $roots[$id->getAlphadecimal()] = $posts[$id->getAlphadecimal()];
     }
     // Attach every post in the tree to its root. setRootPost
     // recursively applies it to all children as well.
     foreach ($roots as $post) {
         $post->setRootPost($post);
     }
     return $roots;
 }