/**
  * @param Workflow $workflow
  * @param IContextSource $context
  * @param AbstractBlock[] $blocks
  * @param string $action
  * @param array $parameters
  * @return AbstractBlock[]
  * @throws InvalidActionException
  * @throws InvalidDataException
  */
 public function handleSubmit(Workflow $workflow, IContextSource $context, array $blocks, $action, array $parameters)
 {
     // since this is a submit force dbFactory to always return master
     $this->dbFactory->forceMaster();
     /** @var Block[] $interestedBlocks */
     $interestedBlocks = array();
     foreach ($blocks as $block) {
         // This is just a check whether the block understands the action,
         // Doesn't consider permissions
         if ($block->canSubmit($action)) {
             $block->init($context, $action);
             $interestedBlocks[] = $block;
         }
     }
     if (!$interestedBlocks) {
         if (!$blocks) {
             throw new InvalidDataException('No Blocks?!?', 'fail-load-data');
         }
         $type = array();
         foreach ($blocks as $block) {
             $type[] = get_class($block);
         }
         // All blocks returned null, nothing knows how to handle this action
         throw new InvalidActionException("No block accepted the '{$action}' action: " . implode(',', array_unique($type)), 'invalid-action');
     }
     // Check mediawiki core permissions for title protection, blocked
     // status, etc.
     if (!$workflow->userCan('edit', $context->getUser())) {
         reset($interestedBlocks)->addError('block', wfMessage('blockedtitle'));
         return array();
     }
     $success = true;
     foreach ($interestedBlocks as $block) {
         $name = $block->getName();
         $data = isset($parameters[$name]) ? $parameters[$name] : array();
         $success &= $block->onSubmit($data);
     }
     return $success ? $interestedBlocks : array();
 }
 /**
  * Collects the workflow and header (if it exists) and puts them into the database. Does
  * not commit yet. It is intended for prepareMove to be called from the TitleMove hook,
  * and committed from TitleMoveComplete hook. This ensures that if some error prevents the
  * core transaction from committing this transaction is also not committed.
  *
  * @param int $oldPageId Page ID before move/change
  * @param Title $newPage Page after move/change
  */
 public function prepareMove($oldPageId, Title $newPage)
 {
     if ($this->dbw !== null) {
         throw new FlowException("Already prepared for move from {$oldPageId} to {$newPage->getArticleID()}");
     }
     // All reads must go through master to help ensure consistency
     $this->dbFactory->forceMaster();
     // Open a transaction, this will be closed from self::commit.
     $this->dbw = $this->dbFactory->getDB(DB_MASTER);
     $this->dbw->begin();
     $this->cache->begin();
     // @todo this loads every topic workflow this board has ever seen,
     // would prefer to update db directly but that won't work due to
     // the caching layer not getting updated.  After dropping Flow\Data\Index\*
     // revisit this.
     $found = $this->storage->find('Workflow', array('workflow_wiki' => wfWikiId(), 'workflow_page_id' => $oldPageId));
     if (!$found) {
         throw new FlowException("Could not locate workflow for {$oldPageId}");
     }
     $discussionWorkflow = null;
     foreach ($found as $workflow) {
         if ($workflow->getType() === 'discussion') {
             $discussionWorkflow = $workflow;
         }
         $workflow->updateFromPageId($oldPageId, $newPage);
         $this->storage->put($workflow, array());
     }
     if ($discussionWorkflow === null) {
         throw new FlowException("Main discussion workflow for {$oldPageId} not found");
     }
     $found = $this->storage->find('Header', array('rev_type_id' => $discussionWorkflow->getId()), array('sort' => 'rev_id', 'order' => 'DESC', 'limit' => 1));
     if ($found) {
         $this->header = reset($found);
         $nextHeader = $this->header->newNextRevision($this->nullEditUser, $this->header->getContentRaw(), $this->header->getContentFormat(), 'edit-header', $newPage);
         $this->storage->put($nextHeader, array('workflow' => $discussionWorkflow));
     }
 }