/** * Lightweight method to get the parser output for a page, checking the parser cache * and so on. Doesn't consider most of the stuff that WikiPage::view is forced to * consider, so it's not appropriate to use there. * * @since 1.16 (r52326) for LiquidThreads * * @param $oldid mixed integer Revision ID or null * @param $user User The relevant user * @return ParserOutput or false if the given revsion ID is not found */ public function getParserOutput($oldid = null, User $user = null) { global $wgEnableParserCache, $wgUser; $user = is_null($user) ? $wgUser : $user; wfProfileIn(__METHOD__); // Should the parser cache be used? $useParserCache = $wgEnableParserCache && $user->getStubThreshold() == 0 && $this->mPage->exists() && $oldid === null; wfDebug(__METHOD__ . ': using parser cache: ' . ($useParserCache ? 'yes' : 'no') . "\n"); if ($user->getStubThreshold()) { wfIncrStats('pcache_miss_stub'); } if ($useParserCache) { $parserOutput = ParserCache::singleton()->get($this, $this->mPage->getParserOptions()); if ($parserOutput !== false) { wfProfileOut(__METHOD__); return $parserOutput; } } // Cache miss; parse and output it. if ($oldid === null) { $text = $this->mPage->getRawText(); } else { $rev = Revision::newFromTitle($this->getTitle(), $oldid); if ($rev === null) { wfProfileOut(__METHOD__); return false; } $text = $rev->getText(); } wfProfileOut(__METHOD__); return $this->getOutputFromWikitext($text, $useParserCache); }
/** * Constructor * * @param WikiPage $page Page we are updating * @throws MWException */ function __construct(WikiPage $page) { parent::__construct(false); // no implicit transaction $this->mPage = $page; if (!$page->exists()) { throw new MWException("Page ID not known, perhaps the page doesn't exist?"); } }
function filter_antispam($formatter, $value, $options) { global $Config; $blacklist_pages = array('BadContent', 'LocalBadContent'); $whitelist_pages = array('GoodContent', 'LocalGoodContent'); if (!in_array($formatter->page->name, $blacklist_pages) and !in_array($formatter->page->name, $whitelist_pages)) { $badcontents_file = !empty($options['.badcontents']) ? $options['.badcontents'] : $Config['badcontents']; if (!file_exists($badcontents_file)) { return $value; } $badcontent = file_get_contents($badcontents_file); foreach ($blacklist_pages as $list) { $p = new WikiPage($list); if ($p->exists()) { $badcontent .= $p->get_raw_body(); } } if (!$badcontent) { return $value; } $badcontents = explode("\n", $badcontent); $pattern[0] = ''; $i = 0; foreach ($badcontents as $line) { if (isset($line[0]) and $line[0] == '#') { continue; } $line = preg_replace('/[ ]*#.*$/', '', $line); $test = @preg_match("/{$line}/i", ""); if ($test === false) { $line = preg_quote($line, '/'); } if ($line) { $pattern[$i] .= $line . '|'; } if (strlen($pattern[$i]) > 4000) { $i++; $pattern[$i] = ''; } } for ($k = 0; $k <= $i; $k++) { $pattern[$k] = '/(' . substr($pattern[$k], 0, -1) . ')/i'; } #foreach ($whitelist_pages as $list) { # $p=new WikiPage($list); # if ($p->exists()) $goodcontent.=$p->get_raw_body(); #} #$goodcontents=explode("\n",$goodcontent); return preg_replace($pattern, "''''''[[HTML(<span class='blocked'>)]]\\1[[HTML(</span>)]]''''''", $value); } return $value; }
/** * @param WikiPage $page Page we are updating * @param integer|null $pageId ID of the page we are updating [optional] * @throws MWException */ function __construct(WikiPage $page, $pageId = null) { parent::__construct(false); // no implicit transaction $this->page = $page; if ($page->exists()) { $this->pageId = $page->getId(); } elseif ($pageId) { $this->pageId = $pageId; } else { throw new MWException("Page ID not known, perhaps the page doesn't exist?"); } }
/** * @param WikiPage $page Page we are updating * @param integer|null $pageId ID of the page we are updating [optional] * @param string|null $timestamp TS_MW timestamp of deletion * @throws MWException */ function __construct(WikiPage $page, $pageId = null, $timestamp = null) { parent::__construct(); $this->page = $page; if ($pageId) { $this->pageId = $pageId; // page ID at time of deletion } elseif ($page->exists()) { $this->pageId = $page->getId(); } else { throw new InvalidArgumentException("Page ID not known. Page doesn't exist?"); } $this->timestamp = $timestamp ?: wfTimestampNow(); }
protected function createPage($page, $text, $model = null) { if (is_string($page)) { $page = Title::newFromText($page); } if ($page instanceof Title) { $page = new WikiPage($page); } if ($page->exists()) { $page->doDeleteArticle("done"); } $page->doEdit($text, "testing", EDIT_NEW); return $page; }
protected function createPage($page, $text, $model = null) { if (is_string($page)) { if (!preg_match('/:/', $page) && ($model === null || $model === CONTENT_MODEL_WIKITEXT)) { $ns = $this->getDefaultWikitextNS(); $page = MWNamespace::getCanonicalName($ns) . ':' . $page; } $page = Title::newFromText($page); } if ($page instanceof Title) { $page = new WikiPage($page); } if ($page->exists()) { $page->doDeleteArticle("done"); } $content = ContentHandler::makeContent($text, $page->getTitle(), $model); $page->doEditContent($content, "testing", EDIT_NEW); return $page; }
/** * Clear the cache when the page is edited */ public static function onArticleSaveComplete(WikiPage &$page, &$user, $text, $summary, $minoredit, $watchthis, $sectionanchor, &$flags, $revision, &$status, $baseRevId) { /** * @var $service ArticleService */ if ($page->exists()) { $id = $page->getId(); F::app()->wg->Memc->delete(self::getCacheKey($id)); if (array_key_exists($id, self::$localCache)) { unset(self::$localCache[$id]); } } return true; }
function macro_FullSearch($formatter, $value = "", &$opts) { global $DBInfo; $needle = $value; if ($value === true) { $needle = $value = $formatter->page->name; $options['noexpr'] = 1; } else { # for MoinMoin compatibility with [[FullSearch("blah blah")]] #$needle = preg_replace("/^('|\")([^\\1]*)\\1/","\\2",$value); $needle = $value; } // for pagination $offset = ''; if (!empty($opts['offset']) and is_numeric($opts['offset'])) { if ($opts['offset'] > 0) { $offset = $opts['offset']; } } $url = $formatter->link_url($formatter->page->urlname); $fneedle = _html_escape($needle); $tooshort = !empty($DBInfo->fullsearch_tooshort) ? $DBInfo->fullsearch_tooshort : 2; $m1 = _("Display context of search results"); $m2 = _("Search BackLinks only"); $m3 = _("Case-sensitive searching"); $msg = _("Go"); $bchecked = !empty($DBInfo->use_backlinks) ? 'checked="checked"' : ''; $form = <<<EOF <form method='get' action='{$url}'> <input type='hidden' name='action' value='fullsearch' /> <input name='value' size='30' value="{$fneedle}" /> <span class='button'><input type='submit' class='button' value='{$msg}' /></span><br /> <input type='checkbox' name='backlinks' value='1' {$bchecked} />{$m2}<br /> <input type='checkbox' name='context' value='20' />{$m1}<br /> <input type='checkbox' name='case' value='1' />{$m3}<br /> </form> EOF; if (!isset($needle[0]) or !empty($opts['form'])) { # or blah blah $opts['msg'] = _("No search text"); return $form; } $opts['form'] = $form; # XXX $excl = array(); $incl = array(); if (!empty($opts['noexpr'])) { $tmp = preg_split("/\\s+/", $needle); $needle = $value = join('|', $tmp); $raw_needle = implode(' ', $tmp); $needle = preg_quote($needle); } else { if (empty($opts['backlinks'])) { $terms = preg_split('/((?<!\\S)[-+]?"[^"]+?"(?!\\S)|\\S+)/s', $needle, -1, PREG_SPLIT_DELIM_CAPTURE | PREG_SPLIT_NO_EMPTY); $common_words = array('the', 'that', 'where', 'what', 'who', 'how', 'too', 'are'); $common = array(); foreach ($terms as $term) { if (trim($term) == '') { continue; } if (preg_match('/^([-+]?)("?)([^\\2]+?)\\2$/', $term, $match)) { $word = str_replace(array('\\', '.', '*'), '', $match[3]); $len = strlen($word); if (!$match[1] and $match[2] != '"') { if ($len < $tooshort or in_array($word, $common_words)) { $common[] = $word; continue; } } if ($match[1] == '-') { $excl[] = $word; } else { $incl[] = $word; } } } $needle = implode('|', $incl); $needle = _preg_search_escape($needle); $raw_needle = implode(' ', $incl); $test = validate_needle($needle); if ($test === false) { // invalid regex $tmp = array_map('preg_quote', $incl); $needle = implode('|', $tmp); } $excl_needle = implode('|', $excl); $test = validate_needle($excl_needle); if ($test2 === false) { // invalid regex $tmp = array_map('preg_quote', $excl); $excl_needle = implode('|', $tmp); } } else { $cneedle = _preg_search_escape($needle); $test = validate_needle($cneedle); if ($test === false) { $needle = preg_quote($needle); } else { $needle = $cneedle; } } } $test3 = trim($needle); if (!isset($test3[0])) { $opts['msg'] = _("Empty expression"); return $form; } # set arena and sid if (!empty($opts['backlinks'])) { $arena = 'backlinks'; } else { if (!empty($opts['keywords'])) { $arena = 'keywords'; } else { $arena = 'fullsearch'; } } if ($arena == 'fullsearch') { $sid = md5($value . 'v' . $offset); } else { $sid = $value; } $delay = !empty($DBInfo->default_delaytime) ? $DBInfo->default_delaytime : 0; # retrieve cache $fc = new Cache_text($arena); if (!$formatter->refresh and $fc->exists($sid)) { $data = $fc->fetch($sid); if (!empty($opts['backlinks'])) { // backlinks are not needed to check it. $hits = $data; // also fetch redirects $r = new Cache_Text('redirects'); $redirects = $r->fetch($sid); } else { if (is_array($data)) { # check cache mtime $cmt = $fc->mtime($sid); # check update or not $dmt = $DBInfo->mtime(); if ($dmt > $cmt + $delay) { # XXX crude method $data = array(); } else { # XXX smart but incomplete method if (isset($data['hits'])) { $hits =& $data['hits']; } else { $hits =& $data; } foreach ($hits as $p => $c) { $mp = $DBInfo->getPage($p); $mt = $mp->mtime(); if ($mt > $cmt + $delay) { $data = array(); break; } } } if (isset($data['searched'])) { extract($data); } else { if (!empty($data)) { $hits = $data; } } } } } $pattern = '/' . $needle . '/'; if (!empty($excl_needle)) { $excl_pattern = '/' . $excl_needle . '/'; } if (!empty($opts['case'])) { $pattern .= "i"; $excl_pattern .= "i"; } if (isset($hits)) { if (in_array($arena, array('backlinks', 'keywords'))) { $test = key($hits); if (is_int($test) and $hits[$test] != -1) { // fix compatible issue for keywords, backlinks $hits = array_flip($hits); foreach ($hits as $k => $v) { $hits[$k] = -1; } reset($hits); } // check invert redirect index if (!empty($redirects)) { $redirects = array_flip($redirects); ksort($redirects); foreach ($redirects as $k => $v) { $hits[$k] = -2; } reset($hits); } } //continue; } else { $hits = array(); set_time_limit(0); if (!empty($opts['backlinks']) and empty($DBInfo->use_backlink_search)) { $hits = array(); } else { if (!empty($opts['keywords']) and empty($DBInfo->use_keyword_search)) { $hits = array(); } else { if (!empty($opts['backlinks'])) { $pages = $DBInfo->getPageLists(); #$opts['context']=-1; # turn off context-matching $cache = new Cache_text("pagelinks"); foreach ($pages as $page_name) { $links = $cache->fetch($page_name); if (is_array($links)) { if (in_array($value, $links)) { $hits[$page_name] = -1; } // ignore count if < 0 } } } else { if (!empty($opts['keywords'])) { $pages = $DBInfo->getPageLists(); $opts['context'] = -1; # turn off context-matching $cache = new Cache_text("keyword"); foreach ($pages as $page_name) { $links = $cache->fetch($page_name); // XXX if (is_array($links)) { if (stristr(implode(' ', $links), $needle)) { $hits[$page_name] = -1; } // ignore count if < 0 } } } else { $params = array(); $ret = array(); $params['ret'] =& $ret; $params['offset'] = $offset; $params['search'] = 1; $params['incl'] = $incl; $params['excl'] = $excl; $pages = $DBInfo->getPageLists($params); // set time_limit $mt = explode(' ', microtime()); $timestamp = $mt[0] + $mt[1]; $j = 0; $time_limit = isset($DBInfo->process_time_limit) ? $DBInfo->process_time_limit : 3; // default 3-seconds $j = 0; while (list($_, $page_name) = each($pages)) { // check time_limit if ($time_limit and $j % 30 == 0) { $mt = explode(' ', microtime()); $now = $mt[0] + $mt[1]; if ($now - $timestamp > $time_limit) { break; } } $j++; $p = new WikiPage($page_name); if (!$p->exists()) { continue; } $body = $p->_get_raw_body(); #$count = count(preg_split($pattern, $body))-1; $count = preg_match_all($pattern, $body, $matches); if ($count) { foreach ($excl as $ex) { if (stristr($body, $ex)) { continue; } } foreach ($incl as $in) { if (!stristr($body, $in)) { continue; } } $hits[$page_name] = $count; } } $searched = $j > 0 ? $j : 0; $offset = !empty($offset) ? $offset + $j : $j; } } } } #krsort($hits); #ksort($hits); $name = array_keys($hits); array_multisort($hits, SORT_DESC, $name, SORT_ASC); if (in_array($arena, array('backlinks', 'keywords'))) { $fc->update($sid, $name); } else { $fc->update($sid, array('hits' => $hits, 'offset' => $offset, 'searched' => $searched)); } } $opts['hits'] = $hits; $opts['hit'] = count($hits); $opts['all'] = $DBInfo->getCounter(); if ($opts['all'] > $searched) { $opts['next'] = $offset; $opts['searched'] = $searched; } if (!empty($opts['call'])) { return $hits; } $out = "<!-- RESULT LIST START -->"; // for search plugin $out .= "<ul class='fullsearchResult'>"; $idx = 1; $checkbox = ''; while (list($page_name, $count) = each($hits)) { $pgname = _html_escape($page_name); if (!empty($opts['checkbox'])) { $checkbox = "<input type='checkbox' name='pagenames[]' value=\"{$pgname}\" />"; } $out .= '<!-- RESULT ITEM START -->'; // for search plugin $out .= '<li>' . $checkbox . $formatter->link_tag(_rawurlencode($page_name), '?action=highlight&value=' . _urlencode($value), $pgname, 'tabindex="' . $idx . '"'); if ($count > 0) { $out .= ' . . . . ' . sprintf($count == 1 ? _("%d match") : _("%d matches"), $count); } else { if ($count == -2) { $out .= " <span class='redirectIcon'><span>" . _("Redirect page") . "</span></span>\n"; } } if (!empty($opts['context']) and $opts['context'] > 0) { # search matching contexts $p = new WikiPage($page_name); if ($p->exists()) { $body = $p->_get_raw_body(); $out .= find_needle($body, $needle, $excl_needle, $opts['context']); } } $out .= "</li>\n"; $out .= '<!-- RESULT ITEM END -->'; // for search plugin $idx++; #if ($idx > 50) break; } $out .= "</ul>\n"; $out .= "<!-- RESULT LIST END -->"; // for search plugin return $out; }
/** * @covers WikiPage::exists */ public function testExists() { $page = $this->newPage("WikiPageTest_testExists"); $this->assertFalse($page->exists()); # ----------------- $this->createPage($page, "some text", CONTENT_MODEL_WIKITEXT); $this->assertTrue($page->exists()); $page = new WikiPage($page->getTitle()); $this->assertTrue($page->exists()); # ----------------- $page->doDeleteArticle("done testing"); $this->assertFalse($page->exists()); $page = new WikiPage($page->getTitle()); $this->assertFalse($page->exists()); }
function latex_ref($page, $appearance, $hover = '') { global $db; if ($hover != '') { $hover = ' title="' . $hover . '"'; } $p = new WikiPage($db, $page); if ($p->exists()) { // return '<a href="' . viewURL($page) . '"' . $hover . '>' . $page . '</a>'; return '\\textbf{' . $page . '}'; } else { return '\\textbf{' . $appearance . $hover . "}"; } }
/** * Attempt submission (no UI) * * @param array $result Array to add statuses to, currently with the * possible keys: * - spam (string): Spam string from content if any spam is detected by * matchSpamRegex. * - sectionanchor (string): Section anchor for a section save. * - nullEdit (boolean): Set if doEditContent is OK. True if null edit, * false otherwise. * - redirect (bool): Set if doEditContent is OK. True if resulting * revision is a redirect. * @param bool $bot True if edit is being made under the bot right. * * @return Status Status object, possibly with a message, but always with * one of the AS_* constants in $status->value, * * @todo FIXME: This interface is TERRIBLE, but hard to get rid of due to * various error display idiosyncrasies. There are also lots of cases * where error metadata is set in the object and retrieved later instead * of being returned, e.g. AS_CONTENT_TOO_BIG and * AS_BLOCKED_PAGE_FOR_USER. All that stuff needs to be cleaned up some * time. */ function internalAttemptSave(&$result, $bot = false) { global $wgUser, $wgRequest, $wgParser, $wgMaxArticleSize; global $wgContentHandlerUseDB; $status = Status::newGood(); if (!Hooks::run('EditPage::attemptSave', array($this))) { wfDebug("Hook 'EditPage::attemptSave' aborted article saving\n"); $status->fatal('hookaborted'); $status->value = self::AS_HOOK_ERROR; return $status; } $spam = $wgRequest->getText('wpAntispam'); if ($spam !== '') { wfDebugLog('SimpleAntiSpam', $wgUser->getName() . ' editing "' . $this->mTitle->getPrefixedText() . '" submitted bogus field "' . $spam . '"'); $status->fatal('spamprotectionmatch', false); $status->value = self::AS_SPAM_ERROR; return $status; } try { # Construct Content object $textbox_content = $this->toEditContent($this->textbox1); } catch (MWContentSerializationException $ex) { $status->fatal('content-failed-to-parse', $this->contentModel, $this->contentFormat, $ex->getMessage()); $status->value = self::AS_PARSE_ERROR; return $status; } # Check image redirect if ($this->mTitle->getNamespace() == NS_FILE && $textbox_content->isRedirect() && !$wgUser->isAllowed('upload')) { $code = $wgUser->isAnon() ? self::AS_IMAGE_REDIRECT_ANON : self::AS_IMAGE_REDIRECT_LOGGED; $status->setResult(false, $code); return $status; } # Check for spam $match = self::matchSummarySpamRegex($this->summary); if ($match === false && $this->section == 'new') { # $wgSpamRegex is enforced on this new heading/summary because, unlike # regular summaries, it is added to the actual wikitext. if ($this->sectiontitle !== '') { # This branch is taken when the API is used with the 'sectiontitle' parameter. $match = self::matchSpamRegex($this->sectiontitle); } else { # This branch is taken when the "Add Topic" user interface is used, or the API # is used with the 'summary' parameter. $match = self::matchSpamRegex($this->summary); } } if ($match === false) { $match = self::matchSpamRegex($this->textbox1); } if ($match !== false) { $result['spam'] = $match; $ip = $wgRequest->getIP(); $pdbk = $this->mTitle->getPrefixedDBkey(); $match = str_replace("\n", '', $match); wfDebugLog('SpamRegex', "{$ip} spam regex hit [[{$pdbk}]]: \"{$match}\""); $status->fatal('spamprotectionmatch', $match); $status->value = self::AS_SPAM_ERROR; return $status; } if (!Hooks::run('EditFilter', array($this, $this->textbox1, $this->section, &$this->hookError, $this->summary))) { # Error messages etc. could be handled within the hook... $status->fatal('hookaborted'); $status->value = self::AS_HOOK_ERROR; return $status; } elseif ($this->hookError != '') { # ...or the hook could be expecting us to produce an error $status->fatal('hookaborted'); $status->value = self::AS_HOOK_ERROR_EXPECTED; return $status; } if ($wgUser->isBlockedFrom($this->mTitle, false)) { // Auto-block user's IP if the account was "hard" blocked $wgUser->spreadAnyEditBlock(); # Check block state against master, thus 'false'. $status->setResult(false, self::AS_BLOCKED_PAGE_FOR_USER); return $status; } $this->kblength = (int) (strlen($this->textbox1) / 1024); if ($this->kblength > $wgMaxArticleSize) { // Error will be displayed by showEditForm() $this->tooBig = true; $status->setResult(false, self::AS_CONTENT_TOO_BIG); return $status; } if (!$wgUser->isAllowed('edit')) { if ($wgUser->isAnon()) { $status->setResult(false, self::AS_READ_ONLY_PAGE_ANON); return $status; } else { $status->fatal('readonlytext'); $status->value = self::AS_READ_ONLY_PAGE_LOGGED; return $status; } } $changingContentModel = false; if ($this->contentModel !== $this->mTitle->getContentModel()) { if (!$wgContentHandlerUseDB) { $status->fatal('editpage-cannot-use-custom-model'); $status->value = self::AS_CANNOT_USE_CUSTOM_MODEL; return $status; } elseif (!$wgUser->isAllowed('editcontentmodel')) { $status->setResult(false, self::AS_NO_CHANGE_CONTENT_MODEL); return $status; } $changingContentModel = true; $oldContentModel = $this->mTitle->getContentModel(); } if ($this->changeTags) { $changeTagsStatus = ChangeTags::canAddTagsAccompanyingChange($this->changeTags, $wgUser); if (!$changeTagsStatus->isOK()) { $changeTagsStatus->value = self::AS_CHANGE_TAG_ERROR; return $changeTagsStatus; } } if (wfReadOnly()) { $status->fatal('readonlytext'); $status->value = self::AS_READ_ONLY_PAGE; return $status; } if ($wgUser->pingLimiter() || $wgUser->pingLimiter('linkpurge', 0)) { $status->fatal('actionthrottledtext'); $status->value = self::AS_RATE_LIMITED; return $status; } # If the article has been deleted while editing, don't save it without # confirmation if ($this->wasDeletedSinceLastEdit() && !$this->recreate) { $status->setResult(false, self::AS_ARTICLE_WAS_DELETED); return $status; } # Load the page data from the master. If anything changes in the meantime, # we detect it by using page_latest like a token in a 1 try compare-and-swap. $this->page->loadPageData('fromdbmaster'); $new = !$this->page->exists(); if ($new) { // Late check for create permission, just in case *PARANOIA* if (!$this->mTitle->userCan('create', $wgUser)) { $status->fatal('nocreatetext'); $status->value = self::AS_NO_CREATE_PERMISSION; wfDebug(__METHOD__ . ": no create permission\n"); return $status; } // Don't save a new page if it's blank or if it's a MediaWiki: // message with content equivalent to default (allow empty pages // in this case to disable messages, see bug 50124) $defaultMessageText = $this->mTitle->getDefaultMessageText(); if ($this->mTitle->getNamespace() === NS_MEDIAWIKI && $defaultMessageText !== false) { $defaultText = $defaultMessageText; } else { $defaultText = ''; } if (!$this->allowBlankArticle && $this->textbox1 === $defaultText) { $this->blankArticle = true; $status->fatal('blankarticle'); $status->setResult(false, self::AS_BLANK_ARTICLE); return $status; } if (!$this->runPostMergeFilters($textbox_content, $status, $wgUser)) { return $status; } $content = $textbox_content; $result['sectionanchor'] = ''; if ($this->section == 'new') { if ($this->sectiontitle !== '') { // Insert the section title above the content. $content = $content->addSectionHeader($this->sectiontitle); } elseif ($this->summary !== '') { // Insert the section title above the content. $content = $content->addSectionHeader($this->summary); } $this->summary = $this->newSectionSummary($result['sectionanchor']); } $status->value = self::AS_SUCCESS_NEW_ARTICLE; } else { # not $new # Article exists. Check for edit conflict. $this->page->clear(); # Force reload of dates, etc. $timestamp = $this->page->getTimestamp(); wfDebug("timestamp: {$timestamp}, edittime: {$this->edittime}\n"); if ($timestamp != $this->edittime) { $this->isConflict = true; if ($this->section == 'new') { if ($this->page->getUserText() == $wgUser->getName() && $this->page->getComment() == $this->newSectionSummary()) { // Probably a duplicate submission of a new comment. // This can happen when CDN resends a request after // a timeout but the first one actually went through. wfDebug(__METHOD__ . ": duplicate new section submission; trigger edit conflict!\n"); } else { // New comment; suppress conflict. $this->isConflict = false; wfDebug(__METHOD__ . ": conflict suppressed; new section\n"); } } elseif ($this->section == '' && Revision::userWasLastToEdit(DB_MASTER, $this->mTitle->getArticleID(), $wgUser->getId(), $this->edittime)) { # Suppress edit conflict with self, except for section edits where merging is required. wfDebug(__METHOD__ . ": Suppressing edit conflict, same user.\n"); $this->isConflict = false; } } // If sectiontitle is set, use it, otherwise use the summary as the section title. if ($this->sectiontitle !== '') { $sectionTitle = $this->sectiontitle; } else { $sectionTitle = $this->summary; } $content = null; if ($this->isConflict) { wfDebug(__METHOD__ . ": conflict! getting section '{$this->section}' for time '{$this->edittime}'" . " (article time '{$timestamp}')\n"); $content = $this->page->replaceSectionContent($this->section, $textbox_content, $sectionTitle, $this->edittime); } else { wfDebug(__METHOD__ . ": getting section '{$this->section}'\n"); $content = $this->page->replaceSectionContent($this->section, $textbox_content, $sectionTitle); } if (is_null($content)) { wfDebug(__METHOD__ . ": activating conflict; section replace failed.\n"); $this->isConflict = true; $content = $textbox_content; // do not try to merge here! } elseif ($this->isConflict) { # Attempt merge if ($this->mergeChangesIntoContent($content)) { // Successful merge! Maybe we should tell the user the good news? $this->isConflict = false; wfDebug(__METHOD__ . ": Suppressing edit conflict, successful merge.\n"); } else { $this->section = ''; $this->textbox1 = ContentHandler::getContentText($content); wfDebug(__METHOD__ . ": Keeping edit conflict, failed merge.\n"); } } if ($this->isConflict) { $status->setResult(false, self::AS_CONFLICT_DETECTED); return $status; } if (!$this->runPostMergeFilters($content, $status, $wgUser)) { return $status; } if ($this->section == 'new') { // Handle the user preference to force summaries here if (!$this->allowBlankSummary && trim($this->summary) == '') { $this->missingSummary = true; $status->fatal('missingsummary'); // or 'missingcommentheader' if $section == 'new'. Blegh $status->value = self::AS_SUMMARY_NEEDED; return $status; } // Do not allow the user to post an empty comment if ($this->textbox1 == '') { $this->missingComment = true; $status->fatal('missingcommenttext'); $status->value = self::AS_TEXTBOX_EMPTY; return $status; } } elseif (!$this->allowBlankSummary && !$content->equals($this->getOriginalContent($wgUser)) && !$content->isRedirect() && md5($this->summary) == $this->autoSumm) { $this->missingSummary = true; $status->fatal('missingsummary'); $status->value = self::AS_SUMMARY_NEEDED; return $status; } # All's well $sectionanchor = ''; if ($this->section == 'new') { $this->summary = $this->newSectionSummary($sectionanchor); } elseif ($this->section != '') { # Try to get a section anchor from the section source, redirect # to edited section if header found. # XXX: Might be better to integrate this into Article::replaceSection # for duplicate heading checking and maybe parsing. $hasmatch = preg_match("/^ *([=]{1,6})(.*?)(\\1) *\\n/i", $this->textbox1, $matches); # We can't deal with anchors, includes, html etc in the header for now, # headline would need to be parsed to improve this. if ($hasmatch && strlen($matches[2]) > 0) { $sectionanchor = $wgParser->guessLegacySectionNameFromWikiText($matches[2]); } } $result['sectionanchor'] = $sectionanchor; // Save errors may fall down to the edit form, but we've now // merged the section into full text. Clear the section field // so that later submission of conflict forms won't try to // replace that into a duplicated mess. $this->textbox1 = $this->toEditText($content); $this->section = ''; $status->value = self::AS_SUCCESS_UPDATE; } if (!$this->allowSelfRedirect && $content->isRedirect() && $content->getRedirectTarget()->equals($this->getTitle())) { // If the page already redirects to itself, don't warn. $currentTarget = $this->getCurrentContent()->getRedirectTarget(); if (!$currentTarget || !$currentTarget->equals($this->getTitle())) { $this->selfRedirect = true; $status->fatal('selfredirect'); $status->value = self::AS_SELF_REDIRECT; return $status; } } // Check for length errors again now that the section is merged in $this->kblength = (int) (strlen($this->toEditText($content)) / 1024); if ($this->kblength > $wgMaxArticleSize) { $this->tooBig = true; $status->setResult(false, self::AS_MAX_ARTICLE_SIZE_EXCEEDED); return $status; } $flags = EDIT_AUTOSUMMARY | ($new ? EDIT_NEW : EDIT_UPDATE) | ($this->minoredit && !$this->isNew ? EDIT_MINOR : 0) | ($bot ? EDIT_FORCE_BOT : 0); $doEditStatus = $this->page->doEditContent($content, $this->summary, $flags, false, $wgUser, $content->getDefaultFormat(), $this->changeTags); if (!$doEditStatus->isOK()) { // Failure from doEdit() // Show the edit conflict page for certain recognized errors from doEdit(), // but don't show it for errors from extension hooks $errors = $doEditStatus->getErrorsArray(); if (in_array($errors[0][0], array('edit-gone-missing', 'edit-conflict', 'edit-already-exists'))) { $this->isConflict = true; // Destroys data doEdit() put in $status->value but who cares $doEditStatus->value = self::AS_END; } return $doEditStatus; } $result['nullEdit'] = $doEditStatus->hasMessage('edit-no-change'); if ($result['nullEdit']) { // We don't know if it was a null edit until now, so increment here $wgUser->pingLimiter('linkpurge'); } $result['redirect'] = $content->isRedirect(); $this->updateWatchlist(); // If the content model changed, add a log entry if ($changingContentModel) { $this->addContentModelChangeLogEntry($wgUser, $oldContentModel, $this->contentModel, $this->summary); } return $status; }
function html_ref($page, $appearance, $hover = '', $anchor = '', $anchor_appearance = '') { global $db, $SeparateLinkWords; if ($hover != '') { $hover = ' title="' . $hover . '"'; } $p = new WikiPage($db, $page); if ($p->exists()) { if ($SeparateLinkWords && $page == $appearance) { $appearance = html_split_name($page); } return '<a href="' . viewURL($page) . $anchor . '"' . $hover . '>' . $appearance . $anchor_appearance . '</a>'; } else { if (validate_page($page) == 1 && $appearance == $page) { return $page . '<a href="' . editURL($page) . '"' . $hover . '>?</a>'; } else { return '(' . $appearance . ')<a href="' . editURL($page) . '"' . $hover . '>?</a>'; } } }
/** * This is the default action of the index.php entry point: just view the * page of the given title. */ public function view() { global $wgUser, $wgOut, $wgRequest, $wgParser; global $wgUseFileCache, $wgUseETag, $wgDebugToolbar; wfProfileIn(__METHOD__); # Get variables from query string # As side effect this will load the revision and update the title # in a revision ID is passed in the request, so this should remain # the first call of this method even if $oldid is used way below. $oldid = $this->getOldID(); # Another whitelist check in case getOldID() is altering the title $permErrors = $this->getTitle()->getUserPermissionsErrors('read', $wgUser); if (count($permErrors)) { wfDebug(__METHOD__ . ": denied on secondary read check\n"); wfProfileOut(__METHOD__); throw new PermissionsError('read', $permErrors); } # getOldID() may as well want us to redirect somewhere else if ($this->mRedirectUrl) { $wgOut->redirect($this->mRedirectUrl); wfDebug(__METHOD__ . ": redirecting due to oldid\n"); wfProfileOut(__METHOD__); return; } # If we got diff in the query, we want to see a diff page instead of the article. if ($wgRequest->getCheck('diff')) { wfDebug(__METHOD__ . ": showing diff page\n"); $this->showDiffPage(); wfProfileOut(__METHOD__); return; } # Set page title (may be overridden by DISPLAYTITLE) $wgOut->setPageTitle($this->getTitle()->getPrefixedText()); $wgOut->setArticleFlag(true); # Allow frames by default $wgOut->allowClickjacking(); $parserCache = ParserCache::singleton(); $parserOptions = $this->getParserOptions(); # Render printable version, use printable version cache if ($wgOut->isPrintable()) { $parserOptions->setIsPrintable(true); $parserOptions->setEditSection(false); } elseif (!$this->isCurrent() || !$this->getTitle()->quickUserCan('edit')) { $parserOptions->setEditSection(false); } # Try client and file cache if (!$wgDebugToolbar && $oldid === 0 && $this->mPage->checkTouched()) { if ($wgUseETag) { $wgOut->setETag($parserCache->getETag($this, $parserOptions)); } # Is it client cached? if ($wgOut->checkLastModified($this->mPage->getTouched())) { wfDebug(__METHOD__ . ": done 304\n"); wfProfileOut(__METHOD__); return; # Try file cache } elseif ($wgUseFileCache && $this->tryFileCache()) { wfDebug(__METHOD__ . ": done file cache\n"); # tell wgOut that output is taken care of $wgOut->disable(); $this->mPage->doViewUpdates($wgUser); wfProfileOut(__METHOD__); return; } } # Should the parser cache be used? $useParserCache = $this->mPage->isParserCacheUsed($parserOptions, $oldid); wfDebug('Article::view using parser cache: ' . ($useParserCache ? 'yes' : 'no') . "\n"); if ($wgUser->getStubThreshold()) { wfIncrStats('pcache_miss_stub'); } $this->showRedirectedFromHeader(); $this->showNamespaceHeader(); # Iterate through the possible ways of constructing the output text. # Keep going until $outputDone is set, or we run out of things to do. $pass = 0; $outputDone = false; $this->mParserOutput = false; while (!$outputDone && ++$pass) { switch ($pass) { case 1: wfRunHooks('ArticleViewHeader', array(&$this, &$outputDone, &$useParserCache)); break; case 2: # Early abort if the page doesn't exist if (!$this->mPage->exists()) { wfDebug(__METHOD__ . ": showing missing article\n"); $this->showMissingArticle(); wfProfileOut(__METHOD__); /* Wikia change begin - @author: Marcin, #BugId: 30436 */ $text = ''; if (wfRunHooks('ArticleNonExistentPage', array(&$this, $wgOut, &$text))) { $this->mParserOutput = $wgParser->parse($text, $this->getTitle(), $parserOptions); $wgOut->addParserOutput($this->mParserOutput); } /* Wikia change end */ return; } # Try the parser cache if ($useParserCache) { $this->mParserOutput = $parserCache->get($this, $parserOptions); //Wikia Change Transaction::setAttribute(Transaction::PARAM_PARSER_CACHE_USED, $this->mParserOutput !== false); //Wikia Change End if ($this->mParserOutput !== false) { if ($oldid) { wfDebug(__METHOD__ . ": showing parser cache contents for current rev permalink\n"); $this->setOldSubtitle($oldid); } else { wfDebug(__METHOD__ . ": showing parser cache contents\n"); } $wgOut->addParserOutput($this->mParserOutput); // Wikia change - begin - @author: wladek wfRunHooks('ArticleViewAddParserOutput', array($this, $this->mParserOutput)); // Wikia change - end # Ensure that UI elements requiring revision ID have # the correct version information. $wgOut->setRevisionId($this->mPage->getLatest()); # Preload timestamp to avoid a DB hit $cachedTimestamp = $this->mParserOutput->getTimestamp(); if ($cachedTimestamp !== null) { $wgOut->setRevisionTimestamp($cachedTimestamp); $this->mPage->setTimestamp($cachedTimestamp); } $outputDone = true; } // Wikia change - begin - @author: wladek } else { Transaction::setAttribute(Transaction::PARAM_PARSER_CACHE_USED, false); // Wikia change - end } break; case 3: # This will set $this->mRevision if needed $this->fetchContent(); // Wikia change - begin // @author macbre // return status different than HTTP 200 when revision is missing (BAC-630) if (!$this->mRevision instanceof Revision) { global $wgEnableParserCache; wfDebug(__METHOD__ . ": no revision found - disabling parser cache and returning 404\n"); $wgOut->getRequest()->response()->header('X-Missing-Revision: 1', true, 404); $useParserCache = false; $wgEnableParserCache = false; } // Wikia change - end # Are we looking at an old revision if ($oldid && $this->mRevision) { $this->setOldSubtitle($oldid); if (!$this->showDeletedRevisionHeader()) { wfDebug(__METHOD__ . ": cannot view deleted revision\n"); wfProfileOut(__METHOD__); return; } } # Ensure that UI elements requiring revision ID have # the correct version information. $wgOut->setRevisionId($this->getRevIdFetched()); # Preload timestamp to avoid a DB hit $wgOut->setRevisionTimestamp($this->getTimestamp()); # Pages containing custom CSS or JavaScript get special treatment if ($this->getTitle()->isCssOrJsPage() || $this->getTitle()->isCssJsSubpage()) { wfDebug(__METHOD__ . ": showing CSS/JS source\n"); $this->showCssOrJsPage(); $outputDone = true; } elseif (!wfRunHooks('ArticleViewCustom', array($this->mContent, $this->getTitle(), $wgOut))) { # Allow extensions do their own custom view for certain pages $outputDone = true; } else { $text = $this->getContent(); $rt = Title::newFromRedirectArray($text); if ($rt) { wfDebug(__METHOD__ . ": showing redirect=no page\n"); # Viewing a redirect page (e.g. with parameter redirect=no) $wgOut->addHTML($this->viewRedirect($rt)); # Parse just to get categories, displaytitle, etc. $this->mParserOutput = $wgParser->parse($text, $this->getTitle(), $parserOptions); $wgOut->addParserOutputNoText($this->mParserOutput); $outputDone = true; } } break; case 4: # Run the parse, protected by a pool counter wfDebug(__METHOD__ . ": doing uncached parse\n"); $poolArticleView = new PoolWorkArticleView($this, $parserOptions, $this->getRevIdFetched(), $useParserCache, $this->getContent()); if (!$poolArticleView->execute()) { $error = $poolArticleView->getError(); if ($error) { $wgOut->clearHTML(); // for release() errors $wgOut->enableClientCache(false); $wgOut->setRobotPolicy('noindex,nofollow'); $errortext = $error->getWikiText(false, 'view-pool-error'); $wgOut->addWikiText('<div class="errorbox">' . $errortext . '</div>'); } # Connection or timeout error wfProfileOut(__METHOD__); return; } $this->mParserOutput = $poolArticleView->getParserOutput(); $wgOut->addParserOutput($this->mParserOutput); // Wikia change - begin - @author: wladek Transaction::setAttribute(Transaction::PARAM_PARSER_CACHE_USED, $poolArticleView->getIsDirty()); wfRunHooks('ArticleViewAddParserOutput', array($this, $this->mParserOutput)); // Wikia change - end # Don't cache a dirty ParserOutput object if ($poolArticleView->getIsDirty()) { $wgOut->setSquidMaxage(0); $wgOut->addHTML("<!-- parser cache is expired, sending anyway due to pool overload-->\n"); } # <Wikia> if (!$poolArticleView->getIsDirty()) { wfRunHooks('ArticleViewAfterParser', array($this, $this->mParserOutput)); } # </Wikia> $outputDone = true; break; # Should be unreachable, but just in case... # Should be unreachable, but just in case... default: break 2; } } # Get the ParserOutput actually *displayed* here. # Note that $this->mParserOutput is the *current* version output. $pOutput = $outputDone instanceof ParserOutput ? $outputDone : $this->mParserOutput; # Adjust title for main page & pages with displaytitle if ($pOutput) { $this->adjustDisplayTitle($pOutput); if ($pOutput->getText() == '') { \Wikia\Logger\WikiaLogger::instance()->error('PLATFORM-1212 - empty parser output'); } } # For the main page, overwrite the <title> element with the con- # tents of 'pagetitle-view-mainpage' instead of the default (if # that's not empty). # This message always exists because it is in the i18n files if ($this->getTitle()->isMainPage()) { $msg = wfMessage('pagetitle-view-mainpage')->inContentLanguage(); if (!$msg->isDisabled()) { $wgOut->setHTMLTitle($msg->title($this->getTitle())->text()); } } # Check for any __NOINDEX__ tags on the page using $pOutput $policy = $this->getRobotPolicy('view', $pOutput); $wgOut->setIndexPolicy($policy['index']); $wgOut->setFollowPolicy($policy['follow']); $this->showViewFooter(); $this->mPage->doViewUpdates($wgUser); wfProfileOut(__METHOD__); }
/** * Create or edit a group */ public function html_group(&$q) { global $wgOut, $wgUser, $wgScript, $haclgHaloScriptPath, $wgContLang, $haclgContLang; $grpTitle = $grpArticle = $grpName = $grpPrefix = NULL; if (!empty($q['group'])) { $pe = IACLDefinition::nameOfPE($q['group']); $t = Title::newFromText($q['group'], HACL_NS_ACL); if ($t && $pe[0] == IACL::PE_GROUP) { $a = new WikiPage($t); if ($a->exists()) { $grpTitle = $t; $grpArticle = $a; $grpPrefix = $haclgContLang->getPetPrefix(IACL::PE_GROUP); $grpName = $pe[1]; } } } /* Run template */ ob_start(); require dirname(__FILE__) . '/../templates/HACL_GroupEditor.tpl.php'; $html = ob_get_contents(); ob_end_clean(); $wgOut->addModules('ext.intraacl.groupeditor'); $wgOut->setPageTitle($grpTitle ? wfMsg('hacl_grp_editing', $grpTitle->getText()) : wfMsg('hacl_grp_creating')); $wgOut->addHTML($html); }
function approveEditById($id) { $dbw = wfGetDB(DB_MASTER); $row = $dbw->selectRow('moderation', array('mod_id AS id', 'mod_timestamp AS timestamp', 'mod_user AS user', 'mod_user_text AS user_text', 'mod_cur_id AS cur_id', 'mod_namespace AS namespace', 'mod_title AS title', 'mod_comment AS comment', 'mod_minor AS minor', 'mod_bot AS bot', 'mod_last_oldid AS last_oldid', 'mod_ip AS ip', 'mod_header_xff AS header_xff', 'mod_header_ua AS header_ua', 'mod_text AS text', 'mod_merged_revid AS merged_revid', 'mod_rejected AS rejected', 'mod_stash_key AS stash_key'), array('mod_id' => $id), __METHOD__); if (!$row) { throw new ModerationError('moderation-edit-not-found'); } if ($row->merged_revid) { throw new ModerationError('moderation-already-merged'); } if ($row->rejected && $row->timestamp < $this->mSpecial->earliestReapprovableTimestamp) { throw new ModerationError('moderation-rejected-long-ago'); } # Prepare everything $title = Title::makeTitle($row->namespace, $row->title); $model = $title->getContentModel(); $user = $row->user ? User::newFromId($row->user) : User::newFromName($row->user_text, false); $flags = EDIT_DEFER_UPDATES | EDIT_AUTOSUMMARY; if ($row->bot && $user->isAllowed('bot')) { $flags |= EDIT_FORCE_BOT; } if ($row->minor) { # doEditContent() checks the right $flags |= EDIT_MINOR; } # For CheckUser extension to work properly, IP, XFF and UA # should be set to the correct values for the original user # (not from the moderator) $cuHook = new ModerationCheckUserHook(); $cuHook->install($row->ip, $row->header_xff, $row->header_ua); $approveHook = new ModerationApproveHook(); $approveHook->install(array('rev_timestamp' => $dbw->timestamp($row->timestamp), 'rev_user' => $user->getId(), 'rev_user_text' => $user->getName())); $status = Status::newGood(); if ($row->stash_key) { # This is the upload from stash. $stash = RepoGroup::singleton()->getLocalRepo()->getUploadStash($user); try { $file = $stash->getFile($row->stash_key); } catch (MWException $e) { throw new ModerationError('moderation-missing-stashed-image'); } $upload = new UploadFromStash($user, $stash); $upload->initialize($row->stash_key, $title->getText()); $status = $upload->performUpload($row->comment, $row->text, 0, $user); } else { # This is normal edit (not an upload). $new_content = ContentHandler::makeContent($row->text, null, $model); $page = new WikiPage($title); if (!$page->exists()) { # New page $status = $page->doEditContent($new_content, $row->comment, $flags, false, $user); } else { # Existing page $latest = $page->getLatest(); if ($latest == $row->last_oldid) { # Page hasn't changed since this edit was queued for moderation. $status = $page->doEditContent($new_content, $row->comment, $flags, $row->last_oldid, $user); } else { # Page has changed! # Let's attempt merging, as MediaWiki does in private EditPage::mergeChangesIntoContent(). $base_content = $row->last_oldid ? Revision::newFromId($row->last_oldid)->getContent(Revision::RAW) : ContentHandler::makeContent('', null, $model); $latest_content = Revision::newFromId($latest)->getContent(Revision::RAW); $handler = ContentHandler::getForModelID($base_content->getModel()); $merged_content = $handler->merge3($base_content, $new_content, $latest_content); if ($merged_content) { $status = $page->doEditContent($merged_content, $row->comment, $flags, $latest, $user); } else { $dbw = wfGetDB(DB_MASTER); $dbw->update('moderation', array('mod_conflict' => 1), array('mod_id' => $id), __METHOD__); $dbw->commit(__METHOD__); throw new ModerationError('moderation-edit-conflict'); } } } } $approveHook->deinstall(); $cuHook->deinstall(); if (!$status->isGood()) { throw new ModerationError($status->getMessage()); } $logEntry = new ManualLogEntry('moderation', 'approve'); $logEntry->setPerformer($this->moderator); $logEntry->setTarget($title); $logEntry->setParameters(array('revid' => $approveHook->lastRevId)); $logid = $logEntry->insert(); $logEntry->publish($logid); # Approved edits are removed from "moderation" table, # because they already exist in page history, recentchanges etc. $dbw = wfGetDB(DB_MASTER); $dbw->delete('moderation', array('mod_id' => $id), __METHOD__); }
function do_post_fixbacklinks($formatter, $options = array()) { global $DBInfo; if ($_SERVER['REQUEST_METHOD'] == 'POST' && !$DBInfo->security->writable($options)) { $options['title'] = _("Page is not writable"); return do_invalid($formatter, $options); } $options['name'] = trim($options['name']); $new = $options['name']; if (!empty($DBInfo->use_namespace) and $new[0] == '~' and ($p = strpos($new, '/')) !== false) { // Namespace renaming ~foo/bar -> foo~bar $dummy = substr($new, 1, $p - 1); $dummy2 = substr($new, $p + 1); $options['name'] = $dummy . '~' . $dummy2; } if (isset($options['name'][0]) and $options['name']) { if ($DBInfo->hasPage($options['name'])) { $formatter->send_header('', $options); $new_encodedname = _rawurlencode($options['name']); $fixed = 0; $msg = ''; $title = sprintf(_("backlinks of \"%s\" page are fixed !"), $options['page']); $comment = sprintf(_("Fixed \"%s\" to \"%s\""), $options['page'], $options['name']); if ($options['pagenames'] and is_array($options['pagenames'])) { $regex = preg_quote($options['page']); //$options['minor'] = 1; # disable log foreach ($options['pagenames'] as $page) { $p = new WikiPage($page); if (!$p->exists()) { continue; } $f = new Formatter($p); $body = $p->_get_raw_body(); $nbody = preg_replace("/{$regex}/m", $options['name'], $body); // FIXME if ($nbody !== false && $body != $nbody) { $f->page->write($nbody); if (!$options['show_only']) { $DBInfo->savePage($f->page, $comment, $options); } $msg .= sprintf(_("'%s' is changed"), $f->link_tag(_rawurlencode($page), "?action=highlight&value=" . $new_encodedname, _html_escape($page))) . "<br />"; $fixed++; } } } if ($fixed == 0) { $title = _("No pages are fixed!"); } $formatter->send_title($title, '', $options); if ($fixed > 0) { print $msg; print sprintf(_("'%s' links are successfully fixed as '%s'."), _html_escape($options['page']), $formatter->link_tag($new_encodedname, "?action=highlight&value=" . $new_encodedname, _html_escape($options['name']))); } $formatter->send_footer('', $options); return; } else { $title = sprintf(_("Fail to fix backlinks of \"%s\" !"), $options['page']); $options['msg'] = sprintf(_("New pagename \"%s\" is not exists!"), $options['name']); $formatter->send_header('', $options); $formatter->send_title($title, '', $options); $formatter->send_footer('', $options); return; } } $title = sprintf(_("Fix backlinks of \"%s\" ?"), $options['page']); $formatter->send_header('', $options); $formatter->send_title($title, '', $options); $obtn = _("Old name:"); $nbtn = _("New name:"); $pgname = _html_escape($options['page']); print "<form method='post'>\n <table border='0'>\n <tr><td align='right'>{$obtn} </td><td><b>{$pgname}</b></td></tr>\n <tr><td align='right'>{$nbtn} </td><td><input name='name' /></td></tr>\n"; if (!empty($options['value']) and $options['value'] == 'check_backlinks') { $button = _("Fix backlinks"); print "<tr><td colspan='2'>\n"; print check_backlinks($formatter, $options); print "</td></tr>\n"; } else { $button = _("Check backlinks"); } if ($DBInfo->security->is_protected("fixbacklinks", $options)) { print "<tr><td align='right'>" . _("Password") . ": </td><td><input type='password' name='passwd' /> " . _("Only WikiMaster can fix backlinks of this page") . "</td></tr>\n"; } if (!empty($options['value']) and $options['value'] == 'check_backlinks') { print "<tr><td colspan='2'><input type='checkbox' name='show_only' checked='checked' />" . _("show only") . "</td></tr>\n"; } print "<tr><td></td><td><input type='submit' name='button_fixbacklinks' value='{$button}' />"; print "<input type='hidden' name='value' value='check_backlinks' />"; print "</td></tr>\n"; print "\n </table>\n <input type='hidden' name='action' value='fixbacklinks' />\n </form>"; $formatter->send_footer('', $options); }
function macro_Cite($formatter = "", $value = "") { $CITE_MAP = "CiteMap"; $DEFAULT = <<<EOS JCP,J.Chem.Phys. http://jcp.aip.org/jcp/top.jsp?vol=\$VOL&pg=\$PAGE JACS,J.Am.Chem.Soc. http://pubs.acs.org/journals/query/subscriberResults.jsp?Research=true&yearrange1=ASAP&yearrange3=current&cit_qjrn=jacsat&styear=YYYY&endyear=YYYY&vol=\$VOL&spn=\$PAGE JPC,J.Phys.Chem. http://pubs.acs.org/journals/query/subscriberResults.jsp?Research=true&yearrange1=ASAP&yearrange3=current&cit_qjrn=jpchax&styear=YYYY&endyear=YYYY&vol=\$VOL&spn=\$PAGE JPCA,J.Phys.Chem.A http://pubs.acs.org/journals/query/subscriberResults.jsp?Research=true&yearrange1=ASAP&yearrange3=current&cit_qjrn=jpcafh&styear=YYYY&endyear=YYYY&vol=\$VOL&spn=\$PAGE ChemRev,Chem.Rev. http://pubs.acs.org/journals/query/subscriberResults.jsp?Research=true&yearrange1=ASAP&yearrange3=current&cit_qjrn=chreay&styear=YYYY&endyear=YYYY&vol=\$VOL&spn=\$PAGE RMP,Rev.Mod.Phys. http://link.aps.org/volpage?journal=RMP&volume=\$VOL&id=\$PAGE PR,Phys.Rev. http://link.aps.org/volpage?journal=PR&volume=\$VOL&id=\$PAGE PRL,Phys.Rev.Lett. http://link.aps.org/doi/10.1103/PhysRevLett.\$VOL.\$PAGE CPL,Chem.Phys.Lett. http://www.sciencedirect.com/science/journal/00092614 EOS; $CITE_list = array('JCP' => array('http://jcp.aip.org/jcp/top.jsp?vol=$VOL&pg=$PAGE', '', 'J.Chem.Phys.')); $DEFAULT_CITE = "JCP"; $re_cite = "/([A-Z][A-Za-z]*)?\\s*([0-9\\-]+\\s*,\\s*[0-9]+)/x"; $test = preg_match($re_cite, $value, $match); if ($test === false) { return "<p><strong class=\"error\">Invalid CITE \"%value\"</strong></p>"; } list($vol, $page) = explode(',', preg_replace('/ /', '', $match[2])); if (!empty($match[1])) { if (strtolower($match[1][0]) == "k") { $cite = "JKCS"; } else { $cite = $match[1]; } } else { $cite = $DEFAULT_CITE; } $attr = ''; if (!empty($match[3])) { $args = explode(",", $match[3]); foreach ($args as $arg) { if ($arg == "noimg") { $noimg = 1; } else { $name = strtok($arg, '='); $val = strtok(' '); $attr .= $name . '="' . $val . '" '; if ($name == 'align') { $attr .= 'class="img' . ucfirst($val) . '" '; } } } } $list = $DEFAULT; $map = new WikiPage($CITE_MAP); if ($map->exists()) { $list .= $map->get_raw_body(); } $lists = explode("\n", $list); foreach ($lists as $line) { if (empty($line) or !preg_match("/^[A-Z]/", $line[0])) { continue; } $dum = explode(" ", rtrim($line)); if (sizeof($dum) == 2) { $dum[] = $CITE_list[$DEFAULT_CITE][1]; } else { if (sizeof($dum) != 3) { continue; } } list($dum[0], $name) = explode(',', $dum[0]); $CITE_list[$dum[0]] = array($dum[1], $dum[2], $name); } if (!empty($CITE_list[$cite])) { $citelink = $CITE_list[$cite][0]; $imglink = $CITE_list[$cite][1]; $citename = $CITE_list[$cite][2]; if ($citename) { $cite = str_replace('.', '. ', $citename); } } else { $citelink = $CITE_list[$DEFAULT_CITE][0]; $imglink = $CITE_list[$DEFAULT_CITE][1]; } $citelink = str_replace('$VOL', $vol, $citelink); $citelink = str_replace('$PAGE', $page, $citelink); return $formatter->icon['www'] . '<a href=' . "'{$citelink}'>" . $cite . ' <strong>' . $vol . '</strong>, ' . $page . '</a> '; }
function macro_FastSearch($formatter, $value = "", &$opts) { global $DBInfo; $default_limit = isset($DBInfo->fastsearch_limit) ? $DBInfo->fastsearch_limit : 30; if ($value === true) { $needle = $value = $formatter->page->name; } else { # for MoinMoin compatibility with [[FullSearch("blah blah")]] $needle = $value = preg_replace("/^('|\")([^\\1]*)\\1/", "\\2", $value); } $needle = _preg_search_escape($needle); $pattern = '/' . $needle . '/i'; $fneedle = str_replace('"', """, $needle); # XXX $url = $formatter->link_url($formatter->page->urlname); $arena = 'fullsearch'; $check1 = 'checked="checked"'; $check2 = $check3 = ''; if (in_array($opts['arena'], array('titlesearch', 'fullsearch', 'pagelinks'))) { $check1 = ''; $arena = $opts['arena']; if ($arena == 'fullsearch') { $check1 = 'checked="checked"'; } else { if ($arena == 'titlesearch') { $check2 = 'checked="checked"'; } else { $check3 = 'checked="checked"'; } } } if (!empty($opts['backlinks'])) { $arena = 'pagelinks'; $check1 = ''; $check3 = 'checked="checked"'; } $msg = _("Fast search"); $msg2 = _("Display context of search results"); $msg3 = _("Full text search"); $msg4 = _("Title search"); $msg5 = _("Link search"); $form = <<<EOF <form method='get' action='{$url}'> <input type='hidden' name='action' value='fastsearch' /> <input name='value' size='30' value='{$fneedle}' /> <span class='button'><input type='submit' class='button' value='{$msg}' /></span><br /> <input type='checkbox' name='context' value='20' />{$msg2}<br /> <input type='radio' name='arena' value='fullsearch' {$check1} />{$msg3} <input type='radio' name='arena' value='titlesearch' {$check2} />{$msg4} <input type='radio' name='arena' value='pagelinks' {$check3} />{$msg5}<br /> </form> EOF; if (!isset($needle[0]) or !empty($opts['form'])) { # or blah blah $opts['msg'] = _("No search text"); return $form; } else { if (validate_needle($needle) === false) { $opts['msg'] = sprintf(_("Invalid search expression \"%s\""), $needle); return $form; } } $DB = new Indexer_dba($arena, "r", $DBInfo->dba_type); if ($DB->db == null) { $opts['msg'] = _("Couldn't open search database, sorry."); $opts['hits'] = array(); $opts['hit'] = 0; $opts['all'] = 0; return ''; } $opts['form'] = $form; $sc = new Cache_text("searchkey"); if ($arena == "pagelinks") { $words = array($value); } else { $words = getTokens($value); } // $words=explode(' ', strtolower($value)); $idx = array(); $new_words = array(); foreach ($words as $word) { if ($sc->exists($word)) { $searchkeys = $sc->fetch($word); } else { $searchkeys = $DB->_search($word); $sc->update($word, $searchkeys); } $new_words = array_merge($new_words, $searchkeys); $new_words = array_merge($idx, $DB->_search($word)); } $words = array_merge($words, $new_words); // $word = array_shift($words); $idx = $DB->_fetchValues($word); foreach ($words as $word) { $ids = $DB->_fetchValues($word); // FIXME foreach ($ids as $id) { $idx[] = $id; } } $init_hits = array_count_values($idx); // initial hits $idx = array_keys($init_hits); //arsort($idx); $all_count = $DBInfo->getCounter(); $pages = array(); $hits = array(); foreach ($idx as $id) { $key = $DB->_fetch($id); $pages[$id] = $key; $hits['_' . $key] = $init_hits[$id]; // HACK. prefix '_' to numerical named pages } $DB->close(); if (!empty($_GET['q']) and isset($_GET['q'][0])) { return $pages; } $context = !empty($opts['context']) ? $opts['context'] : 0; $limit = isset($opts['limit'][0]) ? $opts['limit'] : $default_limit; $contexts = array(); if ($arena == 'fullsearch' || $arena == 'pagelinks') { $idx = 1; foreach ($pages as $page_name) { if (!empty($limit) and $idx > $limit) { break; } $p = new WikiPage($page_name); if (!$p->exists()) { continue; } $body = $p->_get_raw_body(); $count = preg_match_all($pattern, $body, $matches); // more precisely count matches if ($context) { # search matching contexts $contexts[$page_name] = find_needle($body, $needle, '', $context); } $hits['_' . $page_name] = $count; // XXX hack for numerical named pages $idx++; } } //uasort($hits, 'strcasecmp'); //$order = 0; //uasort($hits, create_function('$a, $b', 'return ' . ($order ? '' : '-') . '(strcasecmp($a, $b));')); $name = array_keys($hits); array_multisort($hits, SORT_DESC, $name, SORT_ASC); $opts['hits'] = $hits; $opts['hit'] = count($hits); $opts['all'] = $all_count; if (!empty($opts['call'])) { return $hits; } $out = "<!-- RESULT LIST START -->"; // for search plugin $out .= "<ul>"; $idx = 1; while (list($page_name, $count) = each($hits)) { $page_name = substr($page_name, 1); $out .= '<!-- RESULT ITEM START -->'; // for search plugin $out .= '<li>' . $formatter->link_tag(_rawurlencode($page_name), "?action=highlight&value=" . _urlencode($needle), $page_name, "tabindex='{$idx}'"); if ($count > 1) { $out .= ' . . . . ' . sprintf($count == 1 ? _("%d match") : _("%d matches"), $count); if (!empty($contexts[$page_name])) { $out .= $contexts[$page_name]; } } $out .= "</li>\n"; $out .= '<!-- RESULT ITEM END -->'; // for search plugin $idx++; if (!empty($limit) and $idx > $limit) { break; } } $out .= "</ul>\n"; $out .= "<!-- RESULT LIST END -->"; // for search plugin return $out; }
function odt_ref($refPage, $appearance, $hover = '', $anchor = '', $anchor_appearance = '') { global $db, $SeparateLinkWords, $page, $pagestore, $ScriptBase; if ($page == 'RecentChanges') { $p_exists = $pagestore->page_exists($refPage); } else { $p = new WikiPage($db, $refPage); $p_exists = $p->exists(); // automatically handle plurals if (!$p_exists) { foreach (array('s', 'es') as $plural) { if (substr($refPage, -strlen($plural)) == $plural) { $temp_refPage = substr($refPage, 0, strlen($refPage) - strlen($plural)); $p = new WikiPage($db, $temp_refPage); if ($p_exists = $p->exists()) { $refPage = $temp_refPage; break; } } } } } if ($p_exists) { if ($SeparateLinkWords && $refPage == $appearance) { $appearance = html_split_name($refPage); } $url = $ScriptBase . '?page=' . urlencode($refPage) . $anchor; $result = odt_url($url, $appearance . $anchor_appearance); } else { $result = ""; if (validate_page($refPage) == 1 && $appearance == $refPage) { $result = $refPage; } else { // Free link. // Puts the appearance between parenthesis if there's a space in it. if (strpos($appearance, ' ') === false) { $tempAppearance = $appearance; } else { $tempAppearance = "({$appearance})"; } $result = $tempAppearance; } } return $result; }
/** * wfMaintenance -- wiki factory maintenance * * @static */ public static function wfMaintenance() { $results = []; // VOLDEV-96: Do not credit edits to localhost $wikiaUser = User::newFromName('Wikia'); /** * create Blog:Recent posts page if not exists */ $recentPosts = wfMessage('create-blog-post-recent-listing')->text(); if ($recentPosts) { $recentPostsKey = "Creating {$recentPosts}"; $oTitle = Title::newFromText($recentPosts, NS_BLOG_LISTING); if ($oTitle) { $page = new WikiPage($oTitle); if (!$page->exists()) { $page->doEdit('<bloglist summary="true" count=50><title>' . wfMessage('create-blog-post-recent-listing-title ')->text() . '</title><type>plain</type><order>date</order></bloglist>', wfMessage('create-blog-post-recent-listing-log')->text(), EDIT_NEW | EDIT_MINOR | EDIT_FORCE_BOT, false, $wikiaUser); $results[$recentPostsKey] = 'done'; } else { $results[$recentPostsKey] = 'already exists'; } } } /** * create Category:Blog page if not exists */ $catName = wfMessage('create-blog-post-category')->text(); if ($catName && $catName !== "-") { $catNameKey = "Creating {$catName}"; $oTitle = Title::newFromText($catName, NS_CATEGORY); if ($oTitle) { $page = new WikiPage($oTitle); if (!$page->exists()) { $page->doEdit(wfMessage('create-blog-post-category-body')->text(), wfMessage('create-blog-post-category-log')->text(), EDIT_NEW | EDIT_MINOR | EDIT_FORCE_BOT, false, $wikiaUser); $results[$catNameKey] = 'done'; } else { $results[$catNameKey] = 'already exists'; } } } return $results; }
/** * UI entry point for page deletion */ public function delete() { # This code desperately needs to be totally rewritten $title = $this->getTitle(); $user = $this->getContext()->getUser(); # Check permissions $permission_errors = $title->getUserPermissionsErrors('delete', $user); if (count($permission_errors)) { throw new PermissionsError('delete', $permission_errors); } # Read-only check... if (wfReadOnly()) { throw new ReadOnlyError(); } # Better double-check that it hasn't been deleted yet! $this->mPage->loadPageData('fromdbmaster'); if (!$this->mPage->exists()) { $deleteLogPage = new LogPage('delete'); $outputPage = $this->getContext()->getOutput(); $outputPage->setPageTitle(wfMessage('cannotdelete-title', $title->getPrefixedText())); $outputPage->wrapWikiMsg("<div class=\"error mw-error-cannotdelete\">\n\$1\n</div>", array('cannotdelete', wfEscapeWikiText($title->getPrefixedText()))); $outputPage->addHTML(Xml::element('h2', null, $deleteLogPage->getName()->text())); LogEventsList::showLogExtract($outputPage, 'delete', $title); return; } $request = $this->getContext()->getRequest(); $deleteReasonList = $request->getText('wpDeleteReasonList', 'other'); $deleteReason = $request->getText('wpReason'); if ($deleteReasonList == 'other') { $reason = $deleteReason; } elseif ($deleteReason != '') { // Entry from drop down menu + additional comment $colonseparator = wfMessage('colon-separator')->inContentLanguage()->text(); $reason = $deleteReasonList . $colonseparator . $deleteReason; } else { $reason = $deleteReasonList; } if ($request->wasPosted() && $user->matchEditToken($request->getVal('wpEditToken'), array('delete', $this->getTitle()->getPrefixedText()))) { # Flag to hide all contents of the archived revisions $suppress = $request->getVal('wpSuppress') && $user->isAllowed('suppressrevision'); $this->doDelete($reason, $suppress); if ($user->isLoggedIn() && $request->getCheck('wpWatch') != $user->isWatched($title)) { if ($request->getCheck('wpWatch')) { WatchAction::doWatch($title, $user); } else { WatchAction::doUnwatch($title, $user); } } return; } // Generate deletion reason $hasHistory = false; if (!$reason) { try { $reason = $this->generateReason($hasHistory); } catch (MWException $e) { # if a page is horribly broken, we still want to be able to delete it. so be lenient about errors here. wfDebug("Error while building auto delete summary: {$e}"); $reason = ''; } } // If the page has a history, insert a warning if ($hasHistory) { $revisions = $this->mTitle->estimateRevisionCount(); // @todo FIXME: i18n issue/patchwork message $this->getContext()->getOutput()->addHTML('<strong class="mw-delete-warning-revisions">' . wfMessage('historywarning')->numParams($revisions)->parse() . wfMessage('word-separator')->plain() . Linker::linkKnown($title, wfMessage('history')->escaped(), array('rel' => 'archives'), array('action' => 'history')) . '</strong>'); if ($this->mTitle->isBigDeletion()) { global $wgDeleteRevisionsLimit; $this->getContext()->getOutput()->wrapWikiMsg("<div class='error'>\n\$1\n</div>\n", array('delete-warning-toobig', $this->getContext()->getLanguage()->formatNum($wgDeleteRevisionsLimit))); } } $this->confirmDelete($reason); }
function do_post_rename($formatter, $options) { global $DBInfo; $new = $options['name']; if ($new[0] == '~' and ($p = strpos($new, '/')) !== false) { // Namespace renaming $dummy = substr($new, 1, $p - 1); $dummy2 = substr($new, $p + 1); $options['name'] = $dummy . '~' . $dummy2; } if (isset($options['name']) and trim($options['name'])) { if ($DBInfo->hasPage($options['page']) && !$DBInfo->hasPage($options['name'])) { $title = sprintf(_("\"%s\" is renamed !"), $options['page']); $formatter->send_header("", $options); $formatter->send_title($title, "", $options); $new_encodedname = _rawurlencode($options['name']); if ($options['pagenames'] and is_array($options['pagenames'])) { $regex = preg_quote($options['page']); $options['minor'] = 1; foreach ($options['pagenames'] as $page) { $p = new WikiPage($page); if (!$p->exists()) { continue; } $f = new Formatter($p); $body = $p->_get_raw_body(); $body = preg_replace("/{$regex}/m", $options['name'], $body); $f->page->write($body); if (!$options['show_only']) { $DBInfo->savePage($f->page, '', $options); } $msg .= sprintf(_("'%s' is changed"), $f->link_tag(_rawurlencode($page), "?action=highlight&value=" . $new_encodedname)) . "<br />"; } } print $msg; if (!$options['show_only']) { $DBInfo->renamePage($options['page'], $options['name'], $options); } print sprintf(_("'%s' is renamed as '%s' successfully."), $options['page'], $formatter->link_tag($options['name'], "?action=highlight&value=" . $new_encodedname)); $formatter->send_footer("", $options); return; } else { $title = sprintf(_("Fail to rename \"%s\" !"), $options['page']); $formatter->send_header("", $options); $formatter->send_title($title, "", $options); $formatter->send_footer("", $options); return; } } $title = sprintf(_("Rename \"%s\" ?"), $options['page']); $formatter->send_header("", $options); $formatter->send_title($title, "", $options); #<tr><td align='right'><input type='checkbox' name='show' checked='checked' />show only </td><td><input type='password' name='passwd'> $obtn = _("Old name:"); $nbtn = _("New name:"); print "<form method='post'>\n<table border='0'>\n<tr><td align='right'>{$obtn} </td><td><b>{$options['page']}</b></td></tr>\n<tr><td align='right'>{$nbtn} </td><td><input name='name' /></td></tr>\n"; $rename_button = _("Rename"); if ($options['value'] == 'check_backlinks') { print "<tr><td colspan='2'>\n"; print check_backlinks($formatter, $options); print "</td></tr>\n"; $rename_button = _("Rename and fix Backlinks"); } if ($DBInfo->security->is_protected("rename", $options)) { print "<tr><td align='right'>" . _("Password") . ": </td><td><input type='password' name='passwd' /> " . _("Only WikiMaster can rename this page") . "</td></tr>\n"; } print "<tr><td colspan='2'><input type='checkbox' name='history' />" . _("with revision history") . "</td></tr>\n"; print "<tr><td colspan='2'><input type='checkbox' name='show_only' checked='checked' />" . _("show only") . "</td></tr>\n"; print "<tr><td></td><td><input type='submit' name='button_rename' value='{$rename_button}' />"; print " <a href='?action=rename&value=check_backlinks'>" . _("Check backlinks") . "</a>"; print "</td></tr>\n"; print "\n</table>\n <input type=hidden name='action' value='rename' />\n </form>"; # $formatter->send_page(); $formatter->send_footer("", $options); }
/** * get updated info * */ function ajax_RecentChanges($formatter, $options = array()) { global $DBInfo; // list style if (!empty($options['type']) and $options['type'] == 'list') { $options['call'] = 1; $options['ajax'] = 1; $opt = ''; if (isset($options['datefmt'])) { $opt .= $options['datefmt'] . ','; } $opt .= 'list'; if (!empty($options['item'])) { $opt .= ',item=' . $options['item']; } $out = macro_RecentChanges($formatter, $opt, $options); echo $out; return; } if (empty($options['value'])) { echo '[]'; return; } $checknew = 0; $checkchange = 0; if (!empty($options['new'])) { $checknew = 1; } if (!empty($options['change'])) { $checkchange = 1; } require_once 'lib/JSON.php'; $json = new Services_JSON(); $rclist = $json->decode($options['value']); if (!is_array($rclist)) { echo '[]'; return; } // get bookmark parameter and call bookmark macro if (!empty($options['time'])) { if (is_numeric($options['time']) and $options['time'] > 0) { $formatter->macro_repl('Bookmark', '', $options); //$bookmark = $options['time']; } } $u = $DBInfo->user; # retrive user info if ($u->id != 'Anonymous') { $bookmark = !empty($u->info['bookmark']) ? $u->info['bookmark'] : ''; } else { $bookmark = $u->bookmark; } if (!$bookmark) { $bookmark = time(); } $tz_offset = $formatter->tz_offset; $info = array(); foreach ($rclist as $page_name) { $p = new WikiPage($page_name); if (!$p->exists()) { $info[$page_name]['state'] = 'deleted'; continue; // XXX } $ed_time = $p->mtime(); if ($ed_time <= $bookmark) { break; } $info[$page_name]['state'] = 'updated'; $add = 0; $del = 0; if ($checknew or $checkchange) { $v = $p->get_rev($bookmark); if (empty($v)) { $info[$page_name]['state'] = 'new'; $add += $p->lines(); } } if ($checkchange) { if (empty($v)) { // new $infos = array(); } else { $infos = $p->get_info('>' . $bookmark); } foreach ($infos as $inf) { $tmp = explode(' ', trim($inf[1])); if (isset($tmp[1])) { $add += $tmp[0]; $del += $tmp[1]; } } $info[$page_name]['add'] = $add; $info[$page_name]['del'] = $del; } } $info['__-_-bookmark-_-__'] = $bookmark; echo $json->encode($info); return; }
function html_ref($refPage, $appearance, $hover = '', $anchor = '', $anchor_appearance = '') { global $db, $SeparateLinkWords, $page, $pagestore; if ($hover != '') { $hover = ' alt="' . $hover . '" title="' . $hover . '"'; } $redirect_from = ''; if ($page == 'RecentChanges') { $p_exists = $pagestore->page_exists($refPage); } else { $p = new WikiPage($db, $refPage); $p_exists = $p->exists(); // automatically handle plurals if (!$p_exists) { foreach (array('s', 'es') as $plural) { if (substr($refPage, -strlen($plural)) == $plural) { $temp_refPage = substr($refPage, 0, strlen($refPage) - strlen($plural)); $p = new WikiPage($db, $temp_refPage); if ($p_exists = $p->exists()) { $redirect_from = $refPage; $refPage = $temp_refPage; break; } } } } } $twintext = ""; $onlytwin = ""; $twin = $pagestore->twinpages($refPage, $page); if (!$p_exists && count($twin) == 1) { $onlytwin = html_twin_x($twin[0][0], $twin[0][1], $twin[0][1]); } else { if (count($twin)) { // point at the sisterwiki's version $n = 1; foreach ($twin as $site) { $twintext = $twintext . html_twin_x($site[0], $n, $site[1]); $n++; } $twintext = '<sup>' . $twintext . '</sup>'; } } if ($p_exists) { if ($SeparateLinkWords && $refPage == $appearance) { $appearance = html_split_name($refPage); } $result = '<a href="' . viewURL($refPage) . ($redirect_from ? '&redirect_from=' . $redirect_from : '') . $anchor . '"' . $hover . '>' . $appearance . $anchor_appearance . '</a>' . $onlytwin; } else { $result = ""; if (validate_page($refPage) == 1 && $appearance == $refPage) { if ($onlytwin) { $result = $onlytwin; } else { $result = $refPage; } } else { // Puts the appearance between parenthesis if there's a space in it. if (strpos($appearance, ' ') === false) { $tempAppearance = $appearance; } else { $tempAppearance = "({$appearance})"; } if ($onlytwin) { $result = $onlytwin; } else { $result = $tempAppearance; } } $result = $result . '<a href="' . editURL($refPage, '', $page) . '"' . ' title="Create this Wiki page" ' . $hover . '>?</a>' . $twintext; } return $result; }
/** * This method is called after an article has been saved. * This is the server side of IntraACL protection toolbar, * allowing to modify page SD together with article save. * * No modifications are made if either: * - Page namespace is ACL * - User is anonymous * - Users don't have the right to modify page SD * - 'haloacl_protect_with' request value is invalid * (valid are 'unprotected', or ID/name of predefined right or THIS page SD) * * @param WikiPage $article The article which was saved * @param User $user The user who saved the article * @param string $text The content of the article * * @return true */ public static function articleSaveComplete_SaveSD($article, User $user, $text) { global $wgUser, $wgRequest, $haclgContLang; if ($user->isAnon()) { // Don't handle protection toolbar for anonymous users return true; } if ($article->getTitle()->getNamespace() == HACL_NS_ACL) { // Don't use protection toolbar for articles in the namespace ACL. // Note that embedded content protection toolbar is handled nevertheless. return true; } // Obtain user selection // hacl_protected_with == '<peType>:<peID>' or 'unprotected' $selectedSD = $wgRequest->getVal('hacl_protected_with'); if ($selectedSD && $selectedSD != 'unprotected') { // Some SD is selected by the user // Ignore selection of invalid SDs $selectedSD = array_map('intval', explode('-', $selectedSD, 2)); if (count($selectedSD) != 2) { $selectedSD = NULL; } } if (!$selectedSD) { return true; } if ($selectedSD == 'unprotected') { $selectedSD = NULL; } // Check if current SD must be modified if ($article->exists()) { $pageSD = IACLDefinition::getSDForPE(IACL::PE_PAGE, $article->getId()); if ($pageSD && $selectedSD) { // Check if page's SD ID passed as selected if ($pageSD['pe_type'] == $selectedSD[0] && $pageSD['pe_id'] == $selectedSD[1]) { return true; } // Check if page's SD is single inclusion and it is passed as selected if ($pageSD['single_child'] == $selectedSD) { return true; } } } // Check if no protection selected and no protection exists if (!$selectedSD && !$pageSD) { return true; } // Check if other SD is a predefined right // FIXME Allow selecting non-PE_RIGHTs in quick acl toolbar? if ($selectedSD && $selectedSD[0] != IACL::PE_RIGHT) { return true; } // Check SD modification rights $pageSDName = IACLDefinition::nameOfSD(IACL::PE_PAGE, $article->getTitle()); $etc = haclfDisableTitlePatch(); $pageSDTitle = Title::newFromText($pageSDName); haclfRestoreTitlePatch($etc); if (!$pageSDTitle->userCan('edit')) { return true; } $newSDArticle = new WikiPage($pageSDTitle); if ($selectedSD) { // Create/modify page SD $selectedSDTitle = IACLDefinition::getSDTitle($selectedSD); $content = '{{#predefined right: ' . $selectedSDTitle->getText() . "}}\n" . '{{#manage rights: assigned to = User:'******'hacl_comment_protect_with', $selectedSDTitle->getFullText())); } else { // Remove page SD $newSDArticle->doDeleteArticle(wfMsg('hacl_comment_unprotect')); } // Continue hook processing return true; }
function macro_ISBN($formatter, $value = "") { global $DBInfo; // http://www.isbn-international.org/en/identifiers/allidentifiers.html $default_map = array('89' => 'Aladdin'); $ISBN_MAP = "IsbnMap"; $DEFAULT = <<<EOS Amazon http://www.amazon.com/exec/obidos/ISBN= http://images.amazon.com/images/P/\$ISBN.01.MZZZZZZZ.gif Aladdin http://www.aladdin.co.kr/shop/wproduct.aspx?ISBN= http://image.aladdin.co.kr/cover/cover/\$ISBN_1.gif @(http://image\\..*/cover/(?:[^\\s_/]*\$ISBN_\\d\\.(?:jpe?g|gif)))@ Gang http://kangcom.com/common/qsearch/search.asp?s_flag=T&s_text= http://kangcom.com/l_pic/\$ISBN.jpg @bookinfo\\.asp\\?sku=(\\d+)"@ EOS; $DEFAULT_ISBN = "Amazon"; $re_isbn = "/^([0-9\\-]+[xX]?)(?:,\\s*)?(([A-Z][A-Za-z]*)?(?:,)?(.*))?/x"; if ($value != '') { $test = preg_match($re_isbn, $value, $match); if ($test === false) { return "<p><strong class=\"error\">Invalid ISBN \"%value\"</strong></p>"; } } $list = $DEFAULT; $map = new WikiPage($ISBN_MAP); if ($map->exists()) { $list .= $map->get_raw_body(); } $lists = explode("\n", $list); $ISBN_list = array(); foreach ($lists as $line) { if (!$line or !preg_match("/^[A-Z]/", $line[0])) { continue; } $dum = explode(" ", rtrim($line)); $re = ''; $sz = sizeof($dum); if (!preg_match('/^(http|ftp)/', $dum[1])) { continue; } if ($sz == 2) { $dum[] = $ISBN_list[$DEFAULT_ISBN][1]; } else { if ($sz != 3) { if ($sz == 4) { if (($p = strpos(substr($dum[3], 1), $dum[3][0])) !== false) { $retest = substr($dum[3], 0, $p + 2); } else { $retest = $dum[3]; } if (preg_match($retest, '') !== false) { $re = $dum[3]; } } else { continue; } } } $ISBN_list[$dum[0]] = array($dum[1], $dum[2], $re); } if ($value == '') { $out = "<ul>"; foreach ($ISBN_list as $interwiki => $v) { $href = $ISBN_list[$interwiki][0]; if (strpos($href, '$ISBN') === false) { $url = $href . '0738206679'; } else { $url = str_replace('$ISBN', '0738206679', $href); } $icon = $DBInfo->imgs_url_interwiki . strtolower($interwiki) . '-16.png'; $sx = 16; $sy = 16; if ($DBInfo->intericon[$interwiki]) { $icon = $DBInfo->intericon[$interwiki][2]; $sx = $DBInfo->intericon[$interwiki][0]; $sy = $DBInfo->intericon[$interwiki][1]; } $out .= "<li><img src='{$icon}' width='{$sx}' height='{$sy}' " . "align='middle' alt='{$interwiki}:' /><a href='{$url}'>{$interwiki}</a>: " . "<tt class='link'>{$href}</tt></li>"; } $out .= "</ul>\n"; return $out; } $isbn2 = $match[1]; $isbn = str_replace('-', '', $isbn2); #print_r($match); if ($match[3]) { if (strtolower($match[2][0]) == 'k') { $lang = 'Aladdin'; } else { $lang = $match[3]; } } else { $cl = strlen($isbn); if ($cl == 13) { $lang_code = substr($isbn, 3, 2); } else { $lang_code = substr($isbn, 0, 2); } // 89 if (!empty($default_map[$lang_code])) { $lang = $default_map[$lang_code]; } else { $lang = $DEFAULT_ISBN; } } $attr = ''; $ext = ''; if ($match[2]) { $args = explode(',', $match[2]); foreach ($args as $arg) { $arg = trim($arg); if ($arg == 'noimg') { $noimg = 1; } else { if (strtolower($arg) == 'k') { $lang = 'Aladdin'; } else { $name = strtok($arg, '='); $val = strtok(' '); if ($val) { $attr .= $name . '="' . $val . '" '; } #XXX if ($name == 'align') { $attr .= 'class="img' . ucfirst($val) . '" '; } if ($name == 'img') { $ext = $val; } } } } } if ($ISBN_list[$lang]) { $booklink = $ISBN_list[$lang][0]; $imglink = $ISBN_list[$lang][1]; $imgre = $ISBN_list[$lang][2]; } else { $booklink = $ISBN_list[$DEFAULT_ISBN][0]; $imglink = $ISBN_list[$DEFAULT_ISBN][1]; } if (strpos($booklink, '$ISBN') === false) { $booklink .= $isbn; } else { if (strpos($booklink, '$ISBN2') === false) { $booklink = str_replace('$ISBN', $isbn, $booklink); } else { $booklink = str_replace('$ISBN2', $isbn2, $booklink); } } if (empty($noimg) and $imgre and get_cfg_var('allow_url_fopen')) { if (($p = strpos(substr($imgre, 1), $imgre[0])) !== false) { $imgrepl = substr($imgre, $p + 2); $imgre = substr($imgre, 0, $p + 2); if ($imgrepl == '@') { $imgrepl = ''; } $imgre = str_replace('$ISBN', $isbn, $imgre); } $md5sum = md5($booklink); // check cache $bcache = new Cache_text('isbn'); if (empty($formatter->refresh) and $bcache->exists($md5sum)) { $imgname = trim($bcache->fetch($md5sum)); $fetch_ok = 1; } else { // fetch the bookinfo page and grep the imagname of the book. $fd = fopen($booklink, 'r'); if (is_resource($fd)) { while (!feof($fd)) { $line = fgets($fd, 1024); preg_match($imgre, $line, $match); if (!empty($match[1])) { $bcache->update($md5sum, $match[1]); $imgname = $match[1]; $fetch_ok = 1; break; } } fclose($fd); } } if ($fetch_ok) { if ($imgrepl) { $imglink = preg_replace('@' . $imgrepl . '@', $imgname, $imglink); } else { if (!preg_match('/^https?:/', $imgname)) { $imglink = str_replace('$ISBN', $imgname, $imglink); } else { $imglink = $imgname; } } } if (!empty($fetch_ok) and !empty($DBInfo->isbn_img_download)) { # some sites such as the IMDB check the referer and # do not permit to show any of its images # the $isbn_img_download option is needed to show such images preg_match('/^(.*)\\.(jpeg|jpg|gif|png)$/i', $imglink, $m); if (!empty($m[1]) and isset($m[2])) { $myimglink = md5($m[1]) . '.' . $m[2]; } if (isset($m[2])) { # skip XXX } else { if (file_exists($DBInfo->upload_dir . '/isbn/' . $myimglink)) { $mlink = $formatter->macro_repl('attachment', 'isbn:' . $myimglink, 1); $imglink = qualifiedUrl($DBInfo->url_prefix . '/' . $mlink); } else { $fd = fopen($imglink, 'r'); if (is_resource($fd)) { $myimg = ''; while (!feof($fd)) { $myimg .= fread($fd, 1024); } fclose($fd); if (!is_dir($DBInfo->upload_dir . '/isbn/')) { umask(00); mkdir($DBInfo->upload_dir . '/isbn/', 0777); umask($DBInfo->umask); } $fd = fopen($DBInfo->upload_dir . '/isbn/' . $myimglink, 'w'); if (is_resource($fd)) { fwrite($fd, $myimg); fclose($fd); } } } } } } if (empty($fetch_ok)) { if (strpos($imglink, '$ISBN') === false) { $imglink .= $isbn; } else { if (strpos($imglink, '$ISBN2') === false) { $imglink = str_replace('$ISBN', $isbn, $imglink); } else { $imglink = str_replace('$ISBN2', $isbn2, $imglink); } if ($ext) { $imglink = preg_replace('/\\.(gif|jpeg|jpg|png|bmp)$/i', $ext, $imglink); } } } if (!empty($noimg)) { $icon = $DBInfo->imgs_url_interwiki . strtolower($lang) . '-16.png'; $sx = 16; $sy = 16; if (!empty($DBInfo->intericon[$lang])) { $icon = $DBInfo->intericon[$lang][2]; $sx = $DBInfo->intericon[$lang][0]; $sy = $DBInfo->intericon[$lang][1]; } return "<img src='{$icon}' alt='{$lang}:' align='middle' width='{$sx}' height='{$sy}' title='{$lang}' />" . "[<a href='{$booklink}'>ISBN-{$isbn2}</a>]"; } else { return "<a href='{$booklink}'><img src='{$imglink}' border='1' title='{$lang}" . ":ISBN-{$isbn}' alt='[ISBN-{$isbn2}]' class='isbn' {$attr} /></a>"; } }