/**
  * @param stdClass $row
  * @return array
  * @throws TimestampException
  * @throws \Flow\Exception\FlowException
  * @throws \Flow\Exception\InvalidInputException
  */
 public function update($row)
 {
     $uuid = UUID::create($row->workflow_id);
     switch ($row->workflow_type) {
         case 'discussion':
             $revision = $this->storage->get('Header', $uuid);
             break;
         case 'topic':
             // fetch topic (has same id as workflow) via RootPostLoader so
             // all children are populated
             $revision = $this->rootPostLoader->get($uuid);
             break;
         default:
             throw new FlowException('Unknown workflow type: ' . $row->workflow_type);
     }
     if (!$revision) {
         return array();
     }
     $timestamp = $this->getUpdateTimestamp($revision)->getTimestamp(TS_MW);
     if ($timestamp === $row->workflow_last_update_timestamp) {
         // correct update timestamp already, nothing to update
         return array();
     }
     return array('workflow_last_update_timestamp' => $timestamp);
 }
 /**
  * @param ResultWrapper $workflows
  * @return PostRevision[]
  */
 public function getRoots(ResultWrapper $workflows)
 {
     $roots = array();
     foreach ($workflows as $row) {
         $roots[$row->workflow_id] = UUID::create($row->workflow_id);
     }
     // we need to fetch all data via rootloader because we'll want children
     // to be populated
     return $this->rootPostLoader->getMulti($roots);
 }
 /**
  * Loads the post referenced by $postId. Returns null when:
  *    $postId does not belong to the workflow
  *    The user does not have view access to the topic title
  *    The user does not have view access to the referenced post
  * All these conditions add a relevant error message to $this->errors when returning null
  *
  * @param UUID|string $postId The post being requested
  * @return PostRevision|null
  */
 protected function loadRequestedPost($postId)
 {
     if (!$postId instanceof UUID) {
         $postId = UUID::create($postId);
     }
     if ($this->rootLoader === null) {
         // Since there is no root loader the full tree is already loaded
         $topicTitle = $root = $this->loadRootPost();
         if (!$topicTitle) {
             return null;
         }
         $post = $root->getDescendant($postId);
         if ($post === null) {
             // The requested postId is not a member of the current workflow
             $this->addError('post', $this->context->msg('flow-error-invalid-postId', $postId->getAlphadecimal()));
             return null;
         }
     } else {
         // Load the post and its root
         $found = $this->rootLoader->getWithRoot($postId);
         if (!$found['post'] || !$found['root'] || !$found['root']->getPostId()->equals($this->workflow->getId())) {
             $this->addError('post', $this->context->msg('flow-error-invalid-postId', $postId->getAlphadecimal()));
             return null;
         }
         $this->topicTitle = $topicTitle = $found['root'];
         $post = $found['post'];
         // using the path to the root post, we can know the post's depth
         $rootPath = $this->rootLoader->getTreeRepo()->findRootPath($postId);
         $post->setDepth(count($rootPath) - 1);
         $post->setRootPost($found['root']);
     }
     if ($this->permissions->isAllowed($topicTitle, 'view') && $this->permissions->isAllowed($post, 'view')) {
         return $post;
     }
     $this->addError('moderation', $this->context->msg('flow-error-not-allowed'));
     return null;
 }