public function testSortByOption() { $user = User::newFromId(1); $user->setOption('flow-topiclist-sortby', ''); // reset flow state, so everything ($container['permissions']) // uses this particular $user \FlowHooks::resetFlowExtension(); Container::reset(); $container = Container::getContainer(); $container['user'] = $user; $ctx = $this->getMock('IContextSource'); $ctx->expects($this->any())->method('getUser')->will($this->returnValue($user)); $workflow = Workflow::create('discussion', Title::newFromText('Talk:Flow_QA')); $block = new TopicListBlock($workflow, Container::get('storage')); $block->init($ctx, 'view'); $res = $block->renderApi(array()); $this->assertEquals('newest', $res['sortby'], 'With no sortby defaults to newest'); $res = $block->renderApi(array('sortby' => 'foo')); $this->assertEquals('newest', $res['sortby'], 'With invalid sortby defaults to newest'); $res = $block->renderApi(array('sortby' => 'updated')); $this->assertEquals('updated', $res['sortby'], 'With sortby updated output changes to updated'); $res = $block->renderApi(array()); $this->assertEquals('newest', $res['sortby'], 'Sort still defaults to newest'); $res = $block->renderApi(array('sortby' => 'updated', 'savesortby' => '1')); $this->assertEquals('updated', $res['sortby'], 'Request saving sortby option'); $res = $block->renderApi(array()); $this->assertEquals('updated', $res['sortby'], 'Default sortby now changed to updated'); $res = $block->renderApi(array('sortby' => '')); $this->assertEquals('updated', $res['sortby'], 'Default sortby with blank sortby still uses user default'); }
public function setUp() { parent::setUp(); // reset flow state, so everything ($container['permissions']) // uses this particular $user \FlowHooks::resetFlowExtension(); Container::reset(); $container = Container::getContainer(); $container['user'] = User::newFromName('127.0.0.1', false); }
protected function doDBUpdates() { // get "User:" namespace prefix in wiki language global $wgContLang; $namespaces = $wgContLang->getFormattedNamespaces(); $title = Title::newFromText(wfMessage('flow-ve-mention-template-title')->inContentLanguage()->plain(), NS_TEMPLATE); $article = new Article($title); $page = $article->getPage(); if ($page->getRevision() !== null) { // template already exists, don't overwrite it return true; } $status = $page->doEditContent(new WikitextContent('@[[' . $namespaces[NS_USER] . ':{{{1|Example}}}|{{{2|{{{1|Example}}}}}}]]'), '/* Automatically created by Flow */', EDIT_FORCE_BOT | EDIT_SUPPRESS_RC, false, FlowHooks::getOccupationController()->getTalkpageManager()); return $status->isOK(); }
public function execute() { global $wgLang, $wgParser; $provided = $this->getArg(0); $namespace = $wgLang->getNsIndex($provided); if (!$namespace) { $this->error("Invalid namespace provided: {$provided}"); return; } $namespaceName = $wgLang->getNsText($namespace); if (!MWNamespace::hasSubpages($namespace)) { $this->error("Subpages are not enabled in the {$namespaceName} namespace."); $this->error("In order to convert this namespace to Flow, you must enable subpages using:"); $this->error("\$wgNamespacesWithSubpages[{$namespace}] = true;"); return; } $noConvertTemplates = explode(',', $this->getOption('no-convert-templates', '')); if ($noConvertTemplates === array('')) { // explode( ',', '' ) returns array( '' ) $noConvertTemplates = array(); } // Convert to Title objects foreach ($noConvertTemplates as &$template) { $title = Title::newFromText($template, NS_TEMPLATE); if (!$title) { $this->error("Invalid template name: {$template}"); return; } $template = $title; } // @todo send to prod logger? $logger = new MaintenanceDebugLogger($this); $dbw = wfGetDB(DB_MASTER); $converter = new \Flow\Import\Converter($dbw, Flow\Container::get('importer'), $logger, FlowHooks::getOccupationController()->getTalkpageManager(), new Flow\Import\Wikitext\ConversionStrategy($wgParser, new Flow\Import\NullImportSourceStore(), $logger, $noConvertTemplates, $this->getOption('archive-pattern', null))); $logger->info("Starting conversion of {$namespaceName} namespace"); // Iterate over all existing pages of the namespace. $it = new NamespaceIterator($dbw, $namespace); // NamespaceIterator is an IteratorAggregate. Get an Iterator // so we can wrap that. $it = $it->getIterator(); $converter->convertAll($it); $logger->info("Finished conversion of {$namespaceName} namespace"); }
public function execute() { $logger = new MaintenanceDebugLogger($this); if ($this->getOption('debug')) { $logger->setMaximumLevel(LogLevel::DEBUG); } else { $logger->setMaximumLevel(LogLevel::INFO); } $importer = Flow\Container::get('importer'); $talkpageManagerUser = FlowHooks::getOccupationController()->getTalkpageManager(); $dbw = wfGetDB(DB_MASTER); $strategy = new ConversionStrategy($dbw, new FileImportSourceStore($this->getOption('logfile')), new LocalApiBackend($talkpageManagerUser), Container::get('url_generator'), $talkpageManagerUser, Container::get('controller.notification')); $converter = new \Flow\Import\Converter($dbw, $importer, $logger, $talkpageManagerUser, $strategy); $startId = $this->getOption('startId'); $stopId = $this->getOption('stopId'); $logger->info("Starting full wiki LQT conversion of all pages with use-liquid-threads property"); $titles = new PagesWithPropertyIterator($dbw, 'use-liquid-threads', $startId, $stopId); $converter->convertAll($titles); $logger->info("Finished conversion"); }
/** * @param string $action * @param OutputPage|null $output * @throws ErrorPageError * @throws FlowException */ public function showForAction($action, OutputPage $output = null) { $container = Container::getContainer(); $occupationController = \FlowHooks::getOccupationController(); if ($output === null) { $output = $this->context->getOutput(); } // Check if this is actually a Flow page. if (!$this->page instanceof WikiPage && !$this->page instanceof Article) { throw new ErrorPageError('nosuchaction', 'flow-action-unsupported'); } $title = $this->page->getTitle(); if (!$occupationController->isTalkpageOccupied($title)) { throw new ErrorPageError('nosuchaction', 'flow-action-unsupported'); } // @todo much of this seems to duplicate BoardContent::getParserOutput $view = new View($container['url_generator'], $container['lightncandy'], $output, $container['flow_actions']); $request = $this->context->getRequest(); // BC for urls pre july 2014 with workflow query parameter $redirect = $this->getRedirectUrl($request, $title); if ($redirect) { $output->redirect($redirect); return; } $action = $request->getVal('action', 'view'); try { /** @var WorkflowLoaderFactory $factory */ $factory = $container['factory.loader.workflow']; $loader = $factory->createWorkflowLoader($title); if ($title->getNamespace() === NS_TOPIC && $loader->getWorkflow()->getType() !== 'topic') { // @todo better error handling throw new FlowException('Invalid title: uuid is not a topic'); } $view->show($loader, $action); } catch (FlowException $e) { $e->setOutput($output); throw $e; } }
public function execute() { $cacheDir = $this->getOption('cacheremoteapidir'); if (!is_dir($cacheDir)) { if (!mkdir($cacheDir)) { throw new Flow\Exception\FlowException('Provided dir for caching remote api calls is not creatable.'); } } if (!is_writable($cacheDir)) { throw new Flow\Exception\FlowException('Provided dir for caching remote api calls is not writable.'); } $api = new RemoteApiBackend($this->getOption('remoteapi'), $cacheDir); $importer = Flow\Container::get('importer'); $importer->setAllowUnknownUsernames(true); $talkPageManagerUser = \FlowHooks::getOccupationController()->getTalkpageManager(); $srcPageName = $this->getOption('srcpage'); if ($this->hasOption('dstpage')) { $dstPageName = $this->getOption('dstpage'); } else { $dstPageName = $srcPageName; } $dstTitle = Title::newFromText($dstPageName); $source = new LiquidThreadsApiImportSource($api, $srcPageName, $talkPageManagerUser); $logFilename = $this->getOption('logfile'); $sourceStore = new FileImportSourceStore($logFilename); $logger = new MaintenanceDebugLogger($this); if ($this->getOption('debug')) { $logger->setMaximumLevel(LogLevel::DEBUG); } else { $logger->setMaximumLevel(LogLevel::INFO); } $importer->setLogger($logger); $api->setLogger($logger); $logger->info("Starting LQT conversion of page {$srcPageName}"); $importer->import($source, $dstTitle, $sourceStore); $logger->info("Finished LQT conversion of page {$srcPageName}"); }
public function execute() { $talkPageManagerUser = \FlowHooks::getOccupationController()->getTalkpageManager(); $api = new LocalApiBackend($talkPageManagerUser); $importer = Container::get('importer'); $srcPageName = $this->getOption('srcpage'); $logFilename = $this->getOption('logfile'); $sourceStore = new FileImportSourceStore($logFilename); $dbw = wfGetDB(DB_MASTER); $logger = new MaintenanceDebugLogger($this); if ($this->getOption('debug')) { $logger->setMaximumLevel(LogLevel::DEBUG); } else { $logger->setMaximumLevel(LogLevel::INFO); } $strategy = new LiquidThreadsApiConversionStrategy($dbw, $sourceStore, $api, Container::get('url_generator'), $talkPageManagerUser, Container::get('controller.notification')); $importer->setLogger($logger); $api->setLogger($logger); $converter = new \Flow\Import\Converter($dbw, $importer, $logger, $talkPageManagerUser, $strategy); $logger->info("Starting LQT conversion of page {$srcPageName}"); $srcTitle = \Title::newFromText($srcPageName); $converter->convertAll(array($srcTitle)); $logger->info("Finished LQT conversion of page {$srcPageName}"); }
$c['factory.loader.workflow'] = function ($c) { global $wgFlowDefaultWorkflow; return new Flow\WorkflowLoaderFactory($c['storage'], $c['factory.block'], $c['submission_handler'], $wgFlowDefaultWorkflow); }; // Initialized in FlowHooks to facilitate only loading the flow container // when flow is specifically requested to run. Extension initialization // must always happen before calling flow code. $c['occupation_controller'] = FlowHooks::getOccupationController(); $c['controller.notification'] = function ($c) { global $wgContLang; return new Flow\NotificationController($wgContLang); }; // Initialized in FlowHooks to faciliate only loading the flow container // when flow is specifically requested to run. Extension initialization // must always happen before calling flow code. $c['controller.abusefilter'] = FlowHooks::getAbuseFilter(); $c['controller.spamregex'] = function ($c) { return new Flow\SpamFilter\SpamRegex(); }; $c['controller.spamblacklist'] = function ($c) { return new Flow\SpamFilter\SpamBlacklist(); }; $c['controller.confirmedit'] = function ($c) { return new Flow\SpamFilter\ConfirmEdit(); }; $c['controller.contentlength'] = function ($c) { global $wgMaxArticleSize; // wgMaxArticleSize is in kilobytes, // whereas this really is characters (it uses // mb_strlen), so it's not the exact same limit. $maxCharCount = $wgMaxArticleSize * 1024;
/** * Blocks topics from being deleted using the core deletion process, since it * doesn't work. * * @param WikiPage &$article Page the user requested to delete * @param User &$user User who requested to delete the article * @param string &$reason Reason given for deletion * @param string &$error Error explaining why we are not allowing the deletion * @return bool False if it is a Topic (to block it); otherwise, true */ public static function onArticleDelete(WikiPage &$article, User &$user, &$reason, &$error) { $title = $article->getTitle(); if ($title->inNamespace(NS_TOPIC)) { $error = FlowHooks::getTopicDeletionError($title); return false; } return true; }
/** * @dataProvider onIRCLineUrlProvider */ public function testOnIRCLineUrl($message, $metadataGen, $expectedQuery) { $user = User::newFromName('127.0.0.1', false); // reset flow state, so everything ($container['permissions']) // uses this particular $user \FlowHooks::resetFlowExtension(); Container::reset(); $container = Container::getContainer(); $container['user'] = $user; $rc = new RecentChange(); $rc->mAttribs = array('rc_namespace' => 0, 'rc_title' => 'Main Page', 'rc_source' => RecentChangesListener::SRC_FLOW); $metadata = $metadataGen($user); Container::get('formatter.irclineurl')->associate($rc, $metadata); $url = 'unset'; $query = 'unset'; $this->assertTrue(FlowHooks::onIRCLineURL($url, $query, $rc)); $expectedQuery['title'] = $metadata['workflow']->getArticleTitle()->getPrefixedDBkey(); $parts = parse_url($url); $this->assertArrayHasKey('query', $parts, $url); parse_str($parts['query'], $queryParts); foreach ($expectedQuery as $key => $value) { $this->assertEquals($value, $queryParts[$key], "Query part {$key}"); } $this->assertEquals('', $query, $message); }