/**
  * @param FormatterRow $row
  * @return array
  * @throws FlowException
  */
 public function buildActions(FormatterRow $row)
 {
     $user = $this->permissions->getUser();
     $workflow = $row->workflow;
     $title = $workflow->getArticleTitle();
     // If a user is blocked from performing actions on this page return
     // an empty array of actions.
     //
     // We only check actual users and not anon's because the anonymous
     // version can be cached and served to many different ip addresses
     // which will not all be blocked.
     if (!$user->isAnon() && ($user->isBlockedFrom($title, true) || !$title->quickUserCan('edit', $user))) {
         return array();
     }
     $revision = $row->revision;
     $action = $revision->getChangeType();
     $workflowId = $workflow->getId();
     $revId = $revision->getRevisionId();
     $postId = method_exists($revision, 'getPostId') ? $revision->getPostId() : null;
     $actionTypes = $this->permissions->getActions()->getValue($action, 'actions');
     if ($actionTypes === null) {
         wfDebugLog('Flow', __METHOD__ . ": No actions defined for action: {$action}");
         return array();
     }
     // actions primarily vary by revision type...
     $links = array();
     foreach ($actionTypes as $type) {
         if (!$this->permissions->isAllowed($revision, $type)) {
             continue;
         }
         switch ($type) {
             case 'thank':
                 if (class_exists('ThanksHooks') && !$user->isAnon() && $revision instanceof PostRevision && $revision->getCreatorId() > 0 && $user->getId() !== $revision->getCreatorId()) {
                     $links['thank'] = $this->urlGenerator->thankAction($postId);
                 }
                 break;
             case 'reply':
                 if (!$postId) {
                     throw new FlowException("{$type} called without \$postId");
                 } elseif (!$revision instanceof PostRevision) {
                     throw new FlowException("{$type} called without PostRevision object");
                 }
                 /*
                  * If the post being replied to is the most recent post
                  * of its depth, the reply link should point to parent
                  */
                 $replyToId = $postId;
                 $replyToRevision = $revision;
                 if ($row->isLastReply) {
                     $replyToId = $replyToRevision->getReplyToId();
                     $replyToRevision = PostCollection::newFromId($replyToId)->getLastRevision();
                 }
                 /*
                  * If the post being replied to is at or exceeds the max
                  * threading depth, the reply link should point to parent.
                  */
                 while ($replyToRevision->getDepth() >= $this->maxThreadingDepth) {
                     $replyToId = $replyToRevision->getReplyToId();
                     $replyToRevision = PostCollection::newFromId($replyToId)->getLastRevision();
                 }
                 $links['reply'] = $this->urlGenerator->replyAction($title, $workflowId, $replyToId, $revision->isTopicTitle());
                 break;
             case 'edit-header':
                 $links['edit'] = $this->urlGenerator->editHeaderAction($title, $workflowId, $revId);
                 break;
             case 'edit-title':
                 if (!$postId) {
                     throw new FlowException("{$type} called without \$postId");
                 }
                 $links['edit'] = $this->urlGenerator->editTitleAction($title, $workflowId, $postId, $revId);
                 break;
             case 'edit-post':
                 if (!$postId) {
                     throw new FlowException("{$type} called without \$postId");
                 }
                 $links['edit'] = $this->urlGenerator->editPostAction($title, $workflowId, $postId, $revId);
                 break;
             case 'undo-edit-header':
             case 'undo-edit-post':
             case 'undo-edit-topic-summary':
                 if (!$revision->isFirstRevision()) {
                     $links['undo'] = $this->urlGenerator->undoAction($revision, $title, $workflowId);
                 }
                 break;
             case 'hide-post':
                 if (!$postId) {
                     throw new FlowException("{$type} called without \$postId");
                 }
                 $links['hide'] = $this->urlGenerator->hidePostAction($title, $workflowId, $postId);
                 break;
             case 'delete-topic':
                 $links['delete'] = $this->urlGenerator->deleteTopicAction($title, $workflowId);
                 break;
             case 'delete-post':
                 if (!$postId) {
                     throw new FlowException("{$type} called without \$postId");
                 }
                 $links['delete'] = $this->urlGenerator->deletePostAction($title, $workflowId, $postId);
                 break;
             case 'suppress-topic':
                 $links['suppress'] = $this->urlGenerator->suppressTopicAction($title, $workflowId);
                 break;
             case 'suppress-post':
                 if (!$postId) {
                     throw new FlowException("{$type} called without \$postId");
                 }
                 $links['suppress'] = $this->urlGenerator->suppressPostAction($title, $workflowId, $postId);
                 break;
             case 'lock-topic':
                 // lock topic link is only available to topics
                 if (!$revision instanceof PostRevision || !$revision->isTopicTitle()) {
                     continue;
                 }
                 $links['lock'] = $this->urlGenerator->lockTopicAction($title, $workflowId);
                 break;
             case 'restore-topic':
                 $moderateAction = $flowAction = null;
                 switch ($revision->getModerationState()) {
                     case AbstractRevision::MODERATED_LOCKED:
                         $moderateAction = 'unlock';
                         $flowAction = 'lock-topic';
                         break;
                     case AbstractRevision::MODERATED_HIDDEN:
                     case AbstractRevision::MODERATED_DELETED:
                     case AbstractRevision::MODERATED_SUPPRESSED:
                         $moderateAction = 'un' . $revision->getModerationState();
                         $flowAction = 'moderate-topic';
                         break;
                 }
                 if (isset($moderateAction) && $moderateAction) {
                     $links[$moderateAction] = $this->urlGenerator->restoreTopicAction($title, $workflowId, $moderateAction, $flowAction);
                 }
                 break;
             case 'restore-post':
                 if (!$postId) {
                     throw new FlowException("{$type} called without \$postId");
                 }
                 $moderateAction = $flowAction = null;
                 switch ($revision->getModerationState()) {
                     case AbstractRevision::MODERATED_HIDDEN:
                     case AbstractRevision::MODERATED_DELETED:
                     case AbstractRevision::MODERATED_SUPPRESSED:
                         $moderateAction = 'un' . $revision->getModerationState();
                         $flowAction = 'moderate-post';
                         break;
                 }
                 if ($moderateAction) {
                     $links[$moderateAction] = $this->urlGenerator->restorePostAction($title, $workflowId, $postId, $moderateAction, $flowAction);
                 }
                 break;
             case 'hide-topic':
                 $links['hide'] = $this->urlGenerator->hideTopicAction($title, $workflowId);
                 break;
                 // Need to use 'edit-topic-summary' to match FlowActions
             // Need to use 'edit-topic-summary' to match FlowActions
             case 'edit-topic-summary':
                 // summarize link is only available to topic workflow
                 if (!in_array($workflow->getType(), array('topic', 'topicsummary'))) {
                     continue;
                 }
                 $links['summarize'] = $this->urlGenerator->editTopicSummaryAction($title, $workflowId);
                 break;
             default:
                 wfDebugLog('Flow', __METHOD__ . ': unkown action link type: ' . $type);
                 break;
         }
     }
     return $links;
 }
 /**
  * @var IContextSource $context
  * @var string $action
  */
 public function init(IContextSource $context, $action)
 {
     $this->context = $context;
     $this->action = $action;
     $this->permissions = Container::get('permissions');
     if (!$context->getUser()->equals($this->permissions->getUser())) {
         throw new PermissionException('Formatting for wrong user: '******' instead of ' . $this->permissions->getUser()->getName());
     }
 }