Example #1
0
 /**
  * Get the last author with the last modification time
  * @param $article Article object
  */
 protected static function getAuthor(Article $article)
 {
     global $wgLang, $wgAllowRealName;
     $user = User::newFromId($article->getUser());
     $timestamp = $article->getTimestamp();
     if ($timestamp) {
         $d = $wgLang->date($article->getTimestamp(), true);
         $t = $wgLang->time($article->getTimestamp(), true);
     } else {
         $d = '';
         $t = '';
     }
     return wfMsg('lastmodifiedatby', $d, $t, self::userLink($user));
 }
 function newAttachmentData($id)
 {
     $obj = $this->cacheManager->retrieveAtachmentData($id);
     if ($obj instanceof \PageAttachment\Attachment\AttachmentData) {
         $pageAttachmentData = $obj;
     } else {
         $title = \Title::newFromID($id);
         $article = new \Article($title, NS_FILE);
         $file = \wfFindFile($title);
         $size = $file->getSize();
         $description = $this->replaceHtmlTags($file->getDescriptionText());
         $dateUploaded = $article->getTimestamp();
         $uploadedBy = null;
         if ($this->runtimeConfig->isShowUserRealName()) {
             $uploadedBy = \User::whoIsReal($article->getUser());
         }
         if ($uploadedBy == null) {
             $uploadedBy = \User::whoIs($article->getUser());
         }
         $attachedToPages = null;
         if ($this->securityManager->isRemoveAttachmentPermanentlyEnabled()) {
             $attachedToPages = $this->getAttachedToPages($id);
         }
         $pageAttachmentData = new AttachmentData($id, $title, $size, $description, $dateUploaded, $uploadedBy, $attachedToPages);
         $this->cacheManager->storeAttachmentData($pageAttachmentData);
     }
     return $pageAttachmentData;
 }
 function timestamp(&$parser, &$ts)
 {
     if (isset($parser->mTagHooks['citation'])) {
         $ts = wfTimestamp(TS_UNIX, $this->mArticle->getTimestamp());
     }
     return true;
 }
Example #4
0
function createComment($title = null, $commenter = null, $text = null)
{
    global $wgTitle;
    $text = $text ? $text : 'The quick brown fox jumps over the lazy dog';
    $commentTitle = Title::newFromText(sprintf("%s/%s-%s", $title->getText(), $commenter, wfTimestampNow()), NS_BLOG_ARTICLE_TALK);
    $wgTitle = $commentTitle;
    /**
     * add article using EditPage class (for hooks)
     */
    $result = null;
    $article = new Article($commentTitle, 0);
    $editPage = new EditPage($article);
    $editPage->edittime = $article->getTimestamp();
    $editPage->textbox1 = $text;
    $retval = $editPage->internalAttemptSave($result);
    $value = $retval->value;
    Wikia::log(__METHOD__, "editpage", "Returned value {$value}");
    return array($value, $article);
}
/**
 * Injects handling of the 'feed' action.
 * Usage: $wgHooks['UnknownAction'][] = 'wfWikiArticleFeedsAction';
 * @param $action Handle to an action string (presumably same as global $action).
 * @param $article Article to be converted to rss or atom feed
 */
function wfWikiArticleFeedsAction( $action, $article ) {

	# If some other action is in the works, cut and run!
	if ( $action != 'feed' ) return true;

	global $wgOut, $wgRequest, $wgFeedClasses, $wgFeedCacheTimeout, $wgDBname, $messageMemc, $wgSitename;

	# Get query parameters
	$feedFormat = $wgRequest->getVal( 'feed', 'atom' );
	$filterTags = $wgRequest->getVal( 'tags', null );

	# Process requested tags for use in keys
	if ( $filterTags ) {
		$filterTags = explode( ',', $filterTags );
		array_walk( $filterTags, 'trim' );
		sort( $filterTags );
	}

	if ( !isset( $wgFeedClasses[$feedFormat] ) ) {
		wfHttpError( 500, "Internal Server Error", "Unsupported feed type." );
		return false;
	}

	# Setup cache-checking vars
	$title = $article->getTitle();
	$titleDBkey = $title->getPrefixedDBkey();
	$tags = ( is_array( $filterTags ) ? ':' . implode( ',', $filterTags ):'' );
	$key = "{$wgDBname}:wikiarticlefeedsextension:{$titleDBkey}:{$feedFormat}{$tags}";
	$timekey = $key . ":timestamp";
	$cachedFeed = false;
	$feedLastmod = $messageMemc->get( $timekey );

	# Dermine last modification time for either the article itself or an included template
	$lastmod = $article->getTimestamp();
	$templates = $article->getUsedTemplates();
	foreach ( $templates as $tTitle ) {
		$tArticle = new Article( $tTitle );
		$tmod = $tArticle->getTimestamp();
		$lastmod = ( $lastmod > $tmod ? $lastmod:$tmod );
	}

	# Check for availability of existing cached version
	if ( ( $wgFeedCacheTimeout > 0 ) && $feedLastmod ) {
		$feedLastmodTS = wfTimestamp( TS_UNIX, $feedLastmod );
		if (
			time() - $feedLastmodTS < $wgFeedCacheTimeout ||
			$feedLastmodTS > wfTimestamp( TS_UNIX, $lastmod )
			) {
			wfDebug( "WikiArticleFeedsExtension: Loading feed from cache ($key; $feedLastmod; $lastmod)...\n" );
			$cachedFeed = $messageMemc->get( $key );
		} else {
			wfDebug( "WikiArticleFeedsExtension: Cached feed timestamp check failed ($feedLastmod; $lastmod)\n" );
		}
	}

	# Display cachedFeed, or generate one from scratch
	global $wgWikiArticleFeedsSkipCache;
	if ( !$wgWikiArticleFeedsSkipCache && is_string( $cachedFeed ) ) {
		wfDebug( "WikiArticleFeedsExtension: Outputting cached feed\n" );
		$feed = new $wgFeedClasses[$feedFormat]( $wgSitename . ' - ' . $title->getText(), '', $title->getFullURL() );
		$feed->httpHeaders();
		echo $cachedFeed;
	} else {
		wfDebug( "WikiArticleFeedsExtension: Rendering new feed and caching it\n" );
		ob_start();
		wfGenerateWikiFeed( $article, $feedFormat, $filterTags );
		$cachedFeed = ob_get_contents();
		ob_end_flush();

		$expire = 3600 * 24; # One day
		$messageMemc->set( $key, $cachedFeed );
		$messageMemc->set( $timekey, wfTimestamp( TS_MW ), $expire );
	}

	# False to indicate that other action handlers should not process this page
	return false;
}
 /**
  * doSaveAsArticle store comment as article
  *
  * @static
  *
  * @param String $text
  * @param Article|WikiPage $article
  * @param User $user
  * @param array $metadata
  * @param string $summary
  *
  * @return Status TODO: Document
  */
 protected static function doSaveAsArticle($text, $article, $user, $metadata = array(), $summary = '')
 {
     $result = null;
     $editPage = new EditPage($article);
     $editPage->edittime = $article->getTimestamp();
     $editPage->textbox1 = self::removeMetadataTag($text);
     $editPage->summary = $summary;
     $editPage->watchthis = $user->isWatched($article->getTitle());
     if (!empty($metadata)) {
         $editPage->textbox1 = $text . Xml::element('ac_metadata', $metadata, ' ');
     }
     $bot = $user->isAllowed('bot');
     return $editPage->internalAttemptSave($result, $bot);
 }
	/**
	 * Prints the mini-form contained at the bottom of various pages, that
	 * allows pages to spoof a normal edit page, that can preview, save,
	 * etc.
	 */
	static function printRedirectForm( $title, $page_contents, $edit_summary, $is_save, $is_preview, $is_diff, $is_minor_edit, $watch_this ) {
		$article = new Article( $title );
		$new_url = $title->getLocalURL( 'action=submit' );
		$starttime = wfTimestampNow();
		$edittime = $article->getTimestamp();
		global $wgUser;
		if ( $wgUser->isLoggedIn() )
			$token = htmlspecialchars( $wgUser->editToken() );
		else
			$token = EDIT_TOKEN_SUFFIX;

		if ( $is_save )
			$action = "wpSave";
		elseif ( $is_preview )
			$action = "wpPreview";
		else // $is_diff
			$action = "wpDiff";

		$text = <<<END
	<form id="editform" name="editform" method="post" action="$new_url">
	<input type="hidden" name="wpTextbox1" id="wpTextbox1" value="$page_contents" />
	<input type="hidden" name="wpSummary" value="$edit_summary" />
	<input type="hidden" name="wpStarttime" value="$starttime" />
	<input type="hidden" name="wpEdittime" value="$edittime" />
	<input type="hidden" name="wpEditToken" value="$token" />
	<input type="hidden" name="$action" />

END;
		if ( $is_minor_edit )
			$text .= '    <input type="hidden" name="wpMinoredit">' . "\n";
		if ( $watch_this )
			$text .= '    <input type="hidden" name="wpWatchthis">' . "\n";
		$text .= <<<END
	</form>
	<script type="text/javascript">
	document.editform.submit();
	</script>

END;
		return $text;
	}
Example #8
0
 public function execute()
 {
     global $wgUser;
     $params = $this->extractRequestParams();
     if (is_null($params['text']) && is_null($params['appendtext']) && is_null($params['prependtext']) && $params['undo'] == 0) {
         $this->dieUsageMsg(array('missingtext'));
     }
     $titleObj = Title::newFromText($params['title']);
     if (!$titleObj || $titleObj->isExternal()) {
         $this->dieUsageMsg(array('invalidtitle', $params['title']));
     }
     if ($params['redirect']) {
         if ($titleObj->isRedirect()) {
             $oldTitle = $titleObj;
             $titles = Title::newFromRedirectArray(Revision::newFromTitle($oldTitle)->getText(Revision::FOR_THIS_USER));
             $redirValues = array();
             foreach ($titles as $id => $newTitle) {
                 if (!isset($titles[$id - 1])) {
                     $titles[$id - 1] = $oldTitle;
                 }
                 $redirValues[] = array('from' => $titles[$id - 1]->getPrefixedText(), 'to' => $newTitle->getPrefixedText());
                 $titleObj = $newTitle;
             }
             $this->getResult()->setIndexedTagName($redirValues, 'r');
             $this->getResult()->addValue(null, 'redirects', $redirValues);
         }
     }
     // Some functions depend on $wgTitle == $ep->mTitle
     global $wgTitle;
     $wgTitle = $titleObj;
     if ($params['createonly'] && $titleObj->exists()) {
         $this->dieUsageMsg(array('createonly-exists'));
     }
     if ($params['nocreate'] && !$titleObj->exists()) {
         $this->dieUsageMsg(array('nocreate-missing'));
     }
     // Now let's check whether we're even allowed to do this
     $errors = $titleObj->getUserPermissionsErrors('edit', $wgUser);
     if (!$titleObj->exists()) {
         $errors = array_merge($errors, $titleObj->getUserPermissionsErrors('create', $wgUser));
     }
     if (count($errors)) {
         $this->dieUsageMsg($errors[0]);
     }
     $articleObj = new Article($titleObj);
     $toMD5 = $params['text'];
     if (!is_null($params['appendtext']) || !is_null($params['prependtext'])) {
         // For non-existent pages, Article::getContent()
         // returns an interface message rather than ''
         // We do want getContent()'s behavior for non-existent
         // MediaWiki: pages, though
         if ($articleObj->getID() == 0 && $titleObj->getNamespace() != NS_MEDIAWIKI) {
             $content = '';
         } else {
             $content = $articleObj->getContent();
         }
         if (!is_null($params['section'])) {
             // Process the content for section edits
             global $wgParser;
             $section = intval($params['section']);
             $content = $wgParser->getSection($content, $section, false);
             if ($content === false) {
                 $this->dieUsage("There is no section {$section}.", 'nosuchsection');
             }
         }
         $params['text'] = $params['prependtext'] . $content . $params['appendtext'];
         $toMD5 = $params['prependtext'] . $params['appendtext'];
     }
     if ($params['undo'] > 0) {
         if ($params['undoafter'] > 0) {
             if ($params['undo'] < $params['undoafter']) {
                 list($params['undo'], $params['undoafter']) = array($params['undoafter'], $params['undo']);
             }
             $undoafterRev = Revision::newFromID($params['undoafter']);
         }
         $undoRev = Revision::newFromID($params['undo']);
         if (is_null($undoRev) || $undoRev->isDeleted(Revision::DELETED_TEXT)) {
             $this->dieUsageMsg(array('nosuchrevid', $params['undo']));
         }
         if ($params['undoafter'] == 0) {
             $undoafterRev = $undoRev->getPrevious();
         }
         if (is_null($undoafterRev) || $undoafterRev->isDeleted(Revision::DELETED_TEXT)) {
             $this->dieUsageMsg(array('nosuchrevid', $params['undoafter']));
         }
         if ($undoRev->getPage() != $articleObj->getID()) {
             $this->dieUsageMsg(array('revwrongpage', $undoRev->getID(), $titleObj->getPrefixedText()));
         }
         if ($undoafterRev->getPage() != $articleObj->getID()) {
             $this->dieUsageMsg(array('revwrongpage', $undoafterRev->getID(), $titleObj->getPrefixedText()));
         }
         $newtext = $articleObj->getUndoText($undoRev, $undoafterRev);
         if ($newtext === false) {
             $this->dieUsageMsg(array('undo-failure'));
         }
         $params['text'] = $newtext;
         // If no summary was given and we only undid one rev,
         // use an autosummary
         if (is_null($params['summary']) && $titleObj->getNextRevisionID($undoafterRev->getID()) == $params['undo']) {
             $params['summary'] = wfMsgForContent('undo-summary', $params['undo'], $undoRev->getUserText());
         }
     }
     // See if the MD5 hash checks out
     if (!is_null($params['md5']) && md5($toMD5) !== $params['md5']) {
         $this->dieUsageMsg(array('hashcheckfailed'));
     }
     $ep = new EditPage($articleObj);
     // EditPage wants to parse its stuff from a WebRequest
     // That interface kind of sucks, but it's workable
     $reqArr = array('wpTextbox1' => $params['text'], 'wpEditToken' => $params['token'], 'wpIgnoreBlankSummary' => '');
     if (!is_null($params['summary'])) {
         $reqArr['wpSummary'] = $params['summary'];
     }
     // Watch out for basetimestamp == ''
     // wfTimestamp() treats it as NOW, almost certainly causing an edit conflict
     if (!is_null($params['basetimestamp']) && $params['basetimestamp'] != '') {
         $reqArr['wpEdittime'] = wfTimestamp(TS_MW, $params['basetimestamp']);
     } else {
         $reqArr['wpEdittime'] = $articleObj->getTimestamp();
     }
     if (!is_null($params['starttimestamp']) && $params['starttimestamp'] != '') {
         $reqArr['wpStarttime'] = wfTimestamp(TS_MW, $params['starttimestamp']);
     } else {
         $reqArr['wpStarttime'] = wfTimestampNow();
         // Fake wpStartime
     }
     if ($params['minor'] || !$params['notminor'] && $wgUser->getOption('minordefault')) {
         $reqArr['wpMinoredit'] = '';
     }
     if ($params['recreate']) {
         $reqArr['wpRecreate'] = '';
     }
     if (!is_null($params['section'])) {
         $section = intval($params['section']);
         if ($section == 0 && $params['section'] != '0' && $params['section'] != 'new') {
             $this->dieUsage("The section parameter must be set to an integer or 'new'", "invalidsection");
         }
         $reqArr['wpSection'] = $params['section'];
     } else {
         $reqArr['wpSection'] = '';
     }
     $watch = $this->getWatchlistValue($params['watchlist'], $titleObj);
     // Deprecated parameters
     if ($params['watch']) {
         $watch = true;
     } elseif ($params['unwatch']) {
         $watch = false;
     }
     if ($watch) {
         $reqArr['wpWatchthis'] = '';
     }
     $req = new FauxRequest($reqArr, true);
     $ep->importFormData($req);
     // Run hooks
     // Handle CAPTCHA parameters
     global $wgRequest;
     if (!is_null($params['captchaid'])) {
         $wgRequest->setVal('wpCaptchaId', $params['captchaid']);
     }
     if (!is_null($params['captchaword'])) {
         $wgRequest->setVal('wpCaptchaWord', $params['captchaword']);
     }
     $r = array();
     if (!wfRunHooks('APIEditBeforeSave', array($ep, $ep->textbox1, &$r))) {
         if (count($r)) {
             $r['result'] = 'Failure';
             $this->getResult()->addValue(null, $this->getModuleName(), $r);
             return;
         } else {
             $this->dieUsageMsg(array('hookaborted'));
         }
     }
     // Do the actual save
     $oldRevId = $articleObj->getRevIdFetched();
     $result = null;
     // Fake $wgRequest for some hooks inside EditPage
     // FIXME: This interface SUCKS
     $oldRequest = $wgRequest;
     $wgRequest = $req;
     $retval = $ep->internalAttemptSave($result, $wgUser->isAllowed('bot') && $params['bot']);
     $wgRequest = $oldRequest;
     global $wgMaxArticleSize;
     switch ($retval) {
         case EditPage::AS_HOOK_ERROR:
         case EditPage::AS_HOOK_ERROR_EXPECTED:
             $this->dieUsageMsg(array('hookaborted'));
         case EditPage::AS_IMAGE_REDIRECT_ANON:
             $this->dieUsageMsg(array('noimageredirect-anon'));
         case EditPage::AS_IMAGE_REDIRECT_LOGGED:
             $this->dieUsageMsg(array('noimageredirect-logged'));
         case EditPage::AS_SPAM_ERROR:
             $this->dieUsageMsg(array('spamdetected', $result['spam']));
         case EditPage::AS_FILTERING:
             $this->dieUsageMsg(array('filtered'));
         case EditPage::AS_BLOCKED_PAGE_FOR_USER:
             $this->dieUsageMsg(array('blockedtext'));
         case EditPage::AS_MAX_ARTICLE_SIZE_EXCEEDED:
         case EditPage::AS_CONTENT_TOO_BIG:
             $this->dieUsageMsg(array('contenttoobig', $wgMaxArticleSize));
         case EditPage::AS_READ_ONLY_PAGE_ANON:
             $this->dieUsageMsg(array('noedit-anon'));
         case EditPage::AS_READ_ONLY_PAGE_LOGGED:
             $this->dieUsageMsg(array('noedit'));
         case EditPage::AS_READ_ONLY_PAGE:
             $this->dieReadOnly();
         case EditPage::AS_RATE_LIMITED:
             $this->dieUsageMsg(array('actionthrottledtext'));
         case EditPage::AS_ARTICLE_WAS_DELETED:
             $this->dieUsageMsg(array('wasdeleted'));
         case EditPage::AS_NO_CREATE_PERMISSION:
             $this->dieUsageMsg(array('nocreate-loggedin'));
         case EditPage::AS_BLANK_ARTICLE:
             $this->dieUsageMsg(array('blankpage'));
         case EditPage::AS_CONFLICT_DETECTED:
             $this->dieUsageMsg(array('editconflict'));
             // case EditPage::AS_SUMMARY_NEEDED: Can't happen since we set wpIgnoreBlankSummary
         // case EditPage::AS_SUMMARY_NEEDED: Can't happen since we set wpIgnoreBlankSummary
         case EditPage::AS_TEXTBOX_EMPTY:
             $this->dieUsageMsg(array('emptynewsection'));
         case EditPage::AS_SUCCESS_NEW_ARTICLE:
             $r['new'] = '';
         case EditPage::AS_SUCCESS_UPDATE:
             $r['result'] = 'Success';
             $r['pageid'] = intval($titleObj->getArticleID());
             $r['title'] = $titleObj->getPrefixedText();
             // HACK: We create a new Article object here because getRevIdFetched()
             // refuses to be run twice, and because Title::getLatestRevId()
             // won't fetch from the master unless we select for update, which we
             // don't want to do.
             $newArticle = new Article($titleObj);
             $newRevId = $newArticle->getRevIdFetched();
             if ($newRevId == $oldRevId) {
                 $r['nochange'] = '';
             } else {
                 $r['oldrevid'] = intval($oldRevId);
                 $r['newrevid'] = intval($newRevId);
                 $r['newtimestamp'] = wfTimestamp(TS_ISO_8601, $newArticle->getTimestamp());
             }
             break;
         case EditPage::AS_SUMMARY_NEEDED:
             $this->dieUsageMsg(array('summaryrequired'));
         case EditPage::AS_END:
             // This usually means some kind of race condition
             // or DB weirdness occurred. Fall through to throw an unknown
             // error.
             // This needs fixing higher up, as Article::doEdit should be
             // used rather than Article::updateArticle, so that specific
             // error conditions can be returned
         // This usually means some kind of race condition
         // or DB weirdness occurred. Fall through to throw an unknown
         // error.
         // This needs fixing higher up, as Article::doEdit should be
         // used rather than Article::updateArticle, so that specific
         // error conditions can be returned
         default:
             $this->dieUsageMsg(array('unknownerror', $retval));
     }
     $this->getResult()->addValue(null, $this->getModuleName(), $r);
 }
Example #9
0
 /**
  * this fucntion hast three tasks (depending on $exec):
  * (1) show an edit dialogue for template fields (exec = edit)
  * (2) set template parameters to  values specified in the query (exec=set)v
  * (2) preview the source code including any changes of these parameters made in the edit form or with other changes (exec=preview)
  * (3) save the article with the changed value set or with other changes (exec=save)
  * "other changes" means that a regexp can be applied to the source text or arbitrary text can be
  * inserted before or after a pattern occuring in the text
  */
 function updateArticleByRule($title, $text, $rulesText)
 {
     // we use ; as command delimiter; \; stands for a semicolon
     // \n is translated to a real linefeed
     $rulesText = str_replace(";", '°', $rulesText);
     $rulesText = str_replace('\\°', ';', $rulesText);
     $rulesText = str_replace("\\n", "\n", $rulesText);
     $rules = split('°', $rulesText);
     $exec = 'edit';
     $replaceThis = '';
     $replacement = '';
     $after = '';
     $insertionAfter = '';
     $before = '';
     $insertionBefore = '';
     $template = '';
     $parameter = array();
     $value = array();
     $afterparm = array();
     $format = array();
     $preview = array();
     $save = array();
     $tooltip = array();
     $optional = array();
     $lastCmd = '';
     $message = '';
     $summary = '';
     $editForm = false;
     $action = '';
     $hidden = array();
     $legendPage = '';
     $instructionPage = '';
     $table = '';
     $fieldFormat = '';
     $nr = -1;
     foreach ($rules as $rule) {
         if (preg_match('/^\\s*#/', $rule) > 0) {
             continue;
             // # is comment symbol
         }
         $rule = preg_replace('/^[\\s]*/', '', $rule);
         // strip leading white space
         $cmd = preg_split("/ +/", $rule, 2);
         if (count($cmd) > 1) {
             $arg = $cmd[1];
         } else {
             $arg = '';
         }
         $cmd[0] = trim($cmd[0]);
         // after ... insert ...     ,   before ... insert ...
         if ($cmd[0] == 'before') {
             $before = $arg;
             $lastCmd = 'B';
         }
         if ($cmd[0] == 'after') {
             $after = $arg;
             $lastCmd = 'A';
         }
         if ($cmd[0] == 'insert' && $lastCmd != '') {
             if ($lastCmd == 'A') {
                 $insertionAfter = $arg;
             }
             if ($lastCmd == 'B') {
                 $insertionBefore = $arg;
             }
         }
         if ($cmd[0] == 'template') {
             $template = $arg;
         }
         if ($cmd[0] == 'parameter') {
             $nr++;
             $parameter[$nr] = $arg;
             if ($nr > 0) {
                 $afterparm[$nr] = array($parameter[$nr - 1]);
                 $n = $nr - 1;
                 while ($n > 0 && array_key_exists($n, $optional)) {
                     $n--;
                     $afterparm[$nr][] = $parameter[$n];
                 }
             }
         }
         if ($cmd[0] == 'value') {
             $value[$nr] = $arg;
         }
         if ($cmd[0] == 'format') {
             $format[$nr] = $arg;
         }
         if ($cmd[0] == 'tooltip') {
             $tooltip[$nr] = $arg;
         }
         if ($cmd[0] == 'optional') {
             $optional[$nr] = true;
         }
         if ($cmd[0] == 'afterparm') {
             $afterparm[$nr] = array($arg);
         }
         if ($cmd[0] == 'legend') {
             $legendPage = $arg;
         }
         if ($cmd[0] == 'instruction') {
             $instructionPage = $arg;
         }
         if ($cmd[0] == 'table') {
             $table = $arg;
         }
         if ($cmd[0] == 'field') {
             $fieldFormat = $arg;
         }
         if ($cmd[0] == 'replace') {
             $replaceThis = $arg;
         }
         if ($cmd[0] == 'by') {
             $replacement = $arg;
         }
         if ($cmd[0] == 'editform') {
             $editForm = $arg;
         }
         if ($cmd[0] == 'action') {
             $action = $arg;
         }
         if ($cmd[0] == 'hidden') {
             $hidden[] = $arg;
         }
         if ($cmd[0] == 'preview') {
             $preview[] = $arg;
         }
         if ($cmd[0] == 'save') {
             $save[] = $arg;
         }
         if ($cmd[0] == 'summary') {
             $summary = $arg;
         }
         if ($cmd[0] == 'exec') {
             $exec = $arg;
             // desired action (set or edit or preview)
         }
     }
     if ($summary == '') {
         $summary .= "\nbulk update:";
         if ($replaceThis != '') {
             $summary .= "\n replace {$replaceThis}\n by {$replacement}";
         }
         if ($before != '') {
             $summary .= "\n before  {$before}\n insertionBefore";
         }
         if ($after != '') {
             $summary .= "\n after   {$after}\n insertionAfter";
         }
     }
     // perform changes to the wiki source text =======================================
     if ($replaceThis != '') {
         $text = preg_replace("{$replaceThis}", $replacement, $text);
     }
     if ($insertionBefore != '' && $before != '') {
         $text = preg_replace("/({$before})/", $insertionBefore . '\\1', $text);
     }
     if ($insertionAfter != '' && $after != '') {
         $text = preg_replace("/({$after})/", '\\1' . $insertionAfter, $text);
     }
     // deal with template parameters =================================================
     global $wgRequest, $wgUser;
     if ($template != '') {
         if ($exec == 'edit') {
             $tpv = $this->getTemplateParmValues($text, $template);
             $legendText = '';
             if ($legendPage != '') {
                 $legendTitle = '';
                 global $wgParser, $wgUser;
                 $parser = clone $wgParser;
                 DPLInclude::text($parser, $legendPage, $legendTitle, $legendText);
                 $legendText = preg_replace('/^.*?\\<section\\s+begin\\s*=\\s*legend\\s*\\/\\>/s', '', $legendText);
                 $legendText = preg_replace('/\\<section\\s+end\\s*=\\s*legend\\s*\\/\\>.*/s', '', $legendText);
             }
             $instructionText = '';
             $instructions = array();
             if ($instructionPage != '') {
                 $instructionTitle = '';
                 global $wgParser, $wgUser;
                 $parser = clone $wgParser;
                 DPLInclude::text($parser, $instructionPage, $instructionTitle, $instructionText);
                 $instructions = $this->getTemplateParmValues($instructionText, 'Template field');
             }
             // construct an edit form containing all template invocations
             $form = "<html><form method=post action=\"{$action}\" {$editForm}>\n";
             foreach ($tpv as $call => $tplValues) {
                 $form .= "<table {$table}>\n";
                 foreach ($parameter as $nr => $parm) {
                     // try to extract legend from the docs of the template
                     $myToolTip = '';
                     if (array_key_exists($nr, $tooltip)) {
                         $myToolTip = $tooltip[$nr];
                     }
                     $myInstruction = '';
                     $myType = '';
                     foreach ($instructions as $instruct) {
                         if (array_key_exists('field', $instruct) && $instruct['field'] == $parm) {
                             if (array_key_exists('doc', $instruct)) {
                                 $myInstruction = $instruct['doc'];
                             }
                             if (array_key_exists('type', $instruct)) {
                                 $myType = $instruct['type'];
                             }
                             break;
                         }
                     }
                     $myFormat = '';
                     if (array_key_exists($nr, $format)) {
                         $myFormat = $format[$nr];
                     }
                     $myOptional = array_key_exists($nr, $optional);
                     if ($legendText != '' && $myToolTip == '') {
                         $myToolTip = preg_replace('/^.*\\<section\\s+begin\\s*=\\s*' . preg_quote($parm, '/') . '\\s*\\/\\>/s', '', $legendText);
                         if (strlen($myToolTip) == strlen($legendText)) {
                             $myToolTip = '';
                         } else {
                             $myToolTip = preg_replace('/\\<section\\s+end\\s*=\\s*' . preg_quote($parm, '/') . '\\s*\\/\\>.*/s', '', $myToolTip);
                         }
                     }
                     $myValue = '';
                     if (array_key_exists($parm, $tpv[$call])) {
                         $myValue = $tpv[$call][$parm];
                     }
                     $form .= $this->editTemplateCall($text, $template, $call, $parm, $myType, $myValue, $myFormat, $myToolTip, $myInstruction, $myOptional, $fieldFormat);
                 }
                 $form .= "</table>\n<br /><br />";
             }
             foreach ($hidden as $hide) {
                 $form .= "<input type=hidden " . $hide . " />";
             }
             $form .= "<input type=hidden name=\"token\" value=\"" . $wgUser->editToken() . "\" />";
             foreach ($preview as $prev) {
                 $form .= "<input type=submit " . $prev . " /> ";
             }
             $form .= "</form></html>\n";
             return $form;
         } elseif ($exec == 'set' || $exec == 'preview') {
             // loop over all invocations and parameters, this could be improved to enhance performance
             $matchCount = 10;
             for ($call = 0; $call < 10; $call++) {
                 foreach ($parameter as $nr => $parm) {
                     // set parameters to values specified in the dpl source or get them from the http request
                     if ($exec == 'set') {
                         $myvalue = $value[$nr];
                     } else {
                         if ($call >= $matchCount) {
                             break;
                         }
                         $myValue = $wgRequest->getVal(urlencode($call . '_' . $parm), '');
                     }
                     $myOptional = array_key_exists($nr, $optional);
                     $myAfterParm = array();
                     if (array_key_exists($nr, $afterparm)) {
                         $myAfterParm = $afterparm[$nr];
                     }
                     $text = $this->updateTemplateCall($matchCount, $text, $template, $call, $parm, $myValue, $myAfterParm, $myOptional);
                 }
                 if ($exec == 'set') {
                     break;
                     // values taken from dpl text only populate the first invocation
                 }
             }
         }
     }
     if ($exec == 'set') {
         return $this->updateArticle($title, $text, $summary);
     } elseif ($exec == 'preview') {
         global $wgScriptPath, $wgRequest;
         $titleX = Title::newFromText($title);
         $articleX = new Article($titleX);
         $form = '<html><form id="editform" name="editform" method="post" action="' . $wgScriptPath . '/index.php?title=' . urlencode($title) . '&action=submit" ' . 'enctype="multipart/form-data">' . "\n" . '<input type="hidden" value="" name="wpSection" />' . "\n" . '<input type="hidden" value="' . wfTimestampNow() . '" name="wpStarttime" />' . "\n" . '<input type="hidden" value="' . $articleX->getTimestamp() . '" name="wpEdittime" />' . "\n" . '<input type="hidden" value="" name="wpScrolltop" id="wpScrolltop" />' . "\n" . '<textarea tabindex="1" accesskey="," name="wpTextbox1" id="wpTextbox1" rows="' . $wgUser->getIntOption('rows') . '" cols="' . $wgUser->getIntOption('cols') . '" >' . htmlspecialchars($text) . '</textarea>' . "\n" . '<input type="hidden" name="wpSummary value="' . $summary . '" id="wpSummary" />' . '<input name="wpAutoSummary" type="hidden" value="" />' . '<input id="wpSave" name="wpSave" type="submit" value="Save page" accesskey="s" title="Save your changes [s]" />' . '<input type="hidden" value="' . $wgRequest->getVal('token') . '" name="wpEditToken" />' . "\n" . '</form></html>' . "\n";
         return $form;
     }
     return 'exec must be one of the following: edit, preview, set';
 }
Example #10
0
function lw_createPage($titleObj, $content, $summary = "Page created using [[LyricWiki:SOAP|LyricWiki's SOAP Webservice]]")
{
    global $wgUser;
    wfProfileIn(__METHOD__);
    $retVal = "";
    if ($titleObj == null) {
        $retVal = "Title object was null in lw_createPage. This probably means that the string used to create it was invalid (which could be caused by bad unicode characters).";
    } else {
        if (is_string($titleObj)) {
            $retVal = "Passed a string into lw_createPage() for the pageTitle instead of passing a Title object. Tip: use Title::newFromDBkey() to convert strings into titles.";
        } else {
            if (!is_object($titleObj)) {
                $retVal = "Title object not an object. Please pass a title object into lw_createPage().";
            } else {
                // Create the Article object.
                $article = new Article($titleObj);
                /* @var $article WikiPage */
                $result = null;
                $editPage = new EditPage($article);
                $editPage->edittime = $article->getTimestamp();
                $editPage->textbox1 = $content;
                $bot = $wgUser->isAllowed('bot');
                //this function calls Article::onArticleCreate which clears cache for article and it's talk page - NOTE: I don't know what this comment refers to... it was coppied from /extensions/wikia/ArticleComments/ArticleComment.class.php
                $status = $editPage->internalAttemptSave($result, $bot);
                $value = $status->value;
                if ($value == EditPage::AS_SUCCESS_NEW_ARTICLE || $value == EditPage::AS_SUCCESS_UPDATE) {
                    $retVal = true;
                } else {
                    $retVal = $status->getMessage();
                }
            }
        }
    }
    wfProfileOut(__METHOD__);
    return $retVal;
}
Example #11
0
 /**
  *  create or edit board, if $board = null then we are creating new one
  */
 protected function createOrEditBoard($board, $titletext, $body, $bot = false)
 {
     wfProfileIn(__METHOD__);
     $id = null;
     if (!empty($board)) {
         $id = $board->getId();
     }
     if (self::LEN_OK !== $this->validateLength($titletext, 'title') || self::LEN_OK !== $this->validateLength($body, 'desc')) {
         wfProfileOut(__METHOD__);
         return false;
     }
     Forum::$allowToEditBoard = true;
     if ($id == null) {
         $title = Title::newFromText($titletext, NS_WIKIA_FORUM_BOARD);
     } else {
         $title = Title::newFromId($id, Title::GAID_FOR_UPDATE);
         $nt = Title::newFromText($titletext, NS_WIKIA_FORUM_BOARD);
         $title->moveTo($nt, true, '', false);
         $title = $nt;
     }
     $article = new Article($title);
     $editPage = new EditPage($article);
     $editPage->edittime = $article->getTimestamp();
     $editPage->textbox1 = $body;
     $result = array();
     $retval = $editPage->internalAttemptSave($result, $bot);
     if ($id == null) {
         $title = Title::newFromText($titletext, NS_WIKIA_FORUM_BOARD);
         if (!empty($title)) {
             wfSetWikiaPageProp(WPP_WALL_ORDER_INDEX, $title->getArticleId(), $title->getArticleId());
         }
     }
     Forum::$allowToEditBoard = false;
     wfProfileOut(__METHOD__);
     return $retval;
 }
Example #12
0
/**
 * Save categories sent via AJAX into article
 *
 * @author Maciej Błaszkowski <marooned at wikia-inc.com>
 */
function CategorySelectAjaxSaveCategories($articleId, $categories)
{
    global $wgUser;
    if (wfReadOnly()) {
        $result['error'] = wfMsg('categoryselect-error-db-locked');
        return json_encode($result);
    }
    wfProfileIn(__METHOD__);
    Wikia::setVar('EditFromViewMode', 'CategorySelect');
    $categories = CategorySelectChangeFormat($categories, 'json', 'wiki');
    if ($categories == '') {
        $result['info'] = 'Nothing to add.';
    } else {
        $title = Title::newFromID($articleId);
        if (is_null($title)) {
            $result['error'] = wfMsg('categoryselect-error-not-exist', $articleId);
        } else {
            if ($title->userCan('edit') && !$wgUser->isBlocked()) {
                $result = null;
                $article = new Article($title);
                $article_text = $article->fetchContent();
                $article_text .= $categories;
                $dbw = wfGetDB(DB_MASTER);
                $dbw->begin();
                $editPage = new EditPage($article);
                $editPage->edittime = $article->getTimestamp();
                $editPage->recreate = true;
                $editPage->textbox1 = $article_text;
                $editPage->summary = wfMsgForContent('categoryselect-edit-summary');
                $editPage->watchthis = $editPage->mTitle->userIsWatching();
                $bot = $wgUser->isAllowed('bot');
                $status = $editPage->internalAttemptSave($result, $bot);
                $retval = $status->value;
                Wikia::log(__METHOD__, "editpage", "Returned value {$retval}");
                switch ($retval) {
                    case EditPage::AS_SUCCESS_UPDATE:
                    case EditPage::AS_SUCCESS_NEW_ARTICLE:
                        $dbw->commit();
                        $title->invalidateCache();
                        Article::onArticleEdit($title);
                        $skin = RequestContext::getMain()->getSkin();
                        // return HTML with new categories
                        // OutputPage::tryParserCache become deprecated in MW1.17 and removed in MW1.18 (BugId:30443)
                        $parserOutput = ParserCache::singleton()->get($article, $article->getParserOptions());
                        if ($parserOutput !== false) {
                            $skin->getOutput()->addParserOutput($parserOutput);
                        }
                        $cats = $skin->getCategoryLinks();
                        $result['info'] = 'ok';
                        $result['html'] = $cats;
                        break;
                    case EditPage::AS_SPAM_ERROR:
                        $dbw->rollback();
                        $result['error'] = wfMsg('spamprotectiontext') . '<p>( Case #8 )</p>';
                        break;
                    default:
                        $dbw->rollback();
                        $result['error'] = wfMsg('categoryselect-edit-abort');
                }
            } else {
                $result['error'] = wfMsg('categoryselect-error-user-rights');
            }
        }
    }
    wfProfileOut(__METHOD__);
    return json_encode($result);
}
Example #13
0
 /**
  * Constructor for a single item in the vcard. Requires the URI of the item.
  */
 public function __construct(Title $t, $prefix, $firstname, $lastname, $additionalname, $suffix, $fullname, $tels, $addresses, $emails, $birthday, $jobtitle, $role, $organization, $department, $category, $url, $note)
 {
     $this->uri = $t->getFullURL();
     $this->url = $url;
     // read fullname or guess it in a simple way from other names that are given
     if ($fullname != '') {
         $this->label = $fullname;
     } elseif ($firstname . $lastname != '') {
         $this->label = $firstname . ($firstname != '' && $lastname != '' ? ' ' : '') . $lastname;
     } else {
         $this->label = $t->getText();
     }
     $this->label = SRFVCardEntry::vCardEscape($this->label);
     // read firstname and lastname, or guess it from other names that are given
     if ($firstname . $lastname == '') {
         // guessing needed
         $nameparts = explode(' ', $this->label);
         // Accepted forms for guessing:
         // "Lastname"
         // "Firstname Lastname"
         // "Firstname <Additionalnames> Lastname"
         $this->lastname = SRFvCardEntry::vCardEscape(array_pop($nameparts));
         if (count($nameparts) > 0) {
             $this->firstname = SRFvCardEntry::vCardEscape(array_shift($nameparts));
         }
         foreach ($nameparts as $name) {
             $this->additionalname .= ($this->additionalname != '' ? ',' : '') . SRFvCardEntry::vCardEscape($name);
         }
     } else {
         $this->firstname = SRFvCardEntry::vCardEscape($firstname);
         $this->lastname = SRFvCardEntry::vCardEscape($lastname);
     }
     if ($additionalname != '') {
         $this->additionalname = $additionalname;
     }
     // no escape, can be a value list
     // ^ overwrite above guessing in that case
     $this->prefix = SRFvCardEntry::vCardEscape($prefix);
     $this->suffix = SRFvCardEntry::vCardEscape($suffix);
     $this->tels = $tels;
     $this->addresses = $addresses;
     $this->emails = $emails;
     $this->birthday = $birthday;
     $this->title = SRFvCardEntry::vCardEscape($jobtitle);
     $this->role = SRFvCardEntry::vCardEscape($role);
     $this->organization = SRFvCardEntry::vCardEscape($organization);
     $this->department = SRFvCardEntry::vCardEscape($department);
     $this->category = $category;
     // allow non-escaped "," in here for making a list of categories
     $this->note = SRFvCardEntry::vCardEscape($note);
     $article = new Article($t);
     $this->dtstamp = $article->getTimestamp();
 }
 protected function showHeader()
 {
     global $wgOut, $wgUser, $wgMaxArticleSize, $wgLang;
     if ($this->isConflict) {
         $wgOut->wrapWikiMsg("<div class='mw-explainconflict'>\n\$1\n</div>", 'explainconflict');
         $this->edittime = $this->mArticle->getTimestamp();
     } else {
         if ($this->section != '' && !$this->isSectionEditSupported()) {
             // We use $this->section to much before this and getVal('wgSection') directly in other places
             // at this point we can't reset $this->section to '' to fallback to non-section editing.
             // Someone is welcome to try refactoring though
             $wgOut->showErrorPage('sectioneditnotsupported-title', 'sectioneditnotsupported-text');
             return false;
         }
         if ($this->section != '' && $this->section != 'new') {
             $matches = array();
             if (!$this->summary && !$this->preview && !$this->diff) {
                 preg_match("/^(=+)(.+)\\1/mi", $this->textbox1, $matches);
                 if (!empty($matches[2])) {
                     global $wgParser;
                     $this->summary = "/* " . $wgParser->stripSectionName(trim($matches[2])) . " */ ";
                 }
             }
         }
         if ($this->missingComment) {
             $wgOut->wrapWikiMsg("<div id='mw-missingcommenttext'>\n\$1\n</div>", 'missingcommenttext');
         }
         if ($this->missingSummary && $this->section != 'new') {
             $wgOut->wrapWikiMsg("<div id='mw-missingsummary'>\n\$1\n</div>", 'missingsummary');
         }
         if ($this->missingSummary && $this->section == 'new') {
             $wgOut->wrapWikiMsg("<div id='mw-missingcommentheader'>\n\$1\n</div>", 'missingcommentheader');
         }
         if ($this->hookError !== '') {
             $wgOut->addWikiText($this->hookError);
         }
         if (!$this->checkUnicodeCompliantBrowser()) {
             $wgOut->addWikiMsg('nonunicodebrowser');
         }
         if (isset($this->mArticle) && isset($this->mArticle->mRevision)) {
             // Let sysop know that this will make private content public if saved
             if (!$this->mArticle->mRevision->userCan(Revision::DELETED_TEXT)) {
                 $wgOut->wrapWikiMsg("<div class='mw-warning plainlinks'>\n\$1\n</div>\n", 'rev-deleted-text-permission');
             } elseif ($this->mArticle->mRevision->isDeleted(Revision::DELETED_TEXT)) {
                 $wgOut->wrapWikiMsg("<div class='mw-warning plainlinks'>\n\$1\n</div>\n", 'rev-deleted-text-view');
             }
             if (!$this->mArticle->mRevision->isCurrent()) {
                 $this->mArticle->setOldSubtitle($this->mArticle->mRevision->getId());
                 $wgOut->addWikiMsg('editingold');
             }
         }
     }
     if (wfReadOnly()) {
         $wgOut->wrapWikiMsg("<div id=\"mw-read-only-warning\">\n\$1\n</div>", array('readonlywarning', wfReadOnlyReason()));
     } elseif ($wgUser->isAnon()) {
         if ($this->formtype != 'preview') {
             $wgOut->wrapWikiMsg("<div id=\"mw-anon-edit-warning\">\n\$1</div>", 'anoneditwarning');
         } else {
             $wgOut->wrapWikiMsg("<div id=\"mw-anon-preview-warning\">\n\$1</div>", 'anonpreviewwarning');
         }
     } else {
         if ($this->isCssJsSubpage) {
             # Check the skin exists
             if ($this->isWrongCaseCssJsPage) {
                 $wgOut->wrapWikiMsg("<div class='error' id='mw-userinvalidcssjstitle'>\n\$1\n</div>", array('userinvalidcssjstitle', $this->getContextTitle()->getSkinFromCssJsSubpage()));
             }
             if ($this->formtype !== 'preview') {
                 if ($this->isCssSubpage) {
                     $wgOut->wrapWikiMsg("<div id='mw-usercssyoucanpreview'>\n\$1\n</div>", array('usercssyoucanpreview'));
                 }
                 if ($this->isJsSubpage) {
                     $wgOut->wrapWikiMsg("<div id='mw-userjsyoucanpreview'>\n\$1\n</div>", array('userjsyoucanpreview'));
                 }
             }
         }
     }
     if ($this->mTitle->getNamespace() != NS_MEDIAWIKI && $this->mTitle->isProtected('edit')) {
         # Is the title semi-protected?
         if ($this->mTitle->isSemiProtected()) {
             $noticeMsg = 'semiprotectedpagewarning';
         } else {
             # Then it must be protected based on static groups (regular)
             $noticeMsg = 'protectedpagewarning';
         }
         LogEventsList::showLogExtract($wgOut, 'protect', $this->mTitle->getPrefixedText(), '', array('lim' => 1, 'msgKey' => array($noticeMsg)));
     }
     if ($this->mTitle->isCascadeProtected()) {
         # Is this page under cascading protection from some source pages?
         list($cascadeSources, ) = $this->mTitle->getCascadeProtectionSources();
         $notice = "<div class='mw-cascadeprotectedwarning'>\n\$1\n";
         $cascadeSourcesCount = count($cascadeSources);
         if ($cascadeSourcesCount > 0) {
             # Explain, and list the titles responsible
             foreach ($cascadeSources as $page) {
                 $notice .= '* [[:' . $page->getPrefixedText() . "]]\n";
             }
         }
         $notice .= '</div>';
         $wgOut->wrapWikiMsg($notice, array('cascadeprotectedwarning', $cascadeSourcesCount));
     }
     if (!$this->mTitle->exists() && $this->mTitle->getRestrictions('create')) {
         LogEventsList::showLogExtract($wgOut, 'protect', $this->mTitle->getPrefixedText(), '', array('lim' => 1, 'showIfEmpty' => false, 'msgKey' => array('titleprotectedwarning'), 'wrap' => "<div class=\"mw-titleprotectedwarning\">\n\$1</div>"));
     }
     if ($this->kblength === false) {
         $this->kblength = (int) (strlen($this->textbox1) / 1024);
     }
     if ($this->tooBig || $this->kblength > $wgMaxArticleSize) {
         $wgOut->wrapWikiMsg("<div class='error' id='mw-edit-longpageerror'>\n\$1\n</div>", array('longpageerror', $wgLang->formatNum($this->kblength), $wgLang->formatNum($wgMaxArticleSize)));
     } else {
         if (!wfMessage('longpage-hint')->isDisabled()) {
             $wgOut->wrapWikiMsg("<div id='mw-edit-longpage-hint'>\n\$1\n</div>", array('longpage-hint', $wgLang->formatSize(strlen($this->textbox1)), strlen($this->textbox1)));
         }
     }
 }
 function __construct($file)
 {
     $title = $file->getTitle();
     // og:type
     $this->properties['og:type'] = $this->translateType($this->defaultType);
     // og:url
     $this->properties['og:url'] = $title->getFullURL();
     // og:updated_time
     $article = new Article($title, 0);
     $timestamp = $article->getTimestamp(TS_UNIX, $article->getTimestamp());
     $this->properties['og:updated_time'] = $timestamp;
     // og:locale
     global $wgVersion;
     if (version_compare($wgVersion, '1.18', '>=')) {
         // Title::getPageLanguage() is since 1.18
         $langCode = $title->getPageLanguage()->getCode();
     } else {
         global $wgContLang;
         $langCode = $wgContLang->getCode();
     }
     $this->properties['og:locale'] = FacebookLanguage::getFbLocaleForLangCode($langCode);
     // og:title
     $this->properties['og:title'] = $file->getName();
     // og:image
     if ($file->getMediaType() == MEDIATYPE_BITMAP) {
         $this->properties['og:image'] = $file->getCanonicalUrl();
     } else {
         global $wgServer;
         $this->properties['og:image'] = $wgServer . $file->iconThumb()->url;
     }
     // og:description
     // TODO: This crashes MediaWiki because messages cannot be loaded or some bullshit
     // The problem is that message decoding calls MessageCache::parse(), which calls
     // message decoding, which again calls MessageCache::parse(). To provide reentrancy,
     // MessageCache::parse() violates its signature by returning a string instead of an
     // object. You dirty little bastard, you.
     //$this->properties['og:description'] = $file->getLongDesc();
     parent::__construct();
 }
Example #16
0
 /**
  * Fetch additional information that is related to the saving that has just happened,
  * e.g. regarding the last edit date. In runs where this hook is not triggered, the
  * last DB entry (of MW) will be used to fill such properties.
  *
  * @note This method directly accesses a member of Article that is informally declared to
  * be private. However, there is no way to otherwise access an article's parseroutput for
  * the purpose of adding information there. If the private access ever becomes a problem,
  * a global/static variable appears to be the only way to get more article data to
  * LinksUpdate.
  *
  * @param WikiPage|Article $article WikiPage on 1.19 and later
  * @param Revision $rev
  * @param integer $baseID
  * @param User $user
  *
  * @return true
  */
 public static function onNewRevisionFromEditComplete($article, Revision $rev, $baseID, User $user)
 {
     global $smwgPageSpecialProperties;
     if ($article->mPreparedEdit && $article->mPreparedEdit->output instanceof ParserOutput) {
         $semdata = self::getSMWDataFromParserOutput($article->mPreparedEdit->output, $article->getTitle());
     } else {
         // give up, just keep the old data
         return true;
     }
     if (in_array('_MDAT', $smwgPageSpecialProperties)) {
         $timestamp = $article->getTimestamp();
         $di = self::getDataItemFromMWTimestamp($timestamp);
         if (!is_null($di)) {
             $semdata->addPropertyObjectValue(new SMWDIProperty('_MDAT'), $di);
         }
     }
     if (in_array('_LEDT', $smwgPageSpecialProperties)) {
         $di = SMWDIWikiPage::newFromTitle($user->getUserPage());
         if (!is_null($di)) {
             $semdata->addPropertyObjectValue(new SMWDIProperty('_LEDT'), $di);
         }
     }
     if (in_array('_NEWP', $smwgPageSpecialProperties)) {
         $semdata->addPropertyObjectValue(new SMWDIProperty('_NEWP'), new SMWDIBoolean(is_null($rev->getParentId())));
     }
     return true;
 }
Example #17
0
 function rcDoOutputFeed(&$feed, $type, $id, $limit)
 {
     wfProfileIn(__METHOD__);
     $feed->outHeader();
     if ($type == "nid") {
         $dbr = wfGetDB(DB_SLAVE);
         $showall = $dbr->selectField('smw_nm_query', 'show_all', array('notify_id' => $id), 'NotifyMeRSS');
         if ($showall) {
             $query = $dbr->selectField('smw_nm_query', 'query', array('notify_id' => $id), 'NotifyMeRSS');
             SMWQueryProcessor::processFunctionParams(SMWNotifyProcessor::getQueryRawParams($query), $querystring, $params, $printouts);
             $query = SMWQueryProcessor::createQuery($querystring, $params, SMWQueryProcessor::INLINE_QUERY, 'auto', $printouts);
             $res = smwfGetStore()->getQueryResult($query);
             $items = array();
             $labels = array();
             foreach ($res->getPrintRequests() as $pr) {
                 $labels[] = $pr->getText(SMW_OUTPUT_WIKI);
             }
             $row = $res->getNext();
             $linker = new Linker();
             while ($row !== false) {
                 $wikipage = $row[0]->getNextObject();
                 // get the object
                 $a = new Article($wikipage->getTitle());
                 $description = "<table style=\"width: 60em; font-size: 90%; border: 1px solid #aaaaaa; background-color: #f9f9f9; color: black; margin-bottom: 0.5em; margin-left: 1em; padding: 0.2em; clear: right; text-align:left;\"><tr><th style=\"text-align: center; background-color:#ccccff;\" colspan=\"2\"><big>" . $wikipage->getText() . "</big></th></tr>";
                 $idx = 0;
                 foreach ($row as $field) {
                     $description .= "<tr><td>" . $labels[$idx] . "</td><td>";
                     $first_value = true;
                     while (($object = $field->getNextObject()) !== false) {
                         if ($first_value) {
                             $first_value = false;
                         } else {
                             $description .= ', ';
                         }
                         $description .= $object->getShortText(SMW_OUTPUT_HTML, $linker);
                     }
                     $description .= "</td></tr>";
                     $idx++;
                 }
                 $description .= "</table>";
                 $items[] = array('title' => $wikipage->getText(), 'notify' => $description, 'timestamp' => $a->getTimestamp());
                 $row = $res->getNext();
             }
         } else {
             $items = NMStorage::getDatabase()->getNotifyRSS($type, $id, $limit);
         }
     } else {
         $items = NMStorage::getDatabase()->getNotifyRSS($type, $id, $limit);
     }
     foreach ($items as $i) {
         if (isset($i['link']) && $i['link']) {
             $item = new FeedItem($i['title'], $i['notify'], $i['link'], $i['timestamp']);
         } else {
             $title = Title::makeTitle(NS_MAIN, $i['title']);
             $talkpage = $title->getTalkPage();
             $item = new FeedItem($title->getPrefixedText(), $i['notify'], $title->getFullURL(), $i['timestamp'], "", $talkpage->getFullURL());
         }
         $feed->outItem($item);
     }
     $feed->outFooter();
     wfProfileOut(__METHOD__);
 }
Example #18
0
 /**
  * @return bool
  */
 protected function showHeader()
 {
     global $wgOut, $wgUser, $wgMaxArticleSize, $wgLang;
     global $wgAllowUserCss, $wgAllowUserJs;
     if ($this->mTitle->isTalkPage()) {
         $wgOut->addWikiMsg('talkpagetext');
     }
     // Add edit notices
     $wgOut->addHTML(implode("\n", $this->mTitle->getEditNotices($this->oldid)));
     if ($this->isConflict) {
         $wgOut->wrapWikiMsg("<div class='mw-explainconflict'>\n\$1\n</div>", 'explainconflict');
         $this->edittime = $this->mArticle->getTimestamp();
     } else {
         if ($this->section != '' && !$this->isSectionEditSupported()) {
             // We use $this->section to much before this and getVal('wgSection') directly in other places
             // at this point we can't reset $this->section to '' to fallback to non-section editing.
             // Someone is welcome to try refactoring though
             $wgOut->showErrorPage('sectioneditnotsupported-title', 'sectioneditnotsupported-text');
             return false;
         }
         if ($this->section != '' && $this->section != 'new') {
             if (!$this->summary && !$this->preview && !$this->diff) {
                 $sectionTitle = self::extractSectionTitle($this->textbox1);
                 //FIXME: use Content object
                 if ($sectionTitle !== false) {
                     $this->summary = "/* {$sectionTitle} */ ";
                 }
             }
         }
         if ($this->missingComment) {
             $wgOut->wrapWikiMsg("<div id='mw-missingcommenttext'>\n\$1\n</div>", 'missingcommenttext');
         }
         if ($this->missingSummary && $this->section != 'new') {
             $wgOut->wrapWikiMsg("<div id='mw-missingsummary'>\n\$1\n</div>", 'missingsummary');
         }
         if ($this->missingSummary && $this->section == 'new') {
             $wgOut->wrapWikiMsg("<div id='mw-missingcommentheader'>\n\$1\n</div>", 'missingcommentheader');
         }
         if ($this->blankArticle) {
             $wgOut->wrapWikiMsg("<div id='mw-blankarticle'>\n\$1\n</div>", 'blankarticle');
         }
         if ($this->hookError !== '') {
             $wgOut->addWikiText($this->hookError);
         }
         if (!$this->checkUnicodeCompliantBrowser()) {
             $wgOut->addWikiMsg('nonunicodebrowser');
         }
         if ($this->section != 'new') {
             $revision = $this->mArticle->getRevisionFetched();
             if ($revision) {
                 // Let sysop know that this will make private content public if saved
                 if (!$revision->userCan(Revision::DELETED_TEXT, $wgUser)) {
                     $wgOut->wrapWikiMsg("<div class='mw-warning plainlinks'>\n\$1\n</div>\n", 'rev-deleted-text-permission');
                 } elseif ($revision->isDeleted(Revision::DELETED_TEXT)) {
                     $wgOut->wrapWikiMsg("<div class='mw-warning plainlinks'>\n\$1\n</div>\n", 'rev-deleted-text-view');
                 }
                 if (!$revision->isCurrent()) {
                     $this->mArticle->setOldSubtitle($revision->getId());
                     $wgOut->addWikiMsg('editingold');
                 }
             } elseif ($this->mTitle->exists()) {
                 // Something went wrong
                 $wgOut->wrapWikiMsg("<div class='errorbox'>\n\$1\n</div>\n", array('missing-revision', $this->oldid));
             }
         }
     }
     if (wfReadOnly()) {
         $wgOut->wrapWikiMsg("<div id=\"mw-read-only-warning\">\n\$1\n</div>", array('readonlywarning', wfReadOnlyReason()));
     } elseif ($wgUser->isAnon()) {
         if ($this->formtype != 'preview') {
             $wgOut->wrapWikiMsg("<div id='mw-anon-edit-warning'>\n\$1\n</div>", array('anoneditwarning', '{{fullurl:Special:UserLogin|returnto={{FULLPAGENAMEE}}}}', '{{fullurl:Special:UserLogin/signup|returnto={{FULLPAGENAMEE}}}}'));
         } else {
             $wgOut->wrapWikiMsg("<div id=\"mw-anon-preview-warning\">\n\$1</div>", 'anonpreviewwarning');
         }
     } else {
         if ($this->isCssJsSubpage) {
             # Check the skin exists
             if ($this->isWrongCaseCssJsPage) {
                 $wgOut->wrapWikiMsg("<div class='error' id='mw-userinvalidcssjstitle'>\n\$1\n</div>", array('userinvalidcssjstitle', $this->mTitle->getSkinFromCssJsSubpage()));
             }
             if ($this->formtype !== 'preview') {
                 if ($this->isCssSubpage && $wgAllowUserCss) {
                     $wgOut->wrapWikiMsg("<div id='mw-usercssyoucanpreview'>\n\$1\n</div>", array('usercssyoucanpreview'));
                 }
                 if ($this->isJsSubpage && $wgAllowUserJs) {
                     $wgOut->wrapWikiMsg("<div id='mw-userjsyoucanpreview'>\n\$1\n</div>", array('userjsyoucanpreview'));
                 }
             }
         }
     }
     if ($this->mTitle->isProtected('edit') && MWNamespace::getRestrictionLevels($this->mTitle->getNamespace()) !== array('')) {
         # Is the title semi-protected?
         if ($this->mTitle->isSemiProtected()) {
             $noticeMsg = 'semiprotectedpagewarning';
         } else {
             # Then it must be protected based on static groups (regular)
             $noticeMsg = 'protectedpagewarning';
         }
         LogEventsList::showLogExtract($wgOut, 'protect', $this->mTitle, '', array('lim' => 1, 'msgKey' => array($noticeMsg)));
     }
     if ($this->mTitle->isCascadeProtected()) {
         # Is this page under cascading protection from some source pages?
         list($cascadeSources, ) = $this->mTitle->getCascadeProtectionSources();
         $notice = "<div class='mw-cascadeprotectedwarning'>\n\$1\n";
         $cascadeSourcesCount = count($cascadeSources);
         if ($cascadeSourcesCount > 0) {
             # Explain, and list the titles responsible
             foreach ($cascadeSources as $page) {
                 $notice .= '* [[:' . $page->getPrefixedText() . "]]\n";
             }
         }
         $notice .= '</div>';
         $wgOut->wrapWikiMsg($notice, array('cascadeprotectedwarning', $cascadeSourcesCount));
     }
     if (!$this->mTitle->exists() && $this->mTitle->getRestrictions('create')) {
         LogEventsList::showLogExtract($wgOut, 'protect', $this->mTitle, '', array('lim' => 1, 'showIfEmpty' => false, 'msgKey' => array('titleprotectedwarning'), 'wrap' => "<div class=\"mw-titleprotectedwarning\">\n\$1</div>"));
     }
     if ($this->kblength === false) {
         $this->kblength = (int) (strlen($this->textbox1) / 1024);
     }
     if ($this->tooBig || $this->kblength > $wgMaxArticleSize) {
         $wgOut->wrapWikiMsg("<div class='error' id='mw-edit-longpageerror'>\n\$1\n</div>", array('longpageerror', $wgLang->formatNum($this->kblength), $wgLang->formatNum($wgMaxArticleSize)));
     } else {
         if (!wfMessage('longpage-hint')->isDisabled()) {
             $wgOut->wrapWikiMsg("<div id='mw-edit-longpage-hint'>\n\$1\n</div>", array('longpage-hint', $wgLang->formatSize(strlen($this->textbox1)), strlen($this->textbox1)));
         }
     }
     # Add header copyright warning
     $this->showHeaderCopyrightWarning();
     return true;
 }
 /**
  * AJAX helper called from view mode to save gallery data
  * @author Marooned
  */
 public static function saveGalleryDataByHash($hash, $wikitext, $starttime)
 {
     global $wgTitle, $wgUser;
     wfProfileIn(__METHOD__);
     wfDebug(__METHOD__ . ": {$wikitext}\n");
     $result = array();
     // save changed gallery
     $rev = Revision::newFromTitle($wgTitle);
     // try to fix fatal (article has been removed since user opened the page)
     if (empty($rev)) {
         $result['info'] = 'conflict';
         wfDebug(__METHOD__ . ": revision is empty\n");
         wfProfileOut(__METHOD__);
         return $result;
     }
     $articleWikitext = $rev->getText();
     $gallery = '';
     preg_match_all('%<gallery([^>]*)>(.*?)</gallery>%s', $articleWikitext, $matches, PREG_PATTERN_ORDER);
     for ($i = 0; $i < count($matches[0]); $i++) {
         $attribs = Sanitizer::decodeTagAttributes($matches[1][$i]);
         //count hash from attribs and content
         if (md5($matches[2][$i] . implode('', $attribs)) == $hash) {
             $gallery = $matches[0][$i];
             break;
         }
     }
     if (empty($gallery)) {
         $result['info'] = 'conflict';
         wfDebug(__METHOD__ . ": conflict found\n");
     } else {
         $articleWikitext = str_replace($gallery, $wikitext, $articleWikitext);
         //saving
         if ($wgTitle->userCan('edit') && !$wgUser->isBlocked()) {
             $result = null;
             $article = new Article($wgTitle);
             $editPage = new EditPage($article);
             $editPage->edittime = $article->getTimestamp();
             $editPage->starttime = $starttime;
             $editPage->textbox1 = $articleWikitext;
             $editPage->summary = wfMsgForContent('wikiaPhotoGallery-edit-summary');
             // watch all my edits / preserve watchlist (RT #59138)
             if ($wgUser->getOption('watchdefault')) {
                 $editPage->watchthis = true;
             } else {
                 $editPage->watchthis = $editPage->mTitle->userIsWatching();
             }
             $bot = $wgUser->isAllowed('bot');
             $status = $editPage->internalAttemptSave($result, $bot);
             $retval = $status->value;
             Wikia::log(__METHOD__, "editpage", "Returned value {$retval}");
             switch ($retval) {
                 case EditPage::AS_SUCCESS_UPDATE:
                 case EditPage::AS_SUCCESS_NEW_ARTICLE:
                     $wgTitle->invalidateCache();
                     Article::onArticleEdit($wgTitle);
                     $result['info'] = 'ok';
                     break;
                 case EditPage::AS_SPAM_ERROR:
                     $result['error'] = wfMsg('spamprotectiontext') . '<p>( Call #4 )</p>';
                     break;
                 default:
                     $result['error'] = wfMsg('wikiaPhotoGallery-edit-abort');
             }
         } else {
             $result['error'] = wfMsg('wikiaPhotoGallery-error-user-rights');
         }
         if (isset($result['error'])) {
             $result['errorCaption'] = wfMsg('wikiaPhotoGallery-error-caption');
         }
         //end of saving
         wfDebug(__METHOD__ . ": saving from view mode done\n");
         // commit (RT #48304)
         $dbw = wfGetDB(DB_MASTER);
         $dbw->commit();
     }
     wfProfileOut(__METHOD__);
     return $result;
 }
Example #20
0
 static function renderAutoEdit(&$parser)
 {
     // set defaults
     $formcontent = '';
     $linkString = null;
     $linkType = 'span';
     $summary = null;
     $classString = 'autoedit-trigger';
     $inQueryArr = array();
     $editTime = null;
     // parse parameters
     $params = func_get_args();
     array_shift($params);
     // don't need the parser
     foreach ($params as $param) {
         $elements = explode('=', $param, 2);
         $key = trim($elements[0]);
         $value = count($elements) > 1 ? trim($elements[1]) : '';
         switch ($key) {
             case 'link text':
                 $linkString = $parser->recursiveTagParse($value);
                 break;
             case 'link type':
                 $linkType = $parser->recursiveTagParse($value);
                 break;
             case 'reload':
                 $classString .= ' reload';
                 break;
             case 'summary':
                 $summary = $parser->recursiveTagParse($value);
                 break;
             case 'query string':
                 // Change HTML-encoded ampersands directly to
                 // URL-encoded ampersands, so that the string
                 // doesn't get split up on the '&'.
                 $inQueryStr = str_replace('&amp;', '%26', $value);
                 parse_str($inQueryStr, $arr);
                 $inQueryArr = SFUtils::array_merge_recursive_distinct($inQueryArr, $arr);
                 break;
             case 'ok text':
             case 'error text':
                 // do not parse ok text or error text yet. Will be parsed on api call
                 $arr = array($key => $value);
                 $inQueryArr = SFUtils::array_merge_recursive_distinct($inQueryArr, $arr);
                 break;
             case 'target':
             case 'title':
                 $value = $parser->recursiveTagParse($value);
                 $arr = array($key => $value);
                 $inQueryArr = SFUtils::array_merge_recursive_distinct($inQueryArr, $arr);
                 $targetTitle = Title::newFromText($value);
                 if ($targetTitle !== null) {
                     $targetArticle = new Article($targetTitle);
                     $targetArticle->clear();
                     $editTime = $targetArticle->getTimestamp();
                 }
             default:
                 $value = $parser->recursiveTagParse($value);
                 $arr = array($key => $value);
                 $inQueryArr = SFUtils::array_merge_recursive_distinct($inQueryArr, $arr);
         }
     }
     // query string has to be turned into hidden inputs.
     if (!empty($inQueryArr)) {
         $query_components = explode('&', http_build_query($inQueryArr, '', '&'));
         foreach ($query_components as $query_component) {
             $var_and_val = explode('=', $query_component, 2);
             if (count($var_and_val) == 2) {
                 $formcontent .= Html::hidden(urldecode($var_and_val[0]), urldecode($var_and_val[1]));
             }
         }
     }
     if ($linkString == null) {
         return null;
     }
     if ($linkType == 'button') {
         // Html::rawElement() before MW 1.21 or so drops the type attribute
         // do not use Html::rawElement() for buttons!
         $linkElement = '<button ' . Html::expandAttributes(array('type' => 'submit', 'class' => $classString)) . '>' . $linkString . '</button>';
     } elseif ($linkType == 'link') {
         $linkElement = Html::rawElement('a', array('class' => $classString, 'href' => "#"), $linkString);
     } else {
         $linkElement = Html::rawElement('span', array('class' => $classString), $linkString);
     }
     if ($summary == null) {
         $summary = wfMessage('sf_autoedit_summary', "[[{$parser->getTitle()}]]")->text();
     }
     $formcontent .= Html::hidden('wpSummary', $summary);
     if ($editTime !== null) {
         $formcontent .= Html::hidden('wpEdittime', $editTime);
     }
     $form = Html::rawElement('form', array('class' => 'autoedit-data'), $formcontent);
     // ensure loading of jQuery and style sheets
     self::loadScriptsForAutoEdit($parser);
     $output = Html::rawElement('div', array('class' => 'autoedit'), $linkElement . Html::rawElement('span', array('class' => "autoedit-result"), null) . $form);
     // return output HTML
     return $parser->insertStripItem($output, $parser->mStripState);
 }
Example #21
0
 /**
  * Returns the iCal for a single item.
  * 
  * @since 1.5.2
  * 
  * @param array $row
  * 
  * @return string
  */
 protected function getIcalForItem(array $row)
 {
     $result = '';
     $wikipage = $row[0]->getResultSubject();
     // get the object
     $wikipage = SMWDataValueFactory::newDataItemValue($wikipage, null);
     $params = array('summary' => $wikipage->getShortWikiText());
     foreach ($row as $field) {
         // later we may add more things like a generic
         // mechanism to add whatever you want :)
         // could include funny things like geo, description etc. though
         $req = $field->getPrintRequest();
         $label = strtolower($req->getLabel());
         switch ($label) {
             case 'start':
             case 'end':
                 if ($req->getTypeID() == '_dat') {
                     $dataValue = $field->getNextDataValue();
                     if ($dataValue === false) {
                         unset($params[$label]);
                     } else {
                         $params[$label] = $dataValue;
                     }
                 }
                 break;
             case 'location':
             case 'description':
             case 'summary':
                 $value = $field->getNextDataValue();
                 if ($value !== false) {
                     $params[$label] = $value->getShortWikiText();
                 }
                 break;
         }
     }
     $title = $wikipage->getTitle();
     $article = new Article($title);
     $url = $title->getFullURL();
     $result .= "BEGIN:VEVENT\r\n";
     $result .= "SUMMARY:" . $params['summary'] . "\r\n";
     $result .= "URL:{$url}\r\n";
     $result .= "UID:{$url}\r\n";
     if (array_key_exists('start', $params)) {
         $result .= "DTSTART:" . $this->parsedate($params['start']) . "\r\n";
     }
     if (array_key_exists('end', $params)) {
         $result .= "DTEND:" . $this->parsedate($params['end'], true) . "\r\n";
     }
     if (array_key_exists('location', $params)) {
         $result .= "LOCATION:" . $params['location'] . "\r\n";
     }
     if (array_key_exists('description', $params)) {
         $result .= "DESCRIPTION:" . $params['description'] . "\r\n";
     }
     $t = strtotime(str_replace('T', ' ', $article->getTimestamp()));
     $result .= "DTSTAMP:" . date("Ymd", $t) . "T" . date("His", $t) . "\r\n";
     $result .= "SEQUENCE:" . $title->getLatestRevID() . "\r\n";
     $result .= "END:VEVENT\r\n";
     return $result;
 }
 public function execute($par)
 {
     global $wgUser, $wgRequest, $wgOut, $wgCommentboxNamespaces;
     if (!$wgRequest->wasPosted()) {
         $wgOut->redirect(Title::newMainPage()->getFullURL());
         return;
     }
     $this->setHeaders();
     $Pagename = $wgRequest->getText('wpPageName');
     $Author = $wgRequest->getText('wpAuthor', '');
     $Comment = $wgRequest->getText('wpComment', '');
     $title = Title::newFromText($Pagename);
     if ($title == NULL || !$title->exists()) {
         $this->fail('commentbox-error-page-nonexistent');
         return;
     }
     if (!array_key_exists($title->getNamespace(), $wgCommentboxNamespaces) || !$wgCommentboxNamespaces[$title->getNamespace()]) {
         $this->fail('commentbox-error-namespace', $title);
         return;
     }
     if ($Comment == '' || $Comment == wfMsgNoTrans('commentbox-prefill')) {
         $this->fail('commentbox-error-empty-comment', $title);
         return;
     }
     if (!$title->userCan('edit')) {
         $this->displayRestrictionError();
         return;
     }
     // TODO: Integrate with SpamBlacklist etc.
     // Currently, no http/https-links are allowed at all
     $matches = array();
     if (preg_match('@https?://[-.\\w]+@', $Comment, $matches) || preg_match('@https?://[-.\\w]+@', $Author, $matches)) {
         $wgOut->setPageTitle(wfMsg('spamprotectiontitle'));
         $wgOut->setRobotPolicy('noindex,nofollow');
         $wgOut->setArticleRelated(false);
         $wgOut->addWikiMsg('spamprotectiontext');
         $wgOut->addWikiMsg('spamprotectionmatch', "<nowiki>{$matches[0]}</nowiki>");
         $wgOut->returnToMain(false, $title);
         return;
     }
     $article = new Article($title);
     $text = $article->getContent();
     $subject = '';
     if (!preg_match(wfMsgForContentNoTrans('commentbox-regex'), $text)) {
         $subject = wfMsgForContent('commentbox-first-comment-heading') . "\n";
     }
     $sig = $wgUser->isLoggedIn() ? "-- ~~~~" : "-- {$Author} ~~~~~";
     // Append <br /> after each newline, except if the user started a new paragraph
     $Comment = preg_replace('/(?<!\\n)\\n(?!\\n)/', "<br />\n", $Comment);
     $text .= "\n\n" . $subject . $Comment . "\n<br />" . $sig;
     $reqArr = array('wpTextbox1' => $text, 'wpSummary' => wfMsgForContent('commentbox-log'), 'wpEditToken' => $wgUser->editToken(), 'wpIgnoreBlankSummary' => '', 'wpStarttime' => wfTimestampNow(), 'wpEdittime' => $article->getTimestamp());
     $request = new FauxRequest($reqArr, true);
     $ep = new EditPage($article);
     $ep->setContextTitle($title);
     $ep->importFormData($request);
     $details = array();
     // Passed by ref
     $status = $ep->internalAttemptSave($details);
     $retval = $status->value;
     switch ($retval) {
         case EditPage::AS_SUCCESS_UPDATE:
             $wgOut->redirect($title->getFullURL());
             break;
         case EditPage::AS_SPAM_ERROR:
             $ep->spamPageWithContent($details['spam']);
             break;
         case EditPage::AS_BLOCKED_PAGE_FOR_USER:
             $wgOut->blockedPage();
             break;
         case EditPage::AS_READ_ONLY_PAGE_ANON:
         case EditPage::AS_READ_ONLY_PAGE_LOGGED:
             $wgOut->permissionRequired('edit');
             break;
         case EditPage::AS_READ_ONLY_PAGE:
             $wgOut->readOnlyPage();
     }
 }
Example #23
0
 /**
  * Fetch additional information that is related to the saving that has just happened,
  * e.g. regarding the last edit date. In runs where this hook is not triggered, the
  * last DB entry (of MW) will be used to fill such properties.
  *
  * @note This method directly accesses a member of Article that is informally declared to
  * be private. However, there is no way to otherwise access an article's parseroutput for
  * the purpose of adding information there. If the private access ever becomes a problem,
  * a global/static variable appears to be the only way to get more article data to
  * LinksUpdate.
  *
  * @param WikiPage|Article $article WikiPage on 1.19 and later
  * @param Revision $rev
  * @param integer $baseID
  * @param User $user
  *
  * @return true
  */
 public static function onNewRevisionFromEditComplete($article, Revision $rev, $baseID, User $user)
 {
     global $smwgPageSpecialProperties;
     if ($article->mPreparedEdit && $article->mPreparedEdit->output instanceof ParserOutput) {
         $output = $article->mPreparedEdit->output;
         $title = $article->getTitle();
         if (!isset($title)) {
             return true;
             // nothing we can do
         }
         if (!isset($output->mSMWData)) {
             // no data container yet, make one
             $output->mSMWData = new SMWSemanticData(new SMWDIWikiPage($title->getDBkey(), $title->getNamespace(), $title->getInterwiki()));
         }
         $semdata = $output->mSMWData;
     } else {
         // give up, just keep the old data
         return true;
     }
     if (in_array('_MDAT', $smwgPageSpecialProperties)) {
         $timestamp = $article->getTimestamp();
         $di = self::getDataItemFromMWTimestamp($timestamp);
         if (!is_null($di)) {
             $semdata->addPropertyObjectValue(new SMWDIProperty('_MDAT'), $di);
         }
     }
     if (in_array('_LEDT', $smwgPageSpecialProperties)) {
         $di = SMWDIWikiPage::newFromTitle($user->getUserPage());
         if (!is_null($di)) {
             $semdata->addPropertyObjectValue(new SMWDIProperty('_LEDT'), $di);
         }
     }
     if (in_array('_NEWP', $smwgPageSpecialProperties)) {
         $semdata->addPropertyObjectValue(new SMWDIProperty('_NEWP'), new SMWDIBoolean(is_null($rev->getParentId())));
     }
     return true;
 }
 function execute($par)
 {
     global $wgOut, $wgRequest, $wgParser, $wgUser, $wgFilterCallback, $wgCookiePath, $wgCookieDomain, $wgCookieSecure;
     $wgOut->disable();
     // build the article which we are about to save
     $t = Title::newFromUrl($wgRequest->getVal('target'));
     $a = new Article($t);
     $action = $wgRequest->getVal('eaction');
     wfDebug("Html5Editor::execute called with {$action}\n");
     // process the edit update
     if ($action == 'get-vars') {
         $wgOut->disable();
         $response = array('edittoken' => $wgUser->editToken(), 'edittime' => $a->getTimestamp(true), 'drafttoken' => wfGenerateToken(), 'olddraftid' => 0);
         // do they already have a draft saved?
         $drafts = Draft::getDrafts($t, $wgUser->getID());
         if ($drafts) {
             // do we only select an html5 draft? probably not.
             // for loop here in  case we want to display multiple drafts of same article
             $response['olddraftid'] = $drafts[0]->getID();
         }
         print json_encode($response);
         return;
     } else {
         if ($action == 'load-draft') {
             $draftid = $wgRequest->getVal('draftid');
             $draft = new Draft($draftid);
             if (!$draft->exists()) {
                 wfLoadExtensionMessages("Html5editor");
                 $response = array('error' => wfMsg('h5e-draft-does-not-exist', $draftid), 'html' => '');
                 wfDebug("DRAFT: {$draftid} does not exist \n");
             } else {
                 $text = $draft->getText();
                 $html = $this->parse($t, $a, $text);
                 $response = array(error => '', 'html' => $html);
             }
             print json_encode($response);
             return;
         } else {
             if ($action == 'save-draft') {
                 $token = $wgRequest->getVal('edittoken');
                 if ($wgUser->matchEditToken($token)) {
                     wfDebug("Html5Editor::execute save-draft edit token ok!\n");
                     $oldtext = $a->getContent();
                     $html = $wgRequest->getVal('html');
                     $newtext = $this->convertHTML2Wikitext($html, $oldtext);
                     $draftid = $wgRequest->getVal('draftid', null);
                     $draft = null;
                     // 'null' apparently is what javascript is giving us. doh.
                     if (!$draftid || preg_match("@[^0-9]@", $draftid)) {
                         wfDebug("Html5Editor::execute getting draft id from title \n");
                         $draftid = self::getDraftIDFromTitle($t);
                     }
                     if (!$draftid || $draftid == 'null') {
                         $draft = new Draft();
                     } else {
                         $draft = Draft::newFromID($draftid);
                     }
                     wfDebug("Html5Editor::execute got draft id {$draftid} \n");
                     $draft->setTitle($t);
                     //$draft->setStartTime( $wgRequest->getText( 'wpStarttime' ) );
                     $draft->setEditTime($wgRequest->getText('edittime'));
                     $draft->setSaveTime(wfTimestampNow());
                     $draft->setText($newtext);
                     $draft->setSummary($wgRequest->getText('editsummary'));
                     $draft->setHtml5(true);
                     //$draft->setMinorEdit( $wgRequest->getInt( 'wpMinoredit', 0 ) );
                     // Save draft
                     $draft->save();
                     wfDebug("Html5Editor::execute saved draft with id {$draft->getID()} and text {$newtext} \n");
                     $response = array('draftid' => $draft->getID());
                     print json_encode($response);
                     return;
                 } else {
                     wfDebug("Html5Editor::execute save-draft edit token BAD {$token} \n");
                     $response = array('error' => 'edit token bad');
                     print json_encode($response);
                     return;
                 }
                 return;
             } else {
                 if ($action == 'save-summary') {
                     // this implementation could have a few problems
                     // 1. if a user is editing the article in separate windows, it will
                     //		only update the last edit
                     // 2. Could be easy to fake an edit summary save, but is limited to
                     // edits made by the user
                     /// 3. There's no real 'paper' trail of the saved summary
                     // grab the cookie with the rev_id
                     global $wgCookiePrefix;
                     if (isset($_COOKIE["{$wgCookiePrefix}RevId" . $t->getArticleID()])) {
                         $revid = $_COOKIE["{$wgCookiePrefix}RevId" . $t->getArticleID()];
                         wfDebug("AXX: updating revcomment {$revid} \n");
                         $dbw = wfGetDB(DB_MASTER);
                         $summary = "updating from html5 editor, " . $wgRequest->getVal('summary');
                         $dbw->update('revision', array('rev_comment' => $summary), array('rev_id' => $revid, 'rev_user_text' => $wgUser->getName()), "Html5Editor::saveComment", array("LIMIT" => 1));
                         $dbw->update('recentchanges', array('rc_comment' => $summary), array('rc_this_oldid' => $revid, 'rc_user_text' => $wgUser->getName()), "Html5Editor::saveComment", array("LIMIT" => 1));
                     } else {
                         wfDebug("AXX: NOT updating revcomment, why\n");
                     }
                     return;
                 } else {
                     if ($action == 'publish-html') {
                         // check the edit token
                         $token = $wgRequest->getVal('edittoken');
                         if (!$wgUser->matchEditToken($token)) {
                             $response = array('error' => wfMsg('sessionfailure'));
                             print json_encode($response);
                             return;
                         }
                         // check the edit time and check for a conflict
                         $edittime = $wgRequest->getVal('edittime');
                         if (!preg_match('/^\\d{14}$/', $edittime)) {
                             $edittime = null;
                         }
                         if (!$edittime) {
                             $response = array('error' => 'missing or invalid edit time');
                             print json_encode($response);
                             return;
                         }
                         if ($response = $this->getPermissionErrors($t)) {
                             print json_encode($response);
                             return;
                         }
                         $newArticle = !$t->exists();
                         $a = new Article($t);
                         // check for edit conflict
                         //	if( $this->mArticle->getTimestamp() != $this->edittime ) {
                         //   $this->isConflict = true;
                         //	}
                         // now ... let's convert the HTML back into wikitext... holy crap, we are nuts
                         $oldtext = $a->getContent();
                         $html = $wgRequest->getVal('html');
                         $newtext = $this->convertHTML2Wikitext($html, $oldtext);
                         // filter callback?
                         if ($wgFilterCallback && $wgFilterCallback($t, $newtext, null)) {
                             # Error messages or other handling should be performed by the filter function
                             $response = array('error' => self::$spam_message, 'html' => $html);
                             print json_encode($response);
                             return;
                         }
                         // do the save
                         // TODO: check for conflicts (obviously)
                         if ($a->doEdit($newtext, $wgRequest->getVal('summary') . " (HTML5) ")) {
                             //$alerts = new MailAddress("*****@*****.**");
                             //UserMailer::send($alerts, $alerts, "HTML5 Ouput for {$t->getText()}", "{$t->getFullURL()}?action=history \n HTML: " . trim($html) . "\n\nwikitext:\n $newtext\n\n\nUser: "******"\n\n\n\nPOST: " . print_r($_POST, true) );
                             $r = Revision::newFromTitle($t);
                             $this->setRevCookie($t, $r);
                             #$html = WikihowArticleHTML::postProcess($wgOut->parse($newtext));
                             $html = $this->parse($t, $a, $newtext);
                             // Create an anon attribution cookie
                             if ($newArticle && $wgUser->getId() == 0) {
                                 setcookie('aen_anon_newarticleid', $a->getId(), time() + 3600, $wgCookiePath, $wgCookieDomain, $wgCookieSecure);
                             }
                             $response = array(error => '', 'html' => $html);
                             print json_encode($response);
                             return;
                         } else {
                             $response = array(error => 'Error saving', 'html' => '');
                             print json_encode($response);
                             return;
                         }
                     }
                 }
             }
         }
     }
     return;
 }
	/**
	 * This function is the real heart of the entire Semantic Forms
	 * extension. It handles two main actions: (1) displaying a form on the
	 * screen, given a form definition and possibly page contents (if an
	 * existing page is being edited); and (2) creating actual page
	 * contents, if the form was already submitted by the user.
	 *
	 * It also does some related tasks, like figuring out the page name (if
	 * only a page formula exists).
	 */
	function formHTML( $form_def, $form_submitted, $source_is_page, $form_id = null, $existing_page_content = null, $page_name = null, $page_name_formula = null, $is_query = false, $is_embedded = false ) {
		global $wgRequest, $wgUser, $wgParser;
		global $sfgTabIndex; // used to represent the current tab index in the form
		global $sfgFieldNum; // used for setting various HTML IDs

		wfProfileIn( __METHOD__ );

		// initialize some variables
		$sfgTabIndex = 1;
		$sfgFieldNum = 1;
		$source_page_matches_this_form = false;
		$form_page_title = null;
		$generated_page_name = $page_name_formula;
		// $form_is_partial is true if:
		// (a) 'partial' == 1 in the arguments
		// (b) 'partial form' is found in the form definition
		// in the latter case, it may remain false until close to the end of
		// the parsing, so we have to assume that it will become a possibility
		$form_is_partial = false;
		$new_text = "";
		// flag for placing "<onlyinclude>" tags in form output
		$onlyinclude_free_text = false;

		// If we have existing content and we're not in an active replacement
		// situation, preserve the original content. We do this because we want
		// to pass the original content on IF this is a partial form.
		// TODO: A better approach here would be to pass the revision ID of the
		// existing page content through the replace value, which would
		// minimize the html traffic and would allow us to do a concurrent
		// update check. For now, we pass it through a hidden text field.

		if ( ! $wgRequest->getCheck( 'partial' ) ) {
			$original_page_content = $existing_page_content;
		} else {
			$original_page_content = null;
			if ( $wgRequest->getCheck( 'free_text' ) ) {
				$existing_page_content = $wgRequest->getVal( 'free_text' );
				$form_is_partial = true;
			}
		}

		// Disable all form elements if user doesn't have edit
		// permission - two different checks are needed, because
		// editing permissions can be set in different ways.
		// HACK - sometimes we don't know the page name in advance, but
		// we still need to set a title here for testing permissions.
		if ( $is_embedded ) {
			// If this is an embedded form (probably a 'RunQuery'),
			// just use the name of the actual page we're on.
			global $wgTitle;
			$this->mPageTitle = $wgTitle;
		} elseif ( $is_query ) {
			$this->mPageTitle = Title::newFromText( 'RunQuery dummy title' );
		} elseif ( $page_name === '' ) {
			$this->mPageTitle = Title::newFromText(
				$wgRequest->getVal( 'namespace' ) . ":Semantic Forms permissions test" );
		} else {
			$this->mPageTitle = Title::newFromText( $page_name );
		}

		global $wgOut;
		// show previous set of deletions for this page, if it's been deleted before
		if ( ! $form_submitted && ( $this->mPageTitle && !$this->mPageTitle->exists() ) ) {
			$this->showDeletionLog( $wgOut );
		}
		// Unfortunately, we can't just call userCan() here because, as of MW 1.16,
		// it has a bug in which it ignores a setting of
		// "$wgEmailConfirmToEdit = true;". Instead, we'll just get the
		// permission errors from the start, and use those to determine whether
		// the page is editable.
		if ( !$is_query ) {
			// $userCanEditPage = ( $wgUser->isAllowed( 'edit' ) && $this->mPageTitle->userCan( 'edit' ) );
			$permissionErrors = $this->mPageTitle->getUserPermissionsErrors( 'edit', $wgUser );
			$userCanEditPage = count( $permissionErrors ) == 0;
			wfRunHooks( 'sfUserCanEditPage', array( $this->mPageTitle, &$userCanEditPage ) );
		}
		$form_text = "";
		if ( $is_query || $userCanEditPage ) {
			$form_is_disabled = false;
			// Show "Your IP address will be recorded" warning if
			// user is anonymous, and it's not a query -
			// wiki-text for bolding has to be replaced with HTML.
			if ( $wgUser->isAnon() && ! $is_query ) {
				$anon_edit_warning = preg_replace( "/'''(.*)'''/", "<strong>$1</strong>", wfMsg( 'anoneditwarning' ) );
				$form_text .= "<p>$anon_edit_warning</p>\n";
			}
		} else {
			$form_is_disabled = true;
			$wgOut->setPageTitle( wfMsg( 'badaccess' ) );
			$wgOut->addWikiText( $wgOut->formatPermissionsErrorMessage( $permissionErrors, 'edit' ) );
			$wgOut->addHTML( "\n<hr />\n" );
		}

		$oldParser = $wgParser;

		$wgParser = unserialize( serialize( $oldParser ) ); // deep clone of parser
		$wgParser->Options( ParserOptions::newFromUser( $wgUser ) );
		$wgParser->Title( $this->mPageTitle );
		$wgParser->clearState();

		$form_def = SFFormUtils::getFormDefinition( $wgParser, $form_def, $form_id );

		// Turn form definition file into an array of sections, one for each
		// template definition (plus the first section)
		$form_def_sections = array();
		$start_position = 0;
		$section_start = 0;
		$free_text_was_included = false;
		$free_text_preload_page = null;
		$free_text_components = array();
		$all_values_for_template = array();
		// Unencode any HTML-encoded representations of curly brackets and
		// pipes - this is a hack to allow for forms to include templates
		// that themselves contain form elements - the escaping was needed
		// to make sure that those elements don't get parsed too early.
		$form_def = str_replace( array( '&#123;', '&#124;', '&#125;' ), array( '{', '|', '}' ), $form_def );
		// And another hack - replace the 'free text' standard input with
		// a field declaration to get it to be handled as a field.
		$form_def = str_replace( 'standard input|free text', 'field|<freetext>', $form_def );
		while ( $brackets_loc = strpos( $form_def, "{{{", $start_position ) ) {
			$brackets_end_loc = strpos( $form_def, "}}}", $brackets_loc );
			$bracketed_string = substr( $form_def, $brackets_loc + 3, $brackets_end_loc - ( $brackets_loc + 3 ) );
			$tag_components = SFUtils::getFormTagComponents( $bracketed_string );
			$tag_title = trim( $tag_components[0] );
			if ( $tag_title == 'for template' || $tag_title == 'end template' ) {
				// Create a section for everything up to here
				$section = substr( $form_def, $section_start, $brackets_loc - $section_start );
				$form_def_sections[] = $section;
				$section_start = $brackets_loc;
			}
			$start_position = $brackets_loc + 1;
		} // end while
		$form_def_sections[] = trim( substr( $form_def, $section_start ) );

		// Cycle through the form definition file, and possibly an
		// existing article as well, finding template and field
		// declarations and replacing them with form elements, either
		// blank or pre-populated, as appropriate.
		$all_fields = array();
		$data_text = "";
		$template_name = "";
		$allow_multiple = false;
		$instance_num = 0;
		$all_instances_printed = false;
		$strict_parsing = false;

		// Placeholder name in the form
		$curPlaceholder = null;
		// Used to store the HTML code of the multiple template, to reinsert it into the right spot
		// This array will keep track of all the replaced @<name>@ strings
		$placeholderFields = array();

		for ( $section_num = 0; $section_num < count( $form_def_sections ); $section_num++ ) {
			$start_position = 0;
			$template_text = "";
			// the append is there to ensure that the original
			// array doesn't get modified; is it necessary?
			$section = " " . $form_def_sections[$section_num];


			$multipleTemplateString = "";

			while ( $brackets_loc = strpos( $section, '{{{', $start_position ) ) {
				$brackets_end_loc = strpos( $section, "}}}", $brackets_loc );
				$bracketed_string = substr( $section, $brackets_loc + 3, $brackets_end_loc - ( $brackets_loc + 3 ) );
				$tag_components = SFUtils::getFormTagComponents( $bracketed_string );
				$tag_title = trim( $tag_components[0] );
				// =====================================================
				// for template processing
				// =====================================================
				if ( $tag_title == 'for template' ) {
					$old_template_name = $template_name;
					$template_name = trim( $tag_components[1] );
					$tif = SFTemplateInForm::create( $template_name );
					$query_template_name = str_replace( ' ', '_', $template_name );
					$add_button_text = wfMsg( 'sf_formedit_addanother' );
					// Also replace periods with underlines, since that's what
					// POST does to strings anyway.
					$query_template_name = str_replace( '.', '_', $query_template_name );
					// ...and escape apostrophes.
					$query_template_name = str_replace( "'", "\'", $query_template_name );
					// Cycle through the other components.
					for ( $i = 2; $i < count( $tag_components ); $i++ ) {
						$component = $tag_components[$i];
						if ( $component == 'multiple' ) $allow_multiple = true;
						if ( $component == 'strict' ) $strict_parsing = true;
						$sub_components = array_map( 'trim', explode( '=', $component, 2 ) );
						if ( count( $sub_components ) == 2 ) {
							if ( $sub_components[0] == 'label' ) {
								$template_label = $sub_components[1];
							} elseif ( $sub_components[0] == 'add button text' ) {
								$add_button_text = $sub_components[1];
							} elseif ( $sub_components[0] == 'embed in field' ) {
								// Placeholder on form template level. Assume that the template form def
								// will have a multiple+placeholder parameters, and get the placeholder value.
								// We expect something like TemplateName[fieldName], and convert it to the
								// TemplateName___fieldName form used internally.
								preg_match( '/\s*(.*)\[(.*)\]\s*/', $sub_components[1], $matches );
								$curPlaceholder = ( count( $matches ) > 2 ) ? self::placeholderFormat( $matches[1], $matches[2] ) : null;
								unset ( $matches );
							}
						}
					}
					// If this is the first instance, add
					// the label into the form, if there is
					// one, and add the appropriate wrapper
					// div, if this is a multiple-instance
					// template.
					if ( $old_template_name != $template_name ) {
						if ( isset( $template_label ) ) {
							$multipleTemplateString .= "<fieldset>\n";
							$multipleTemplateString .= "<legend>$template_label</legend>\n";
						}
						// If $curPlaceholder is set, it means we want to insert a
						// multiple template form's HTML into the main form's HTML.
 						// So, the HTML will be stored in $multipleTemplateString.
 						if ( $allow_multiple ) {
 							$multipleTemplateString .= "\t" . '<div class="multipleTemplateWrapper">' . "\n";
 							$multipleTemplateString .= "\t" . '<div class="multipleTemplateList">' . "\n";
 						}
					}
					if ( $curPlaceholder == null ) {
						$form_text .= $multipleTemplateString;
					}
					$template_text .= "{{" . $template_name;
					$all_fields = $tif->getAllFields();
					// remove template tag
					$section = substr_replace( $section, '', $brackets_loc, $brackets_end_loc + 3 - $brackets_loc );
					$template_instance_query_values = $wgRequest->getArray( $query_template_name );
					// If we are editing a page, and this
					// template can be found more than
					// once in that page, and multiple
					// values are allowed, repeat this
					// section.
					$existing_template_text = null;
					if ( $source_is_page || $form_is_partial ) {
						// Replace underlines with spaces in template name, to allow for
						// searching on either.
						$search_template_str = str_replace( '_', ' ', $template_name );
						$preg_match_template_str = str_replace(
							array( '/', '(', ')' ),
							array( '\/', '\(', '\)' ),
							$search_template_str );
						$found_instance = preg_match( '/{{' . $preg_match_template_str . '\s*[\|}]/i', str_replace( '_', ' ', $existing_page_content ) );
						if ( $allow_multiple ) {
							// find instances of this template in the page -
							// if there's at least one, re-parse this section of the
							// definition form for the subsequent template instances in
							// this page; if there's none, don't include fields at all.
							// there has to be a more efficient way to handle multiple
							// instances of templates, one that doesn't involve re-parsing
							// the same tags, but I don't know what it is.
							if ( $found_instance ) {
								$instance_num++;
							} else {
								$all_instances_printed = true;
							}
						}
						// get the first instance of this template on the page being edited,
						// even if there are more
						if ( $found_instance ) {
							$matches = array();
							$search_pattern = '/{{' . $preg_match_template_str . '\s*[\|}]/i';
							$content_str = str_replace( '_', ' ', $existing_page_content );
							preg_match( $search_pattern, $content_str, $matches, PREG_OFFSET_CAPTURE );
							// is this check necessary?
							if ( array_key_exists( 0, $matches ) && array_key_exists( 1, $matches[0] ) ) {
								$start_char = $matches[0][1];
								$fields_start_char = $start_char + 2 + strlen( $search_template_str );
								// Skip ahead to the first real character.
								while ( in_array( $existing_page_content[$fields_start_char], array( ' ', '\n' ) ) ) {
									$fields_start_char++;
								}
								// If the next character is a pipe, skip that too.
								if ( $existing_page_content[$fields_start_char] == '|' ) {
									$fields_start_char++;
								}
								$template_contents = array( '0' => '' );
								// Cycle through template call, splitting it up by pipes ('|'),
								// except when that pipe is part of a piped link.
								$field = "";
								$uncompleted_square_brackets = 0;
								$uncompleted_curly_brackets = 2;
								$template_ended = false;
								for ( $i = $fields_start_char; ! $template_ended && ( $i < strlen( $existing_page_content ) ); $i++ ) {
									$c = $existing_page_content[$i];
									if ( $c == '[' ) {
										$uncompleted_square_brackets++;
									} elseif ( $c == ']' && $uncompleted_square_brackets > 0 ) {
										$uncompleted_square_brackets--;
									} elseif ( $c == '{' ) {
										$uncompleted_curly_brackets++;
									} elseif ( $c == '}' && $uncompleted_curly_brackets > 0 ) {
										$uncompleted_curly_brackets--;
									}
									// handle an end to a field and/or template declaration
									$template_ended = ( $uncompleted_curly_brackets == 0 && $uncompleted_square_brackets == 0 );
									$field_ended = ( $c == '|' && $uncompleted_square_brackets == 0 && $uncompleted_curly_brackets <= 2 );
									if ( $template_ended || $field_ended ) {
										// if this was the last character in the template, remove
										// the closing curly brackets
										if ( $template_ended ) {
											$field = substr( $field, 0, - 1 );
										}
										// either there's an equals sign near the beginning or not -
										// handling is similar in either way; if there's no equals
										// sign, the index of this field becomes the key
										$sub_fields = explode( '=', $field, 2 );
										if ( count( $sub_fields ) > 1 ) {
											$template_contents[trim( $sub_fields[0] )] = trim( $sub_fields[1] );
										} else {
											$template_contents[] = trim( $sub_fields[0] );
										}
										$field = '';
									} else {
										$field .= $c;
									}
								}
								// If there are uncompleted opening brackets, the whole form will get messed up -
								// display a warning.
								// (If there are too many *closing* brackets, some template stuff will end up in
								// the "free text" field - which is bad, but it's harder for the code to detect
								// the problem - though hopefully, easier for users.)
								if ( $uncompleted_curly_brackets > 0 || $uncompleted_square_brackets > 0 ) {
									$form_text .= "\t" . '<div class="warningbox">' . wfMsg( 'sf_formedit_mismatchedbrackets', $this->mPageTitle->getFullURL( array( 'action' => 'edit' ) ) ) . "</div>\n<br clear=\"both\" />\n";
								}
								$existing_template_text = substr( $existing_page_content, $start_char, $i - $start_char );
								// now remove this template from the text being edited
								// if this is a partial form, establish a new insertion point
								if ( $existing_page_content && $form_is_partial && $wgRequest->getCheck( 'partial' ) ) {
									// if something already exists, set the new insertion point
									// to its position; otherwise just let it lie
									if ( strpos( $existing_page_content, $existing_template_text ) !== false ) {
										$existing_page_content = str_replace( '{{{insertionpoint}}}', '', $existing_page_content );
										$existing_page_content = str_replace( $existing_template_text, '{{{insertionpoint}}}', $existing_page_content );
									}
								} else {
									$existing_page_content = $this->strReplaceFirst( $existing_template_text, '', $existing_page_content );
								}
								// If this is not a multiple-instance template, and we've found
								// a match in the source page, there's a good chance that this
								// page was created with this form - note that, so we don't
								// send the user a warning
								// (multiple-instance templates have a greater chance of
								// getting repeated from one form to the next)
								// - on second thought, allow even the presence of multiple-
								// instance templates to validate that this is the correct
								// form: the problem is that some forms contain *only* mutliple-
								// instance templates.
								// if (! $allow_multiple) {
								$source_page_matches_this_form = true;
								// }
							}
						}
					}
					// If the input is from the form (meaning the user has hit one
					// of the bottom row of buttons), and we're dealing with a
					// multiple template, get the values for this instance of this
					// template, then delete them from the array, so we can get the
					// next group next time - the next() command for arrays doesn't
					// seem to work here.
					if ( ( ! $source_is_page ) && $allow_multiple && $wgRequest ) {
						$all_instances_printed = true;
						if ( $old_template_name != $template_name ) {
							$all_values_for_template = $wgRequest->getArray( $query_template_name );
						}
						if ( $all_values_for_template ) {
							$cur_key = key( $all_values_for_template );
							// skip the input coming in from the "starter" div
							// TODO: this code is probably no longer necessary
							if ( $cur_key == 'num' ) {
								unset( $all_values_for_template[$cur_key] );
								$cur_key = key( $all_values_for_template );
							}
							if ( $template_instance_query_values = current( $all_values_for_template ) ) {
								$all_instances_printed = false;
								unset( $all_values_for_template[$cur_key] );
							}
						}
					}
				// =====================================================
				// end template processing
				// =====================================================
				} elseif ( $tag_title == 'end template' ) {
					if ( $source_is_page ) {
						// Add any unhandled template fields in the page as hidden variables.
						if ( isset( $template_contents ) ) {
							$form_text .= SFFormUtils::unhandledFieldsHTML( $template_name, $template_contents );
							$template_contents = null;
						}
					}
					// Remove this tag, reset some variables, and close off form HTML tag.
					$section = substr_replace( $section, '', $brackets_loc, $brackets_end_loc + 3 - $brackets_loc );
					$template_name = null;
					if ( isset( $template_label ) && $curPlaceholder == null ) {
						$form_text .= "</fieldset>\n";
						unset ( $template_label );
					}
					$allow_multiple = false;
					$all_instances_printed = false;
					$instance_num = 0;
				// =====================================================
				// field processing
				// =====================================================
				} elseif ( $tag_title == 'field' ) {
					$field_name = trim( $tag_components[1] );
					$fullFieldName = $template_name . '[' . $field_name . ']';
					// cycle through the other components
					$is_mandatory = false;
					$is_hidden = false;
					$is_restricted = false;
					$is_uploadable = false;
					$is_list = false;
					$input_type = null;
					$field_args = array();
					$show_on_select = array();
					$default_value = null;
					$values = null;
					$possible_values = null;
					$semantic_property = null;
					$preload_page = null;
					$holds_template = false;

					for ( $i = 2; $i < count( $tag_components ); $i++ ) {

						$component = trim( $tag_components[$i] );

						if ( $component == 'mandatory' ) {
							$is_mandatory = true;
						} elseif ( $component == 'hidden' ) {
							$is_hidden = true;
						} elseif ( $component == 'restricted' ) {
							$is_restricted = ( ! $wgUser || ! $wgUser->isAllowed( 'editrestrictedfields' ) );
						} elseif ( $component == 'list' ) {
							$is_list = true;
						} elseif ( $component == 'edittools' ) { // free text only
							$free_text_components[] = 'edittools';
						}

						$sub_components = array_map( 'trim', explode( '=', $component, 2 ) );

						if ( count( $sub_components ) == 1 ) {
							// add handling for single-value params, for custom input types
							$field_args[$sub_components[0]] = true;

							if ( $component == 'holds template' ) {
								$is_hidden = true;
								$holds_template = true;
								$placeholderFields[] = self::placeholderFormat( $template_name, $field_name );
							}
						} elseif ( count( $sub_components ) == 2 ) {
							// First, set each value as its own entry in $field_args.
							$field_args[$sub_components[0]] = $sub_components[1];

							// Then, do all special handling.
							if ( $sub_components[0] == 'input type' ) {
								$input_type = $sub_components[1];
							} elseif ( $sub_components[0] == 'default' ) {
								$default_value = $wgParser->recursiveTagParse( $sub_components[1] );
							} elseif ( $sub_components[0] == 'preload' ) {
								// free text field has special handling
								if ( $field_name == 'free text' || $field_name == '<freetext>' ) {
									$free_text_preload_page = $sub_components[1];
								} else {
									$preload_page = $sub_components[1];
								}
							} elseif ( $sub_components[0] == 'show on select' ) {
								// html_entity_decode() is needed to turn '&gt;' to '>'
								$vals = explode( ';', html_entity_decode( $sub_components[1] ) );
								foreach ( $vals as $val ) {
									$val = trim( $val );
									if ( empty( $val ) )
										continue;
									$option_div_pair = explode( '=>', $val, 2 );
									if ( count( $option_div_pair ) > 1 ) {
										$option = $option_div_pair[0];
										$div_id = $option_div_pair[1];
										if ( array_key_exists( $div_id, $show_on_select ) )
											$show_on_select[$div_id][] = $option;
										else
											$show_on_select[$div_id] = array( $option );
									} else {
										$show_on_select[$val] = array();
									}
								}
							} elseif ( $sub_components[0] == 'autocomplete on property' ) {
								$property_name = $sub_components[1];
								$propValue = SMWPropertyValue::makeUserProperty( $property_name );
								if ( $propValue->getPropertyTypeID() == '_wpg' ) {
									$field_args['autocomplete field type'] = 'relation';
								} else {
									$field_args['autocomplete field type'] = 'attribute';
								}
								$field_args['autocompletion source'] = $sub_components[1];
							} elseif ( $sub_components[0] == 'autocomplete on category' ) {
								$field_args['autocomplete field type'] = 'category';
								$field_args['autocompletion source'] = $sub_components[1];
							} elseif ( $sub_components[0] == 'autocomplete on concept' ) {
								$field_args['autocomplete field type'] = 'concept';
								$field_args['autocompletion source'] = $sub_components[1];
							} elseif ( $sub_components[0] == 'autocomplete on namespace' ) {
								$field_args['autocomplete field type'] = 'namespace';
								$autocompletion_source = $sub_components[1];
								// special handling for "main" (blank) namespace
								if ( $autocompletion_source == "" )
									$autocompletion_source = "main";
								$field_args['autocompletion source'] = $autocompletion_source;
							} elseif ( $sub_components[0] == 'autocomplete from url' ) {
								$field_args['autocomplete field type'] = 'external_url';
								$field_args['autocompletion source'] = $sub_components[1];
								// 'external' autocompletion is always done remotely, i.e. via API
								$field_args['remote autocompletion'] = true;
							} elseif ( $sub_components[0] == 'values' ) {
								// Handle this one only after 'delimiter' has
								// also been set.
								$values = $sub_components[1];
							} elseif ( $sub_components[0] == 'values from property' ) {
								$propertyName = $sub_components[1];
								$possible_values = SFUtils::getAllValuesForProperty( $propertyName );
							} elseif ( $sub_components[0] == 'values from category' ) {
								$category_name = ucfirst( $sub_components[1] );
								$possible_values = SFUtils::getAllPagesForCategory( $category_name, 10 );
							} elseif ( $sub_components[0] == 'values from concept' ) {
								$possible_values = SFUtils::getAllPagesForConcept( $sub_components[1] );
							} elseif ( $sub_components[0] == 'values from namespace' ) {
								$possible_values = SFUtils::getAllPagesForNamespace( $sub_components[1] );
							} elseif ( $sub_components[0] == 'values dependent on' ) {
								global $sfgDependentFields;
								$sfgDependentFields[$sub_components[1]] = $fullFieldName;
							} elseif ( $sub_components[0] == 'property' ) {
								$semantic_property = $sub_components[1];
							} elseif ( $sub_components[0] == 'default filename' ) {
								$default_filename = str_replace( '&lt;page name&gt;', $page_name, $sub_components[1] );
								// Parse value, so default filename can include parser functions.
								$default_filename = $wgParser->recursiveTagParse( $default_filename );
								$field_args['default filename'] = $default_filename;
							} elseif ( $sub_components[0] == 'restricted' ) {
								$is_restricted = !array_intersect(
									$wgUser->getEffectiveGroups(), array_map( 'trim', explode( ',', $sub_components[1] ) )
								);
							}
						}
					} // end for
					// Backwards compatibility
					if ( $input_type == 'datetime with timezone' ) {
						$input_type = 'datetime';
						$field_args['include timezone'] = true;
					} elseif ( $input_type == 'text' || $input_type == 'textarea' ) {
						// Also for backwards compatibility,
						// in that once b/c goes away,
						// this will no longer be
						// necessary.
						$field_args['no autocomplete'] = true;
					}
					if ( $allow_multiple ) {
						$field_args['part_of_multiple'] = $allow_multiple;
					}
					if ( count( $show_on_select ) > 0 ) {
						$field_args['show on select'] = $show_on_select;
					}
					// Get the value from the request, if
					// it's there, and if it's not an array.
					$cur_value = null;
					$escaped_field_name = str_replace( "'", "\'", $field_name );
					if ( isset( $template_instance_query_values ) &&
						$template_instance_query_values != null &&
						is_array( $template_instance_query_values ) ) {
						// If the field name contains an
						// apostrophe, the array sometimes
						// has the apostrophe escaped, and
						// sometimes not. For now, just check
						// for both versions.
						// @TODO - figure this out.
						$field_query_val = null;
						if ( array_key_exists( $escaped_field_name, $template_instance_query_values ) ) {
							$field_query_val = $template_instance_query_values[$escaped_field_name];
						} elseif ( array_key_exists( $field_name, $template_instance_query_values ) ) {
							$field_query_val = $template_instance_query_values[$field_name];
						}
						if ( $form_submitted || ( ! empty( $field_query_val ) && ! is_array( $field_query_val ) ) ) {
							$cur_value = $field_query_val;
						}
					}

					if ( empty( $cur_value ) && !$form_submitted ) {
						if ( !is_null( $default_value ) ) {
							// Set to the default value specified in the form, if it's there.
							$cur_value = $default_value;
						} elseif ( $preload_page ) {
							$cur_value = SFFormUtils::getPreloadedText( $preload_page );
						}
					}

					// If the user is editing a page, and that page contains a call to
					// the template being processed, get the current field's value
					// from the template call
					if ( $source_is_page && ( ! empty( $existing_template_text ) ) ) {
						if ( isset( $template_contents[$field_name] ) ) {
							$cur_value = $template_contents[$field_name];

							// If the field is a placeholder, the contents of this template
							// parameter should be treated as elements parsed by an another
							// multiple template form.
							// By putting that at the very end of the parsed string, we'll
							// have it processed as a regular multiple template form.
							if ( $holds_template ) {
								$existing_page_content = $existing_page_content . $cur_value;
							}

							// Now remove this value
							// from $template_contents,
							// so that at the end we
							// can have a list of all
							// the fields that weren't
							// handled by the form.
							unset( $template_contents[$field_name] );
						} else {
							$cur_value = '';
						}
					}

					// Handle the free text field.
					if ( $field_name == '<freetext>' ) {
						// Add placeholders for the free text in both the form and
						// the page, using <free_text> tags - once all the free text
						// is known (at the end), it will get substituted in.
						if ( $is_hidden ) {
							$new_text = SFFormUtils::hiddenFieldHTML( 'free_text', '!free_text!' );
						} else {
							$sfgTabIndex++;
							$sfgFieldNum++;
							if ( $cur_value === '' || is_null( $cur_value )  ) {
								$default_value = '!free_text!';
							} else {
								$default_value = $cur_value;
								// If the FCKeditor extension is installed and
								// active, the default value needs to be parsed
								// for use in the editor.
								global $wgFCKEditorDir;
								if ( $wgFCKEditorDir && strpos( $existing_page_content, '__NORICHEDITOR__' ) === false ) {
									$showFCKEditor = SFFormUtils::getShowFCKEditor();
									if ( !$form_submitted && ( $showFCKEditor & RTE_VISIBLE ) ) {
										$default_value = SFFormUtils::prepareTextForFCK( $cur_value );
									}
								}
							}
							$new_text = SFTextAreaInput::getHTML( $default_value, 'free_text', false, ( $form_is_disabled || $is_restricted ), $field_args );
							if ( in_array( 'edittools', $free_text_components ) ) {
								// borrowed from EditPage::showEditTools()
								$options[] = 'parse';
								$edittools_text = wfMsgExt( 'edittools', array( 'parse' ), array( 'content' ) );

								$new_text .= <<<END
		<div class="mw-editTools">
		$edittools_text
		</div>

END;
							}
						}
						$free_text_was_included = true;
						// add a similar placeholder to the data text
						$data_text .= "!free_text!\n";
					}

					if ( $template_name === '' || $field_name == '<freetext>' ) {
						$section = substr_replace( $section, $new_text, $brackets_loc, $brackets_end_loc + 3 - $brackets_loc );
					} else {
						if ( is_array( $cur_value ) ) {
							// first, check if it's a list
							if ( array_key_exists( 'is_list', $cur_value ) &&
									$cur_value['is_list'] == true ) {
								$cur_value_in_template = "";
								if ( array_key_exists( 'delimiter', $field_args ) ) {
									$delimiter = $field_args['delimiter'];
								} else {
									$delimiter = ",";
								}
								foreach ( $cur_value as $key => $val ) {
									if ( $key !== "is_list" ) {
										if ( $cur_value_in_template != "" ) {
											$cur_value_in_template .= $delimiter . " ";
										}
										$cur_value_in_template .= $val;
									}
								}
							} else {
								// otherwise:
								// if it has 1 or 2 elements, assume it's a checkbox; if it has
								// 3 elements, assume it's a date
								// - this handling will have to get more complex if other
								// possibilities get added
								if ( count( $cur_value ) == 1 ) {
									$cur_value_in_template = SFUtils::getWordForYesOrNo( false );
								} elseif ( count( $cur_value ) == 2 ) {
									$cur_value_in_template = SFUtils::getWordForYesOrNo( true );
								// if it's 3 or greater, assume it's a date or datetime
								} elseif ( count( $cur_value ) >= 3 ) {
									$month = $cur_value['month'];
									$day = $cur_value['day'];
									if ( $day !== '' ) {
										global $wgAmericanDates;
										if ( $wgAmericanDates == false ) {
											// pad out day to always be two digits
											$day = str_pad( $day, 2, "0", STR_PAD_LEFT );
										}
									}
									$year = $cur_value['year'];
									$hour = $minute = $second = $ampm24h = $timezone = null;
									if ( isset( $cur_value['hour'] ) ) $hour = $cur_value['hour'];
									if ( isset( $cur_value['minute'] ) ) $minute = $cur_value['minute'];
									if ( isset( $cur_value['second'] ) ) $second = $cur_value['second'];
									if ( isset( $cur_value['ampm24h'] ) ) $ampm24h = $cur_value['ampm24h'];
									if ( isset( $cur_value['timezone'] ) ) $timezone = $cur_value['timezone'];
									if ( $month !== '' && $day !== '' && $year !== '' ) {
										// special handling for American dates - otherwise, just
										// the standard year/month/day (where month is a number)
										global $wgAmericanDates;
										if ( $wgAmericanDates == true ) {
											$cur_value_in_template = "$month $day, $year";
										} else {
											$cur_value_in_template = "$year/$month/$day";
										}
										// include whatever time information we have
										if ( ! is_null( $hour ) )
											$cur_value_in_template .= " " . str_pad( intval( substr( $hour, 0, 2 ) ), 2, '0', STR_PAD_LEFT ) . ":" . str_pad( intval( substr( $minute, 0, 2 ) ), 2, '0', STR_PAD_LEFT );
										if ( ! is_null( $second ) )
											$cur_value_in_template .= ":" . str_pad( intval( substr( $second, 0, 2 ) ), 2, '0', STR_PAD_LEFT );
										if ( ! is_null( $ampm24h ) )
											$cur_value_in_template .= " $ampm24h";
										if ( ! is_null( $timezone ) )
											$cur_value_in_template .= " $timezone";
									} else {
										$cur_value_in_template = "";
									}
								}
							}
						} else { // value is not an array
							$cur_value_in_template = $cur_value;
						}
						if ( $template_name == null || $template_name === '' ) {
							$input_name = $field_name;
						} elseif ( $allow_multiple ) {
							// 'num' will get replaced by an actual index, either in PHP
							// or in Javascript, later on
							$input_name = $template_name . '[num][' . $field_name . ']';
							$field_args['origName'] = $template_name . '[' . $field_name . ']';
						} else {
							$input_name = $template_name . '[' . $field_name . ']';
						}


						// If the 'values' parameter was set, separate it based on the
						// 'delimiter' parameter, if any.
						if ( ! empty( $values ) ) {
							if ( array_key_exists( 'delimiter', $field_args ) ) {
								$delimiter = $field_args['delimiter'];
							} else {
								$delimiter = ",";
							}
							// Remove whitespaces, and un-escape characters
							$possible_values = array_map( 'trim', explode( $delimiter, $values ) );
							$possible_values = array_map( 'htmlspecialchars_decode', $possible_values );
						}

						// if we're creating the page name from a formula based on
						// form values, see if the current input is part of that formula,
						// and if so, substitute in the actual value
						if ( $form_submitted && $generated_page_name !== '' ) {
							// this line appears to be unnecessary
							// $generated_page_name = str_replace('.', '_', $generated_page_name);
							$generated_page_name = str_replace( ' ', '_', $generated_page_name );
							$escaped_input_name = str_replace( ' ', '_', $input_name );
							$generated_page_name = str_ireplace( "<$escaped_input_name>", $cur_value_in_template, $generated_page_name );
							// once the substitution is done, replace underlines back
							// with spaces
							$generated_page_name = str_replace( '_', ' ', $generated_page_name );
						}
						// disable this field if either the whole form is disabled, or
						// it's a restricted field and user doesn't have sysop privileges
						$is_disabled = ( $form_is_disabled || $is_restricted );
						// Create an SFFormField instance based on all the parameters
						// in the form definition, and any information from the template
						// definition (contained in the $all_fields parameter).
						$form_field = SFFormField::createFromDefinition( $field_name,
							$input_name, $is_mandatory, $is_hidden, $is_uploadable,
							$possible_values, $is_disabled, $is_list, $input_type,
							$field_args, $all_fields, $strict_parsing );
						// If a property was set in the form definition, overwrite whatever
						// is set in the template field - this is somewhat of a hack, since
						// parameters set in the form definition are meant to go into the
						// SFFormField object, not the SFTemplateField object it contains;
						// it seemed like too much work, though, to create an
						// SFFormField::setSemanticProperty() function just for this call
						if ( $semantic_property != null ) {
							$form_field->template_field->setSemanticProperty( $semantic_property );
						}
						$semantic_property = $form_field->template_field->getSemanticProperty();
						if ( !is_null( $semantic_property ) ) {
							global $sfgFieldProperties;
							$sfgFieldProperties[$fullFieldName] = $semantic_property;
						}


						// call hooks - unfortunately this has to be split into two
						// separate calls, because of the different variable names in
						// each case
						if ( $form_submitted ) {
							wfRunHooks( 'sfCreateFormField', array( &$form_field, &$cur_value_in_template, true ) );
						} else {
							wfRunHooks( 'sfCreateFormField', array( &$form_field, &$cur_value, false ) );
						}
						// if this is not part of a 'multiple' template, increment the
						// global tab index (used for correct tabbing)
						if ( ! array_key_exists( 'part_of_multiple', $field_args ) ) {
							$sfgTabIndex++;
						}
						// increment the global field number regardless
						$sfgFieldNum++;
						// If the field is a date field, and its default value was set
						// to 'now', and it has no current value, set $cur_value to be
						// the current date.
						if ( $default_value == 'now' &&
								// if the date is hidden, cur_value will already be set
								// to the default value
								( $cur_value === '' || $cur_value == 'now' ) ) {
							if ( $input_type == 'date' || $input_type == 'datetime' ||
									$input_type == 'year' ||
									( $input_type === '' && $form_field->getTemplateField()->getPropertyType() == '_dat' ) ) {
								// Get current time, for the time zone specified in the wiki.
								global $wgLocaltimezone;
								if ( isset( $wgLocaltimezone ) ) {
									$serverTimezone = date_default_timezone_get();
									date_default_timezone_set( $wgLocaltimezone );
								}
								$cur_time = time();
								$year = date( "Y", $cur_time );
								$month = date( "n", $cur_time );
								$day = date( "j", $cur_time );
								global $wgAmericanDates, $sfg24HourTime;
								if ( $wgAmericanDates == true ) {
									$month_names = SFFormUtils::getMonthNames();
									$month_name = $month_names[$month - 1];
									$cur_value_in_template = "$month_name $day, $year";
								} else {
									$cur_value_in_template = "$year/$month/$day";
								}
								if ( isset( $wgLocaltimezone ) ) {
									date_default_timezone_set( $serverTimezone );
								}
								if ( $input_type ==	'datetime' ) {
									if ( $sfg24HourTime ) {
										$hour = str_pad( intval( substr( date( "G", $cur_time ), 0, 2 ) ), 2, '0', STR_PAD_LEFT );
									} else {
										$hour = str_pad( intval( substr( date( "g", $cur_time ), 0, 2 ) ), 2, '0', STR_PAD_LEFT );
									}
									$minute = str_pad( intval( substr( date( "i", $cur_time ), 0, 2 ) ), 2, '0', STR_PAD_LEFT );
									$second = str_pad( intval( substr( date( "s", $cur_time ), 0, 2 ) ), 2, '0', STR_PAD_LEFT );
									if ( $sfg24HourTime ) {
										$cur_value_in_template .= " $hour:$minute:$second";
									} else {
										$ampm = date( "A", $cur_time );
										$cur_value_in_template .= " $hour:$minute:$second $ampm";
									}
								}
								if ( array_key_exists( 'include timezone', $field_args ) ) {
									$timezone = date( "T", $cur_time );
									$cur_value_in_template .= " $timezone";
								}
							}
						}
						// If the field is a text field, and its default value was set
						// to 'current user', and it has no current value, set $cur_value
						// to be the current user.
						if ( $default_value == 'current user' &&
							// if the date is hidden, cur_value will already be set
							// to the default value
							( $cur_value === '' || $cur_value == 'current user' ) ) {

							$cur_value_in_template = $wgUser->getName();
							$cur_value = $cur_value_in_template;
						}

						// Generate a hidden field with a placeholder value that will be replaced
						// by the multiple-instances template output at form submission.
						//// <input type="hidden" value="@replace_Town___mayors@" name="Town[town_mayors]" />
						if ( $holds_template ) {
							$cur_value = self::makePlaceholderInWikiText( self::placeholderFormat( $template_name, $field_name ) );
						}

						$new_text = $this->formFieldHTML( $form_field, $cur_value );

						// Add a field just after the hidden field, within the HTML, to locate
						// where the multiple-templates HTML, stored in $multipleTemplateString,
						// should be inserted.
						if ( $holds_template ) {
							$new_text .= self::makePlaceholderInFormHTML( self::placeholderFormat( $template_name, $field_name ) );
						}

						// If this field is disabled, add a hidden field holding
						// the value of this field, because disabled inputs for some
						// reason don't submit their value.
						if ( $form_field->isDisabled() ) {
							if ( $field_name == 'free text' || $field_name == '<freetext>' ) {
								$new_text .= SFFormUtils::hiddenFieldHTML( 'free_text', '!free_text!' );
							} else {
								$new_text .= SFFormUtils::hiddenFieldHTML( $input_name, $cur_value );
							}
						}

						if ( $new_text ) {
							// Include the field name only for non-numeric field names.
							if ( is_numeric( $field_name ) ) {
								$template_text .= "|$cur_value_in_template";
							} else {
								// If the value is null, don't include it at all.
								if ( $cur_value_in_template !== '' ) {
									$template_text .= "\n|$field_name=$cur_value_in_template";
								}
							}
							$section = substr_replace( $section, $new_text, $brackets_loc, $brackets_end_loc + 3 - $brackets_loc );
						} else {
							$start_position = $brackets_end_loc;
						}
					}
				// =====================================================
				// standard input processing
				// =====================================================
				} elseif ( $tag_title == 'standard input' ) {
					// handle all the possible values
					$input_name = $tag_components[1];
					$input_label = null;
					$attr = array();

					// if it's a query, ignore all standard inputs except run query
					if ( ( $is_query && $input_name != 'run query' ) || ( !$is_query && $input_name == 'run query' ) ) {
						$new_text = "";
						$section = substr_replace( $section, $new_text, $brackets_loc, $brackets_end_loc + 3 - $brackets_loc );
						continue;
					}
					// set a flag so that the standard 'form bottom' won't get displayed
					$this->standardInputsIncluded = true;
					// cycle through the other components
					for ( $i = 2; $i < count( $tag_components ); $i++ ) {
						$component = $tag_components[$i];
						$sub_components = array_map( 'trim', explode( '=', $component ) );
						if ( count( $sub_components ) == 1 ) {
							if ( $sub_components[0] == 'edittools' ) {
								$free_text_components[] = 'edittools';
							}
						} elseif ( count( $sub_components ) == 2 ) {
							switch( $sub_components[0] ) {
							case 'label':
								$input_label = $sub_components[1];
								break;
							case 'class':
							case 'style':
								$attr[$sub_components[0]] = $sub_components[1];
								break;
							}
							// free text input needs more handling than the rest
							if ( $input_name == 'free text' || $input_name == '<freetext>' ) {
								if ( $sub_components[0] == 'preload' ) {
									$free_text_preload_page = $sub_components[1];
								}
							}
						}
					}
					if ( $input_name == 'summary' ) {
						$new_text = SFFormUtils::summaryInputHTML( $form_is_disabled, $input_label, $attr );
					} elseif ( $input_name == 'minor edit' ) {
						$new_text = SFFormUtils::minorEditInputHTML( $form_is_disabled, $input_label, $attr );
					} elseif ( $input_name == 'watch' ) {
						$new_text = SFFormUtils::watchInputHTML( $form_is_disabled, $input_label, $attr );
					} elseif ( $input_name == 'save' ) {
						$new_text = SFFormUtils::saveButtonHTML( $form_is_disabled, $input_label, $attr );
					} elseif ( $input_name == 'save and continue' ) {
						$new_text = SFFormUtils::saveAndContinueButtonHTML( $form_is_disabled, $input_label, $attr );
					} elseif ( $input_name == 'preview' ) {
						$new_text = SFFormUtils::showPreviewButtonHTML( $form_is_disabled, $input_label, $attr );
					} elseif ( $input_name == 'changes' ) {
						$new_text = SFFormUtils::showChangesButtonHTML( $form_is_disabled, $input_label, $attr );
					} elseif ( $input_name == 'cancel' ) {
						$new_text = SFFormUtils::cancelLinkHTML( $form_is_disabled, $input_label, $attr );
					} elseif ( $input_name == 'run query' ) {
						$new_text = SFFormUtils::runQueryButtonHTML( $form_is_disabled, $input_label, $attr );
					}
					$section = substr_replace( $section, $new_text, $brackets_loc, $brackets_end_loc + 3 - $brackets_loc );
				// =====================================================
				// page info processing
				// =====================================================
				} elseif ( $tag_title == 'info' ) {
					// TODO: Generate an error message if this is included more than once
					foreach ( array_slice( $tag_components, 1 ) as $component ) {
						$sub_components = array_map( 'trim', explode( '=', $component, 2 ) );
						// Tag names are case-insensitive
						$tag = strtolower( $sub_components[0] );
						if ( $tag == 'create title' || $tag == 'add title' ) {
							// Handle this only if
							// we're adding a page.
							if ( !$is_query && !$this->mPageTitle->exists() ) {
								$form_page_title = $sub_components[1];
							}
						} elseif ( $tag == 'edit title' ) {
							// Handle this only if
							// we're editing a page.
							if ( !$is_query && $this->mPageTitle->exists() ) {
								$form_page_title = $sub_components[1];
							}
						} elseif ( $tag == 'query title' ) {
							// Handle this only if
							// we're in 'RunQuery'.
							if ( $is_query ) {
								$form_page_title = $sub_components[1];
							}
						} elseif ( $tag == 'partial form' ) {
							$form_is_partial = true;
							// replacement pages may have minimal matches...
							$source_page_matches_this_form = true;
						} elseif ( $tag == 'includeonly free text' || $tag == 'onlyinclude free text' ) {
							$onlyinclude_free_text = true;
						} elseif ( $tag == 'query form at top' ) {
							// TODO - this should be made a field of
							// some non-static class that actually
							// prints the form, instead of requiring
							// a global variable.
							global $sfgRunQueryFormAtTop;
							$sfgRunQueryFormAtTop = true;
						}
					}
					$section = substr_replace( $section, '', $brackets_loc, $brackets_end_loc + 3 - $brackets_loc );
				// =====================================================
				// default outer level processing
				// =====================================================
				} else { // Tag is not one of the three allowed values -
					// ignore the tag.
					$start_position = $brackets_end_loc;
				} // end if
			} // end while

			if ( ! $all_instances_printed ) {
				if ( $template_text !== '' ) {
					// For mostly aesthetic purposes, if the template call ends with
					// a bunch of pipes (i.e., it's an indexed template with unused
					// parameters at the end), remove the pipes.
					$template_text = preg_replace( '/\|*$/', '', $template_text );
					// add another newline before the final bracket, if this template
					// call is already more than one line
					if ( strpos( $template_text, "\n" ) ) {
						$template_text .= "\n";
					}
					// If we're editing an existing page, and there were fields in
					// the template call not handled by this form, preserve those.
					if ( !$allow_multiple ) {
						$template_text .= SFFormUtils::addUnhandledFields( $template_name );
					}
					$template_text .= "}}";

					// The base $template_text will contain strings like "@replace_xxx@"
					// in the hidden fields when the form is submitted.
					// On the following loops, the text for the multiple-instance templates
					// is progressively reinserted in the main data, always keeping a
					// trailing @replace_xxx@ for a given field
					// The trailing @replace_xxx@ is then deleted at the end.
					// Note: this cleanup step could also be done with a regexp, instead of
					// keeping a track array (e.g., /@replace_(.*)@/)
					$reptmp = self::makePlaceholderInWikiText( $curPlaceholder );
					if ( $curPlaceholder != null && $data_text && strpos( $data_text, $reptmp, 0 ) !== false ) {
						$data_text = preg_replace( '/' . $reptmp . '/', $template_text . $reptmp, $data_text );
					} else {
						$data_text .= $template_text . "\n";
					}

					// If there is a placeholder in the
					// text, we know that we are
					// doing a replace.
					if ( $existing_page_content && strpos( $existing_page_content, '{{{insertionpoint}}}', 0 ) !== false ) {
						$existing_page_content = preg_replace( '/\{\{\{insertionpoint\}\}\}(\r?\n?)/',
							preg_replace( '/\}\}/m', '}�',
								preg_replace( '/\{\{/m', '�{', $template_text ) ) .
							"\n{{{insertionpoint}}}",
							$existing_page_content );
					// otherwise, if it's a partial form, we have to add the new
					// text somewhere
					} elseif ( $form_is_partial && $wgRequest->getCheck( 'partial' ) ) {
						$existing_page_content = preg_replace( '/\}\}/m', '}�',
							preg_replace( '/\{\{/m', '�{', $template_text ) ) .
								"\n{{{insertionpoint}}}\n" . $existing_page_content;
					}
				}
			}

			if ( $allow_multiple ) {
				if ( $curPlaceholder == null ) {
					// The normal process.
					$form_text .= $this->multipleTemplateInstanceHTML( $form_is_disabled, $all_instances_printed, $section, $instance_num, $add_button_text );
				} else { // if ( $curPlaceholder != null ){
					// The template text won't be appended at the end of the template like for usual multiple template forms.
					// The HTML text will then be stored in the $multipleTemplateString variable,
					// and then added in the right @insertHTML_".$placeHolderField."@"; position
					// Optimization: actually, instead of separating the processes, the usual multiple
					// template forms could also be handled this way if a fitting placeholder tag was added.
					$multipleTemplateString .= $this->multipleTemplateInstanceHTML( $form_is_disabled, $all_instances_printed, $section, $instance_num, $add_button_text );
					// We replace the $multipleTemplateString HTML into the
					// current placeholder tag, but also add another
					// placeholder tag, to keep track of it.
					$multipleTemplateString .= self::makePlaceholderInFormHTML( $curPlaceholder );
					if ( isset( $template_label ) ) {
						$multipleTemplateString .= "</fieldset>\n";
						unset ( $template_label );
					}
					$form_text = preg_replace( '/' . self::makePlaceholderInFormHTML( $curPlaceholder ) . '/',
						$multipleTemplateString, $form_text );
				}
				if ( ! $all_instances_printed ) {
					// This will cause the section to be
					// re-parsed on the next go.
					$section_num--;
				}
			} else { // if ( $allow_multiple ) {
				$form_text .= $section;
			}
			$curPlaceholder = null;
		} // end for

		// Cleanup - everything has been browsed.
		// Remove all the remaining placeholder
		// tags in the HTML and wiki-text.
		foreach ( $placeholderFields as $stringToReplace ) {
			// remove the @<replacename>@ tags from the data that is submitted
			$data_text = preg_replace( '/' . self::makePlaceholderInWikiText( $stringToReplace ) . '/', '', $data_text );

			// remove the @<insertHTML>@ tags from the generated HTML form
			$form_text = preg_replace( '/' . self::makePlaceholderInFormHTML( $stringToReplace ) . '/', '', $form_text );
		}

		// if it wasn't included in the form definition, add the
		// 'free text' input as a hidden field at the bottom
		if ( ! $free_text_was_included ) {
			$form_text .= SFFormUtils::hiddenFieldHTML( 'free_text', '!free_text!' );
		}
		// Get free text, and add to page data, as well as retroactively
		// inserting it into the form.

		// If $form_is_partial is true then either:
		// (a) we're processing a replacement (param 'partial' == 1)
		// (b) we're sending out something to be replaced (param 'partial' is missing)
		if ( $form_is_partial ) {
			if ( !$wgRequest->getCheck( 'partial' ) ) {
				$free_text = $original_page_content;
				$form_text .= SFFormUtils::hiddenFieldHTML( 'partial', 1 );
			} else {
				$free_text = null;
				$existing_page_content = preg_replace( array( '/�\{/m', '/\}�/m' ),
					array( '{{', '}}' ),
					$existing_page_content );
				$existing_page_content = preg_replace( '/\{\{\{insertionpoint\}\}\}/', '', $existing_page_content );
			}
		} elseif ( $source_is_page ) {
			// if the page is the source, free_text will just be whatever in the
			// page hasn't already been inserted into the form
			$free_text = trim( $existing_page_content );
		// or get it from a form submission
		} elseif ( $wgRequest->getCheck( 'free_text' ) ) {
			$free_text = $wgRequest->getVal( 'free_text' );
			if ( ! $free_text_was_included ) {
				$data_text .= "!free_text!";
			}
		// or get it from the form definition
		} elseif ( $free_text_preload_page != null ) {
			$free_text = SFFormUtils::getPreloadedText( $free_text_preload_page );
		} else {
			$free_text = null;
		}
		if ( $onlyinclude_free_text ) {
			// modify free text and data text to insert <onlyinclude> tags
			$free_text = str_replace( "<onlyinclude>", '', $free_text );
			$free_text = str_replace( "</onlyinclude>", '', $free_text );
			$free_text = trim( $free_text );
			$data_text = str_replace( '!free_text!', '<onlyinclude>!free_text!</onlyinclude>', $data_text );
		}

		wfRunHooks( 'sfModifyFreeTextField', array( &$free_text, $existing_page_content ) );
		// if the FCKeditor extension is installed, use that for the free text input
		global $wgFCKEditorDir;
		if ( $wgFCKEditorDir && strpos( $existing_page_content, '__NORICHEDITOR__' ) === false ) {
			$showFCKEditor = SFFormUtils::getShowFCKEditor();
			if ( !$form_submitted && ( $showFCKEditor & RTE_VISIBLE ) ) {
				$free_text = SFFormUtils::prepareTextForFCK( $free_text );
			}
		} else {
			$showFCKEditor = 0;
		}
		// now that we have it, substitute free text into the form and page
		$escaped_free_text = Sanitizer::safeEncodeAttribute( $free_text );
		$form_text = str_replace( '!free_text!', $escaped_free_text, $form_text );
		$data_text = str_replace( '!free_text!', $free_text, $data_text );

		// Add a warning in, if we're editing an existing page and that
		// page appears to not have been created with this form.
		if ( !$is_query && $this->mPageTitle->exists() && ( $existing_page_content !== '' ) && ! $source_page_matches_this_form ) {
			$form_text = "\t" . '<div class="warningbox">' . wfMsg( 'sf_formedit_formwarning', $this->mPageTitle->getFullURL() ) . "</div>\n<br clear=\"both\" />\n" . $form_text;
		}

		// add form bottom, if no custom "standard inputs" have been defined
		if ( !$this->standardInputsIncluded ) {
			if ( $is_query )
				$form_text .= SFFormUtils::queryFormBottom( $form_is_disabled );
			else
				$form_text .= SFFormUtils::formBottom( $form_is_disabled );
		}

		$page_article = new Article( $this->mPageTitle, 0 );

		if ( !$is_query ) {
			$form_text .= SFFormUtils::hiddenFieldHTML( 'wpStarttime', wfTimestampNow() );
			$form_text .= SFFormUtils::hiddenFieldHTML( 'wpEdittime', $page_article->getTimestamp() );
		}

		$form_text .= "\t</form>\n";

		// Add general Javascript code.
		wfRunHooks( 'sfAddJavascriptToForm', array( &$javascript_text ) );

		// @TODO The FCKeditor Javascript should be handled within
		// the FCKeditor extension itself, using the hook.
		$javascript_text = "";
		if ( $free_text_was_included && $showFCKEditor > 0 ) {
			$javascript_text .= SFFormUtils::mainFCKJavascript( $showFCKEditor, $field_args );
			if ( $showFCKEditor & ( RTE_TOGGLE_LINK | RTE_POPUP ) ) {
				$javascript_text .= SFFormUTils::FCKToggleJavascript();
			}
			if ( $showFCKEditor & RTE_POPUP ) {
				$javascript_text .= SFFormUTils::FCKPopupJavascript();
			}
		}

		// Send the autocomplete values to the browser, along with the
		// mappings of which values should apply to which fields.
		// If doing a replace, the data text is actually the modified original page
		if ( $wgRequest->getCheck( 'partial' ) )
			$data_text = $existing_page_content;

		if ( !$is_embedded ) {
			$form_page_title = $wgParser->recursiveTagParse( str_replace( "{{!}}", "|", $form_page_title ) );
		} else {
			$form_page_title = null;
		}

		// If the form has already been submitted, i.e. this is just
		// the redirect page, get rid of all the Javascript, to avoid
		// JS errors.
		if ( $form_submitted ) {
			$javascript_text = '';
		}

		$parserOutput = $wgParser->getOutput();
		$wgOut->addParserOutputNoText( $parserOutput );

		$wgParser = $oldParser;

		wfProfileOut( __METHOD__ );

		return array( $form_text, $javascript_text, $data_text, $form_page_title, $generated_page_name );
	}
 /**
  * Save categories sent via AJAX into article
  */
 public function save()
 {
     wfProfileIn(__METHOD__);
     $articleId = $this->request->getVal('articleId', 0);
     $categories = $this->request->getVal('categories', array());
     $response = array();
     $title = Title::newFromID($articleId);
     if (wfReadOnly()) {
         $response['error'] = wfMessage('categoryselect-error-db-locked')->text();
     } else {
         if (is_null($title)) {
             $response['error'] = wfMessage('categoryselect-error-article-doesnt-exist', $articleId)->text();
         } else {
             if (!$title->userCan('edit') || $this->wg->User->isBlocked()) {
                 $response['error'] = wfMessage('categoryselect-error-user-rights')->text();
             } else {
                 if (!empty($categories) && is_array($categories)) {
                     Wikia::setVar('EditFromViewMode', 'CategorySelect');
                     $article = new Article($title);
                     $wikitext = $article->fetchContent();
                     // Pull in categories from templates inside of the article (BugId:100980)
                     $options = new ParserOptions();
                     $preprocessedWikitext = ParserPool::preprocess($wikitext, $title, $options);
                     $preprocessedData = CategoryHelper::extractCategoriesFromWikitext($preprocessedWikitext, true);
                     // Compare the new categories with those already in the article to weed out duplicates
                     $newCategories = CategoryHelper::getDiffCategories($preprocessedData['categories'], $categories);
                     // Append the new categories to the end of the article wikitext
                     $wikitext .= CategoryHelper::changeFormat($newCategories, 'array', 'wikitext');
                     // Update the array of categories for the front-end
                     $categories = array_merge($preprocessedData['categories'], $newCategories);
                     $dbw = wfGetDB(DB_MASTER);
                     $dbw->begin();
                     $editPage = new EditPage($article);
                     $editPage->edittime = $article->getTimestamp();
                     $editPage->recreate = true;
                     $editPage->textbox1 = $wikitext;
                     $editPage->summary = wfMessage('categoryselect-edit-summary')->inContentLanguage()->text();
                     $editPage->watchthis = $editPage->mTitle->userIsWatching();
                     $bot = $this->wg->User->isAllowed('bot');
                     $status = $editPage->internalAttemptSave($result, $bot)->value;
                     $response['status'] = $status;
                     switch ($status) {
                         case EditPage::AS_SUCCESS_UPDATE:
                         case EditPage::AS_SUCCESS_NEW_ARTICLE:
                             $dbw->commit();
                             $title->invalidateCache();
                             Article::onArticleEdit($title);
                             $response['html'] = $this->app->renderView('CategorySelectController', 'categories', array('categories' => $categories));
                             wfRunHooks('CategorySelectSave', array($title, $newCategories));
                             break;
                         case EditPage::AS_SPAM_ERROR:
                             $dbw->rollback();
                             $response['error'] = wfMessage('spamprotectiontext')->text() . '<p>( Case #8 )</p>';
                             break;
                         default:
                             $dbw->rollback();
                             $response['error'] = wfMessage('categoryselect-error-edit-abort')->text();
                     }
                 }
             }
         }
     }
     $this->response->setData($response);
     wfProfileOut(__METHOD__);
 }
Example #27
0
 protected function showHeader()
 {
     global $wgOut, $wgUser, $wgMaxArticleSize, $wgLang;
     if ($this->mTitle->isTalkPage()) {
         $wgOut->addWikiMsg('talkpagetext');
     }
     # Optional notices on a per-namespace and per-page basis
     $editnotice_ns = 'editnotice-' . $this->mTitle->getNamespace();
     $editnotice_ns_message = wfMessage($editnotice_ns)->inContentLanguage();
     if ($editnotice_ns_message->exists()) {
         $wgOut->addWikiText($editnotice_ns_message->plain());
     }
     if (MWNamespace::hasSubpages($this->mTitle->getNamespace())) {
         $parts = explode('/', $this->mTitle->getDBkey());
         $editnotice_base = $editnotice_ns;
         while (count($parts) > 0) {
             $editnotice_base .= '-' . array_shift($parts);
             $editnotice_base_msg = wfMessage($editnotice_base)->inContentLanguage();
             if ($editnotice_base_msg->exists()) {
                 $wgOut->addWikiText($editnotice_base_msg->plain());
             }
         }
     } else {
         # Even if there are no subpages in namespace, we still don't want / in MW ns.
         $editnoticeText = $editnotice_ns . '-' . str_replace('/', '-', $this->mTitle->getDBkey());
         $editnoticeMsg = wfMessage($editnoticeText)->inContentLanguage();
         if ($editnoticeMsg->exists()) {
             $wgOut->addWikiText($editnoticeMsg->plain());
         }
     }
     if ($this->isConflict) {
         $wgOut->wrapWikiMsg("<div class='mw-explainconflict'>\n\$1\n</div>", 'explainconflict');
         $this->edittime = $this->mArticle->getTimestamp();
     } else {
         if ($this->section != '' && !$this->isSectionEditSupported()) {
             // We use $this->section to much before this and getVal('wgSection') directly in other places
             // at this point we can't reset $this->section to '' to fallback to non-section editing.
             // Someone is welcome to try refactoring though
             $wgOut->showErrorPage('sectioneditnotsupported-title', 'sectioneditnotsupported-text');
             return false;
         }
         if ($this->section != '' && $this->section != 'new') {
             if (!$this->summary && !$this->preview && !$this->diff) {
                 $sectionTitle = self::extractSectionTitle($this->textbox1);
                 if ($sectionTitle !== false) {
                     $this->summary = "/* {$sectionTitle} */ ";
                 }
             }
         }
         if ($this->missingComment) {
             $wgOut->wrapWikiMsg("<div id='mw-missingcommenttext'>\n\$1\n</div>", 'missingcommenttext');
         }
         if ($this->missingSummary && $this->section != 'new') {
             $wgOut->wrapWikiMsg("<div id='mw-missingsummary'>\n\$1\n</div>", 'missingsummary');
         }
         if ($this->missingSummary && $this->section == 'new') {
             $wgOut->wrapWikiMsg("<div id='mw-missingcommentheader'>\n\$1\n</div>", 'missingcommentheader');
         }
         if ($this->hookError !== '') {
             $wgOut->addWikiText($this->hookError);
         }
         if (!$this->checkUnicodeCompliantBrowser()) {
             $wgOut->addWikiMsg('nonunicodebrowser');
         }
         if ($this->section != 'new') {
             $revision = $this->mArticle->getRevisionFetched();
             if ($revision) {
                 // Let sysop know that this will make private content public if saved
                 if (!$revision->userCan(Revision::DELETED_TEXT)) {
                     $wgOut->wrapWikiMsg("<div class='mw-warning plainlinks'>\n\$1\n</div>\n", 'rev-deleted-text-permission');
                 } elseif ($revision->isDeleted(Revision::DELETED_TEXT)) {
                     $wgOut->wrapWikiMsg("<div class='mw-warning plainlinks'>\n\$1\n</div>\n", 'rev-deleted-text-view');
                 }
                 if (!$revision->isCurrent()) {
                     $this->mArticle->setOldSubtitle($revision->getId());
                     $wgOut->addWikiMsg('editingold');
                 }
             } elseif ($this->mTitle->exists()) {
                 // Something went wrong
                 $wgOut->wrapWikiMsg("<div class='errorbox'>\n\$1\n</div>\n", array('missing-article', $this->mTitle->getPrefixedText(), wfMsgNoTrans('missingarticle-rev', $this->oldid)));
             }
         }
     }
     if (wfReadOnly()) {
         $wgOut->wrapWikiMsg("<div id=\"mw-read-only-warning\">\n\$1\n</div>", array('readonlywarning', wfReadOnlyReason()));
     } elseif ($wgUser->isAnon()) {
         if ($this->formtype != 'preview') {
             $wgOut->wrapWikiMsg("<div id=\"mw-anon-edit-warning\">\n\$1</div>", 'anoneditwarning');
         } else {
             $wgOut->wrapWikiMsg("<div id=\"mw-anon-preview-warning\">\n\$1</div>", 'anonpreviewwarning');
         }
     } else {
         if ($this->isCssJsSubpage) {
             # Check the skin exists
             if ($this->isWrongCaseCssJsPage) {
                 $wgOut->wrapWikiMsg("<div class='error' id='mw-userinvalidcssjstitle'>\n\$1\n</div>", array('userinvalidcssjstitle', $this->mTitle->getSkinFromCssJsSubpage()));
             }
             if ($this->getTitle()->isSubpageOf($wgUser->getUserPage())) {
                 if ($this->formtype !== 'preview') {
                     if ($this->isCssSubpage) {
                         $wgOut->wrapWikiMsg("<div id='mw-usercssyoucanpreview'>\n\$1\n</div>", array('usercssyoucanpreview'));
                     }
                     if ($this->isJsSubpage) {
                         $wgOut->wrapWikiMsg("<div id='mw-userjsyoucanpreview'>\n\$1\n</div>", array('userjsyoucanpreview'));
                     }
                 }
             }
         }
     }
     if ($this->mTitle->getNamespace() != NS_MEDIAWIKI && $this->mTitle->isProtected('edit')) {
         # Is the title semi-protected?
         if ($this->mTitle->isSemiProtected()) {
             $noticeMsg = 'semiprotectedpagewarning';
         } else {
             # Then it must be protected based on static groups (regular)
             $noticeMsg = 'protectedpagewarning';
         }
         LogEventsList::showLogExtract($wgOut, 'protect', $this->mTitle, '', array('lim' => 1, 'msgKey' => array($noticeMsg)));
     }
     if ($this->mTitle->isCascadeProtected()) {
         # Is this page under cascading protection from some source pages?
         list($cascadeSources, ) = $this->mTitle->getCascadeProtectionSources();
         $notice = "<div class='mw-cascadeprotectedwarning'>\n\$1\n";
         $cascadeSourcesCount = count($cascadeSources);
         if ($cascadeSourcesCount > 0) {
             # Explain, and list the titles responsible
             foreach ($cascadeSources as $page) {
                 $notice .= '* [[:' . $page->getPrefixedText() . "]]\n";
             }
         }
         $notice .= '</div>';
         $wgOut->wrapWikiMsg($notice, array('cascadeprotectedwarning', $cascadeSourcesCount));
     }
     if (!$this->mTitle->exists() && $this->mTitle->getRestrictions('create')) {
         LogEventsList::showLogExtract($wgOut, 'protect', $this->mTitle, '', array('lim' => 1, 'showIfEmpty' => false, 'msgKey' => array('titleprotectedwarning'), 'wrap' => "<div class=\"mw-titleprotectedwarning\">\n\$1</div>"));
     }
     if ($this->kblength === false) {
         $this->kblength = (int) (strlen($this->textbox1) / 1024);
     }
     if ($this->tooBig || $this->kblength > $wgMaxArticleSize) {
         $wgOut->wrapWikiMsg("<div class='error' id='mw-edit-longpageerror'>\n\$1\n</div>", array('longpageerror', $wgLang->formatNum($this->kblength), $wgLang->formatNum($wgMaxArticleSize)));
     } else {
         if (!wfMessage('longpage-hint')->isDisabled()) {
             $wgOut->wrapWikiMsg("<div id='mw-edit-longpage-hint'>\n\$1\n</div>", array('longpage-hint', $wgLang->formatSize(strlen($this->textbox1)), strlen($this->textbox1)));
         }
     }
 }
 /**
  * Create new article
  *
  * When successful returns title object of created article. If not, returns EditPage error code
  */
 protected function createArticle($title, $content, $summary)
 {
     global $wgUser;
     wfProfileIn(__METHOD__);
     self::log(__METHOD__, "creating article '{$title}'");
     //self::log(__METHOD__, array($title, $content, $summary));
     $ret = false;
     // title object for new article
     $newTitle = Title::newFromText($title);
     if (!empty($newTitle) && !empty($wgUser) && $newTitle->userCan('edit') && !$wgUser->isBlocked()) {
         $article = new Article($newTitle);
         $editPage = new EditPage($article);
         $editPage->edittime = $article->getTimestamp();
         $editPage->textbox1 = $content;
         $editPage->summary = $summary;
         $editPage->recreate = true;
         $result = null;
         $bot = $wgUser->isAllowed('bot');
         // do edit
         $status = $editPage->internalAttemptSave($result, $bot);
         $ret = $status->value;
         // creating new article
         if ($ret == EditPage::AS_SUCCESS_NEW_ARTICLE) {
             // edit successful
             $newTitle->invalidateCache();
             Article::onArticleEdit($newTitle);
             self::log(__METHOD__, 'success!');
             $ret = $newTitle;
         } elseif ($ret == EditPage::AS_SPAM_ERROR) {
             self::log(__METHOD__, 'spam found!');
         } else {
             self::log(__METHOD__, 'edit aborted');
         }
     } else {
         self::log(__METHOD__, 'user not allowed to edit');
         $ret = EditPage::AS_USER_CANNOT_EDIT;
     }
     if (is_numeric($ret)) {
         self::log(__METHOD__, "failed with error code #{$ret}");
     }
     wfProfileOut(__METHOD__);
     return $ret;
 }
    /**
     * This function is the real heart of the entire Semantic Forms
     * extension. It handles two main actions: (1) displaying a form on the
     * screen, given a form definition and possibly page contents (if an
     * existing page is being edited); and (2) creating actual page
     * contents, if the form was already submitted by the user.
     *
     * It also does some related tasks, like figuring out the page name (if
     * only a page formula exists).
     */
    function formHTML($form_def, $form_submitted, $source_is_page, $form_id = null, $existing_page_content = null, $page_name = null, $page_name_formula = null, $is_query = false, $is_embedded = false)
    {
        global $wgRequest, $wgUser, $wgParser;
        global $sfgTabIndex;
        // used to represent the current tab index in the form
        global $sfgFieldNum;
        // used for setting various HTML IDs
        // initialize some variables
        $wiki_page = new SFWikiPage();
        $sfgTabIndex = 1;
        $sfgFieldNum = 1;
        $source_page_matches_this_form = false;
        $form_page_title = null;
        $generated_page_name = $page_name_formula;
        // $form_is_partial is true if:
        // (a) 'partial' == 1 in the arguments
        // (b) 'partial form' is found in the form definition
        // in the latter case, it may remain false until close to the end of
        // the parsing, so we have to assume that it will become a possibility
        $form_is_partial = false;
        $new_text = "";
        // If we have existing content and we're not in an active replacement
        // situation, preserve the original content. We do this because we want
        // to pass the original content on IF this is a partial form.
        // TODO: A better approach here would be to pass the revision ID of the
        // existing page content through the replace value, which would
        // minimize the html traffic and would allow us to do a concurrent
        // update check. For now, we pass it through a hidden text field.
        if (!$wgRequest->getCheck('partial')) {
            $original_page_content = $existing_page_content;
        } else {
            $original_page_content = null;
            if ($wgRequest->getCheck('sf_free_text')) {
                if (!isset($existing_page_content) || $existing_page_content == '') {
                    $existing_page_content = $wgRequest->getVal('sf_free_text');
                }
                $form_is_partial = true;
            }
        }
        // Disable all form elements if user doesn't have edit
        // permission - two different checks are needed, because
        // editing permissions can be set in different ways.
        // HACK - sometimes we don't know the page name in advance, but
        // we still need to set a title here for testing permissions.
        if ($is_embedded) {
            // If this is an embedded form (probably a 'RunQuery'),
            // just use the name of the actual page we're on.
            global $wgTitle;
            $this->mPageTitle = $wgTitle;
        } elseif ($is_query) {
            // We're in Special:RunQuery - just use that as the
            // title.
            global $wgTitle;
            $this->mPageTitle = $wgTitle;
        } elseif ($page_name === '' || $page_name === null) {
            $this->mPageTitle = Title::newFromText($wgRequest->getVal('namespace') . ":Semantic Forms permissions test");
        } else {
            $this->mPageTitle = Title::newFromText($page_name);
        }
        global $wgOut;
        // Show previous set of deletions for this page, if it's been
        // deleted before.
        if (!$form_submitted && ($this->mPageTitle && !$this->mPageTitle->exists() && is_null($page_name_formula))) {
            $this->showDeletionLog($wgOut);
        }
        // Unfortunately, we can't just call userCan() here because,
        // since MW 1.16, it has a bug in which it ignores a setting of
        // "$wgEmailConfirmToEdit = true;". Instead, we'll just get the
        // permission errors from the start, and use those to determine
        // whether the page is editable.
        if (!$is_query) {
            // $userCanEditPage = ( $wgUser->isAllowed( 'edit' ) && $this->mPageTitle->userCan( 'edit' ) );
            $permissionErrors = $this->mPageTitle->getUserPermissionsErrors('edit', $wgUser);
            // The handling of $wgReadOnly and $wgReadOnlyFile
            // has to be done separately.
            if (wfReadOnly()) {
                $permissionErrors = array(array('readonlytext', array(wfReadOnlyReason())));
            }
            $userCanEditPage = count($permissionErrors) == 0;
            Hooks::run('sfUserCanEditPage', array($this->mPageTitle, &$userCanEditPage));
        }
        $form_text = "";
        if ($is_query || $userCanEditPage) {
            $form_is_disabled = false;
            // Show "Your IP address will be recorded" warning if
            // user is anonymous, and it's not a query.
            if ($wgUser->isAnon() && !$is_query) {
                // Based on code in MediaWiki's EditPage.php.
                $anonEditWarning = wfMessage('anoneditwarning', '{{fullurl:Special:UserLogin|returnto={{FULLPAGENAMEE}}}}', '{{fullurl:Special:UserLogin/signup|returnto={{FULLPAGENAMEE}}}}')->parse();
                $form_text .= Html::rawElement('div', array('id' => 'mw-anon-edit-warning', 'class' => 'warningbox'), $anonEditWarning);
            }
        } else {
            $form_is_disabled = true;
            $wgOut->setPageTitle(wfMessage('badaccess')->text());
            $wgOut->addWikiText($wgOut->formatPermissionsErrorMessage($permissionErrors, 'edit'));
            $wgOut->addHTML("\n<hr />\n");
        }
        //		$oldParser = $wgParser;
        //		$wgParser = unserialize( serialize( $oldParser ) ); // deep clone of parser
        if (!$wgParser->Options()) {
            $wgParser->Options(ParserOptions::newFromUser($wgUser));
        }
        $wgParser->Title($this->mPageTitle);
        // This is needed in order to make sure $parser->mLinkHolders
        // is set.
        $wgParser->clearState();
        $form_def = SFFormUtils::getFormDefinition($wgParser, $form_def, $form_id);
        // Turn form definition file into an array of sections, one for
        // each template definition (plus the first section).
        $form_def_sections = array();
        $start_position = 0;
        $section_start = 0;
        $free_text_was_included = false;
        // Unencode any HTML-encoded representations of curly brackets and
        // pipes - this is a hack to allow for forms to include templates
        // that themselves contain form elements - the escaping was needed
        // to make sure that those elements don't get parsed too early.
        $form_def = str_replace(array('&#123;', '&#124;', '&#125;'), array('{', '|', '}'), $form_def);
        // And another hack - replace the 'free text' standard input
        // with a field declaration to get it to be handled as a field.
        $form_def = str_replace('standard input|free text', 'field|<freetext>', $form_def);
        while ($brackets_loc = strpos($form_def, "{{{", $start_position)) {
            $brackets_end_loc = strpos($form_def, "}}}", $brackets_loc);
            $bracketed_string = substr($form_def, $brackets_loc + 3, $brackets_end_loc - ($brackets_loc + 3));
            $tag_components = SFUtils::getFormTagComponents($bracketed_string);
            $tag_title = trim($tag_components[0]);
            if ($tag_title == 'for template' || $tag_title == 'end template') {
                // Create a section for everything up to here
                $section = substr($form_def, $section_start, $brackets_loc - $section_start);
                $form_def_sections[] = $section;
                $section_start = $brackets_loc;
            }
            $start_position = $brackets_loc + 1;
        }
        // end while
        $form_def_sections[] = trim(substr($form_def, $section_start));
        // Cycle through the form definition file, and possibly an
        // existing article as well, finding template and field
        // declarations and replacing them with form elements, either
        // blank or pre-populated, as appropriate.
        $tif = null;
        // This array will keep track of all the replaced @<name>@ strings
        $placeholderFields = array();
        for ($section_num = 0; $section_num < count($form_def_sections); $section_num++) {
            $start_position = 0;
            // the append is there to ensure that the original
            // array doesn't get modified; is it necessary?
            $section = " " . $form_def_sections[$section_num];
            while ($brackets_loc = strpos($section, '{{{', $start_position)) {
                $brackets_end_loc = strpos($section, "}}}", $brackets_loc);
                $bracketed_string = substr($section, $brackets_loc + 3, $brackets_end_loc - ($brackets_loc + 3));
                $tag_components = SFUtils::getFormTagComponents($bracketed_string);
                $tag_title = trim($tag_components[0]);
                // =====================================================
                // for template processing
                // =====================================================
                if ($tag_title == 'for template') {
                    if ($tif) {
                        $previous_template_name = $tif->getTemplateName();
                    } else {
                        $previous_template_name = '';
                    }
                    $template_name = str_replace('_', ' ', $tag_components[1]);
                    $is_new_template = $template_name != $previous_template_name;
                    if ($is_new_template) {
                        $tif = SFTemplateInForm::newFromFormTag($tag_components);
                    }
                    // Remove template tag.
                    $section = substr_replace($section, '', $brackets_loc, $brackets_end_loc + 3 - $brackets_loc);
                    // If we are editing a page, and this
                    // template can be found more than
                    // once in that page, and multiple
                    // values are allowed, repeat this
                    // section.
                    if ($source_is_page) {
                        $tif->setPageRelatedInfo($existing_page_content);
                        // Get the first instance of
                        // this template on the page
                        // being edited, even if there
                        // are more.
                        if ($tif->pageCallsThisTemplate()) {
                            $tif->setFieldValuesFromPage($existing_page_content);
                            $existing_template_text = $tif->getFullTextInPage();
                            // Now remove this template from the text being edited.
                            // If this is a partial form, establish a new insertion point.
                            if ($existing_page_content && $form_is_partial && $wgRequest->getCheck('partial')) {
                                // If something already exists, set the new insertion point
                                // to its position; otherwise just let it lie.
                                if (strpos($existing_page_content, $existing_template_text) !== false) {
                                    $existing_page_content = str_replace("\n" . '{{{insertionpoint}}}', '', $existing_page_content);
                                    $existing_page_content = str_replace($existing_template_text, '{{{insertionpoint}}}', $existing_page_content);
                                }
                            } else {
                                $existing_page_content = $this->strReplaceFirst($existing_template_text, '', $existing_page_content);
                            }
                            // If we've found a match in the source
                            // page, there's a good chance that this
                            // page was created with this form - note
                            // that, so we don't send the user a warning.
                            $source_page_matches_this_form = true;
                        }
                    }
                    if ($form_submitted) {
                        $tif->setFieldValuesFromSubmit();
                    }
                    $tif->checkIfAllInstancesPrinted($form_submitted, $source_is_page);
                    if (!$tif->allInstancesPrinted()) {
                        $wiki_page->addTemplate($tif);
                    }
                    // =====================================================
                    // end template processing
                    // =====================================================
                } elseif ($tag_title == 'end template') {
                    if ($source_is_page) {
                        // Add any unhandled template fields
                        // in the page as hidden variables.
                        $form_text .= SFFormUtils::unhandledFieldsHTML($tif);
                    }
                    // Remove this tag from the $section variable.
                    $section = substr_replace($section, '', $brackets_loc, $brackets_end_loc + 3 - $brackets_loc);
                    $tif = null;
                    // =====================================================
                    // field processing
                    // =====================================================
                } elseif ($tag_title == 'field') {
                    // If the template is null, that (hopefully)
                    // means we're handling the free text field.
                    // Make the template a dummy variable.
                    if ($tif == null) {
                        $tif = new SFTemplateInForm();
                    }
                    // We get the field name both here
                    // and in the SFFormField constructor,
                    // because SFFormField isn't equipped
                    // to deal with the <freetext> hack,
                    // among others.
                    $field_name = trim($tag_components[1]);
                    $form_field = SFFormField::newFromFormFieldTag($tag_components, $tif, $form_is_disabled);
                    $cur_value = $form_field->getCurrentValue($tif->getValuesFromSubmit(), $form_submitted, $source_is_page);
                    if ($form_field->holdsTemplate()) {
                        $placeholderFields[] = self::placeholderFormat($tif->getTemplateName(), $field_name);
                    }
                    // If the user is editing a page, and that page contains a call to
                    // the template being processed, get the current field's value
                    // from the template call
                    if ($source_is_page && ($tif->getFullTextInPage() != '' && !$form_submitted)) {
                        if ($tif->hasValueFromPageForField($field_name)) {
                            // Get value, and remove it,
                            // so that at the end we
                            // can have a list of all
                            // the fields that weren't
                            // handled by the form.
                            $cur_value = $tif->getAndRemoveValueFromPageForField($field_name);
                            // If the field is a placeholder, the contents of this template
                            // parameter should be treated as elements parsed by an another
                            // multiple template form.
                            // By putting that at the very end of the parsed string, we'll
                            // have it processed as a regular multiple template form.
                            if ($form_field->holdsTemplate()) {
                                $existing_page_content .= $cur_value;
                            }
                        } elseif (isset($cur_value) && !empty($cur_value)) {
                            // Do nothing.
                        } else {
                            $cur_value = '';
                        }
                    }
                    // Handle the free text field.
                    if ($field_name == '<freetext>') {
                        // Add placeholders for the free text in both the form and
                        // the page, using <free_text> tags - once all the free text
                        // is known (at the end), it will get substituted in.
                        if ($form_field->isHidden()) {
                            $new_text = Html::hidden('sf_free_text', '!free_text!');
                        } else {
                            $sfgTabIndex++;
                            $sfgFieldNum++;
                            if ($cur_value === '' || is_null($cur_value)) {
                                $default_value = '!free_text!';
                            } else {
                                $default_value = $cur_value;
                            }
                            $new_text = SFTextAreaInput::getHTML($default_value, 'sf_free_text', false, $form_is_disabled || $form_field->isRestricted(), $form_field->getFieldArgs());
                            if ($form_field->hasFieldArg('edittools')) {
                                // borrowed from EditPage::showEditTools()
                                $edittools_text = $wgParser->recursiveTagParse(wfMessage('edittools', array('content'))->text());
                                $new_text .= <<<END
\t\t<div class="mw-editTools">
\t\t{$edittools_text}
\t\t</div>

END;
                            }
                        }
                        $free_text_was_included = true;
                        $wiki_page->addFreeTextSection();
                    }
                    if ($tif->getTemplateName() === '' || $field_name == '<freetext>') {
                        $section = substr_replace($section, $new_text, $brackets_loc, $brackets_end_loc + 3 - $brackets_loc);
                    } else {
                        if (is_array($cur_value)) {
                            // @TODO - is this code ever called?
                            $delimiter = $form_field->getFieldArg('is_list');
                            // first, check if it's a list
                            if (array_key_exists('is_list', $cur_value) && $cur_value['is_list'] == true) {
                                $cur_value_in_template = "";
                                foreach ($cur_value as $key => $val) {
                                    if ($key !== "is_list") {
                                        if ($cur_value_in_template != "") {
                                            $cur_value_in_template .= $delimiter . " ";
                                        }
                                        $cur_value_in_template .= $val;
                                    }
                                }
                            } else {
                                // If it's not a list, it's probably from a checkbox or date input -
                                // convert the values into a string.
                                $cur_value_in_template = self::getStringFromPassedInArray($cur_value, $delimiter);
                            }
                        } else {
                            // value is not an array
                            $cur_value_in_template = $cur_value;
                        }
                        // If we're creating the page name from a formula based on
                        // form values, see if the current input is part of that formula,
                        // and if so, substitute in the actual value.
                        if ($form_submitted && $generated_page_name !== '') {
                            // This line appears to be unnecessary.
                            // $generated_page_name = str_replace('.', '_', $generated_page_name);
                            $generated_page_name = str_replace(' ', '_', $generated_page_name);
                            $escaped_input_name = str_replace(' ', '_', $form_field->getInputName());
                            $generated_page_name = str_ireplace("<{$escaped_input_name}>", $cur_value_in_template, $generated_page_name);
                            // Once the substitution is done, replace underlines back
                            // with spaces.
                            $generated_page_name = str_replace('_', ' ', $generated_page_name);
                        }
                        // Call hooks - unfortunately this has to be split into two
                        // separate calls, because of the different variable names in
                        // each case.
                        if ($form_submitted) {
                            Hooks::run('sfCreateFormField', array(&$form_field, &$cur_value_in_template, true));
                        } else {
                            if (!empty($cur_value) && ($form_field->hasFieldArg('mapping template') || $form_field->hasFieldArg('mapping property') || $form_field->hasFieldArg('mapping cargo table') && $form_field->hasFieldArg('mapping cargo field'))) {
                                $cur_value = SFUtils::valuesToLabels($cur_value, $delimiter, $form_field->getPossibleValues());
                            }
                            Hooks::run('sfCreateFormField', array(&$form_field, &$cur_value, false));
                        }
                        // if this is not part of a 'multiple' template, increment the
                        // global tab index (used for correct tabbing)
                        if (!$form_field->hasFieldArg('part_of_multiple')) {
                            $sfgTabIndex++;
                        }
                        // increment the global field number regardless
                        $sfgFieldNum++;
                        // If the field is a date field, and its default value was set
                        // to 'now', and it has no current value, set $cur_value to be
                        // the current date.
                        if ($form_field->getDefaultValue() == 'now' && ($cur_value == '' || $cur_value == 'now')) {
                            $input_type = $form_field->getInputType();
                            if ($input_type == 'date' || $input_type == 'datetime' || $input_type == 'year' || $input_type == '' && $form_field->getTemplateField()->getPropertyType() == '_dat') {
                                $cur_value_in_template = self::getStringForCurrentTime($input_type == 'datetime', $form_field->hasFieldArg('include timezone'));
                            }
                        }
                        // If the field is a text field, and its default value was set
                        // to 'current user', and it has no current value, set $cur_value
                        // to be the current user.
                        if ($form_field->getDefaultValue() == 'current user' && ($cur_value === '' || $cur_value == 'current user')) {
                            $cur_value_in_template = $wgUser->getName();
                            $cur_value = $cur_value_in_template;
                        }
                        // If all instances have been
                        // printed, that means we're
                        // now printing a "starter"
                        // div - set the current value
                        // to null.
                        // (Ideally it wouldn't get
                        // set at all, but that seems a
                        // little harder.)
                        if ($tif->allInstancesPrinted()) {
                            $cur_value = null;
                        }
                        $new_text = $this->formFieldHTML($form_field, $cur_value);
                        $new_text .= $form_field->additionalHTMLForInput($cur_value, $field_name, $tif->getTemplateName());
                        if ($new_text) {
                            $wiki_page->addTemplateParam($template_name, $tif->getInstanceNum(), $field_name, $cur_value_in_template);
                            $section = substr_replace($section, $new_text, $brackets_loc, $brackets_end_loc + 3 - $brackets_loc);
                        } else {
                            $start_position = $brackets_end_loc;
                        }
                    }
                    // =====================================================
                    // standard input processing
                    // =====================================================
                } elseif ($tag_title == 'standard input') {
                    // handle all the possible values
                    $input_name = $tag_components[1];
                    $input_label = null;
                    $attr = array();
                    // if it's a query, ignore all standard inputs except run query
                    if ($is_query && $input_name != 'run query' || !$is_query && $input_name == 'run query') {
                        $new_text = "";
                        $section = substr_replace($section, $new_text, $brackets_loc, $brackets_end_loc + 3 - $brackets_loc);
                        continue;
                    }
                    // set a flag so that the standard 'form bottom' won't get displayed
                    $this->standardInputsIncluded = true;
                    // cycle through the other components
                    $is_checked = false;
                    for ($i = 2; $i < count($tag_components); $i++) {
                        $component = $tag_components[$i];
                        $sub_components = array_map('trim', explode('=', $component));
                        if (count($sub_components) == 1) {
                            if ($sub_components[0] == 'checked') {
                                $is_checked = true;
                            }
                        } elseif (count($sub_components) == 2) {
                            switch ($sub_components[0]) {
                                case 'label':
                                    $input_label = $wgParser->recursiveTagParse($sub_components[1]);
                                    break;
                                case 'class':
                                case 'style':
                                    $attr[$sub_components[0]] = $sub_components[1];
                                    break;
                            }
                        }
                    }
                    if ($input_name == 'summary') {
                        $value = $wgRequest->getVal('wpSummary');
                        $new_text = SFFormUtils::summaryInputHTML($form_is_disabled, $input_label, $attr, $value);
                    } elseif ($input_name == 'minor edit') {
                        $is_checked = $wgRequest->getCheck('wpMinoredit');
                        $new_text = SFFormUtils::minorEditInputHTML($form_submitted, $form_is_disabled, $is_checked, $input_label, $attr);
                    } elseif ($input_name == 'watch') {
                        $is_checked = $wgRequest->getCheck('wpWatchthis');
                        $new_text = SFFormUtils::watchInputHTML($form_submitted, $form_is_disabled, $is_checked, $input_label, $attr);
                    } elseif ($input_name == 'save') {
                        $new_text = SFFormUtils::saveButtonHTML($form_is_disabled, $input_label, $attr);
                    } elseif ($input_name == 'save and continue') {
                        $new_text = SFFormUtils::saveAndContinueButtonHTML($form_is_disabled, $input_label, $attr);
                    } elseif ($input_name == 'preview') {
                        $new_text = SFFormUtils::showPreviewButtonHTML($form_is_disabled, $input_label, $attr);
                    } elseif ($input_name == 'changes') {
                        $new_text = SFFormUtils::showChangesButtonHTML($form_is_disabled, $input_label, $attr);
                    } elseif ($input_name == 'cancel') {
                        $new_text = SFFormUtils::cancelLinkHTML($form_is_disabled, $input_label, $attr);
                    } elseif ($input_name == 'run query') {
                        $new_text = SFFormUtils::runQueryButtonHTML($form_is_disabled, $input_label, $attr);
                    }
                    $section = substr_replace($section, $new_text, $brackets_loc, $brackets_end_loc + 3 - $brackets_loc);
                    // =====================================================
                    // for section processing
                    // =====================================================
                } elseif ($tag_title == 'section') {
                    $section_name = trim($tag_components[1]);
                    $page_section_in_form = SFPageSection::newFromFormTag($tag_components);
                    // Split the existing page contents into the textareas in the form.
                    $default_value = "";
                    $section_start_loc = 0;
                    if ($source_is_page && $existing_page_content !== null) {
                        // For the last section of the page, there is no trailing newline in
                        // $existing_page_content, but the code below expects it. This code
                        // ensures that there is always trailing newline. T72202
                        if (substr($existing_page_content, -1) !== "\n") {
                            $existing_page_content .= "\n";
                        }
                        $equalsSigns = str_pad('', $page_section_in_form->getSectionLevel(), '=');
                        $searchStr = '/^' . preg_quote($equalsSigns, '/') . '[ ]*?' . preg_quote($section_name, '/') . '[ ]*?' . preg_quote($equalsSigns, '/') . '$/m';
                        if (preg_match($searchStr, $existing_page_content, $matches, PREG_OFFSET_CAPTURE)) {
                            $section_start_loc = $matches[0][1];
                            $header_text = $matches[0][0];
                            $existing_page_content = str_replace($header_text, '', $existing_page_content);
                        } else {
                            $section_start_loc = 0;
                        }
                        $section_end_loc = -1;
                        // get the position of the next template or section defined in the form
                        $next_section_start_loc = strpos($section, '{{{', $brackets_end_loc);
                        if ($next_section_start_loc == false) {
                            $section_end_loc = strpos($existing_page_content, '{{', $section_start_loc);
                        } else {
                            $next_section_end_loc = strpos($section, '}}}', $next_section_start_loc);
                            $bracketed_string_next_section = substr($section, $next_section_start_loc + 3, $next_section_end_loc - ($next_section_start_loc + 3));
                            $tag_components_next_section = SFUtils::getFormTagComponents($bracketed_string_next_section);
                            $tag_title_next_section = trim($tag_components_next_section[0]);
                            if ($tag_title_next_section == 'section') {
                                if (preg_match('/(^={1,6}[ ]*?' . $tag_components_next_section[1] . '[ ]*?={1,6}\\s*?$)/m', $existing_page_content, $matches, PREG_OFFSET_CAPTURE)) {
                                    $section_end_loc = $matches[0][1];
                                }
                            }
                        }
                        if ($section_end_loc === -1) {
                            $section_text = $existing_page_content;
                            $existing_page_content = '';
                        } else {
                            $section_text = substr($existing_page_content, $section_start_loc, $section_end_loc - $section_start_loc);
                            $existing_page_content = substr($existing_page_content, $section_end_loc);
                        }
                    }
                    // If input is from the form.
                    if (!$source_is_page && $wgRequest) {
                        $text_per_section = $wgRequest->getArray('_section');
                        $section_text = $text_per_section[trim($section_name)];
                        $wiki_page->addSection($section_name, $page_section_in_form->getSectionLevel(), $section_text);
                    }
                    $section_text = trim($section_text);
                    // Set input name for query string.
                    $input_name = '_section' . '[' . trim($section_name) . ']';
                    $other_args = $page_section_in_form->getSectionArgs();
                    $other_args['isSection'] = true;
                    if ($page_section_in_form->isMandatory()) {
                        $other_args['mandatory'] = true;
                    }
                    if ($page_section_in_form->isHidden()) {
                        $form_section_text = Html::hidden($input_name, $section_text);
                    } else {
                        $form_section_text = SFTextAreaInput::getHTML($section_text, $input_name, false, $form_is_disabled || $page_section_in_form->isRestricted(), $other_args);
                    }
                    $section = substr_replace($section, $form_section_text, $brackets_loc, $brackets_end_loc + 3 - $brackets_loc);
                    // =====================================================
                    // page info processing
                    // =====================================================
                } elseif ($tag_title == 'info') {
                    // TODO: Generate an error message if this is included more than once
                    foreach (array_slice($tag_components, 1) as $component) {
                        $sub_components = array_map('trim', explode('=', $component, 2));
                        // Tag names are case-insensitive
                        $tag = strtolower($sub_components[0]);
                        if ($tag == 'create title' || $tag == 'add title') {
                            // Handle this only if
                            // we're adding a page.
                            if (!$is_query && !$this->mPageTitle->exists()) {
                                $form_page_title = $sub_components[1];
                            }
                        } elseif ($tag == 'edit title') {
                            // Handle this only if
                            // we're editing a page.
                            if (!$is_query && $this->mPageTitle->exists()) {
                                $form_page_title = $sub_components[1];
                            }
                        } elseif ($tag == 'query title') {
                            // Handle this only if
                            // we're in 'RunQuery'.
                            if ($is_query) {
                                $form_page_title = $sub_components[1];
                            }
                        } elseif ($tag == 'partial form') {
                            $form_is_partial = true;
                            // replacement pages may have minimal matches...
                            $source_page_matches_this_form = true;
                        } elseif ($tag == 'includeonly free text' || $tag == 'onlyinclude free text') {
                            $wiki_page->makeFreeTextOnlyInclude();
                        } elseif ($tag == 'query form at top') {
                            // TODO - this should be made a field of
                            // some non-static class that actually
                            // prints the form, instead of requiring
                            // a global variable.
                            global $sfgRunQueryFormAtTop;
                            $sfgRunQueryFormAtTop = true;
                        }
                    }
                    $section = substr_replace($section, '', $brackets_loc, $brackets_end_loc + 3 - $brackets_loc);
                    // =====================================================
                    // default outer level processing
                    // =====================================================
                } else {
                    // Tag is not one of the three allowed values -
                    // ignore the tag.
                    $start_position = $brackets_end_loc;
                }
                // end if
            }
            // end while
            if ($tif && (!$tif->allowsMultiple() || $tif->allInstancesPrinted())) {
                $template_text = $wiki_page->createTemplateCallsForTemplateName($tif->getTemplateName());
                // If there is a placeholder in the text, we
                // know that we are doing a replace.
                if ($existing_page_content && strpos($existing_page_content, '{{{insertionpoint}}}', 0) !== false) {
                    $existing_page_content = preg_replace('/\\{\\{\\{insertionpoint\\}\\}\\}(\\r?\\n?)/', preg_replace('/\\}\\}/m', '}�', preg_replace('/\\{\\{/m', '�{', $template_text)) . "\n{{{insertionpoint}}}", $existing_page_content);
                    // Otherwise, if it's a partial form, we have to add the new
                    // text somewhere.
                } elseif ($form_is_partial && $wgRequest->getCheck('partial')) {
                    $existing_page_content = preg_replace('/\\}\\}/m', '}�', preg_replace('/\\{\\{/m', '�{', $template_text)) . "{{{insertionpoint}}}" . $existing_page_content;
                }
            }
            if ($tif && $tif->allowsMultiple()) {
                if ($tif->getInstanceNum() == 0) {
                    $multipleTemplateHTML = $this->multipleTemplateStartHTML($tif);
                } else {
                    $multipleTemplateHTML = '';
                }
                if (!$tif->allInstancesPrinted()) {
                    $multipleTemplateHTML .= $this->multipleTemplateInstanceHTML($tif, $form_is_disabled, $section);
                } else {
                    $multipleTemplateHTML .= $this->multipleTemplateEndHTML($tif, $form_is_disabled, $section);
                }
                $placeholder = $tif->getPlaceholder();
                if ($placeholder != null) {
                    $multipleTemplateHTML .= self::makePlaceholderInFormHTML($placeholder);
                }
                if ($tif->allInstancesPrinted() && $tif->getLabel() != null) {
                    $multipleTemplateHTML .= "</fieldset>\n";
                }
                if ($placeholder == null) {
                    // The normal process.
                    $form_text .= $multipleTemplateHTML;
                } else {
                    // The template text won't be appended
                    // at the end of the template like for
                    // usual multiple template forms.
                    // The HTML text will instead be stored in
                    // the $multipleTemplateHTML variable,
                    // and then added in the right
                    // @insertHTML_".$placeHolderField."@"; position
                    // Optimization: actually, instead of
                    // separating the processes, the usual
                    // multiple template forms could also be
                    // handled this way if a fitting
                    // placeholder tag was added.
                    // We replace the HTML into the current
                    // placeholder tag, but also add another
                    // placeholder tag, to keep track of it.
                    $form_text = str_replace(self::makePlaceholderInFormHTML($placeholder), $multipleTemplateHTML, $form_text);
                }
                if (!$tif->allInstancesPrinted()) {
                    // This will cause the section to be
                    // re-parsed on the next go.
                    $section_num--;
                    $tif->incrementInstanceNum();
                }
            } else {
                $form_text .= $section;
            }
        }
        // end for
        // Cleanup - everything has been browsed.
        // Remove all the remaining placeholder
        // tags in the HTML and wiki-text.
        foreach ($placeholderFields as $stringToReplace) {
            // Remove the @<insertHTML>@ tags from the generated
            // HTML form.
            $form_text = str_replace(self::makePlaceholderInFormHTML($stringToReplace), '', $form_text);
        }
        // If it wasn't included in the form definition, add the
        // 'free text' input as a hidden field at the bottom.
        if (!$free_text_was_included) {
            $form_text .= Html::hidden('sf_free_text', '!free_text!');
        }
        // Get free text, and add to page data, as well as retroactively
        // inserting it into the form.
        // If $form_is_partial is true then either:
        // (a) we're processing a replacement (param 'partial' == 1)
        // (b) we're sending out something to be replaced (param 'partial' is missing)
        if ($form_is_partial) {
            if (!$wgRequest->getCheck('partial')) {
                $free_text = $original_page_content;
            } else {
                $free_text = null;
                $existing_page_content = preg_replace(array('/�\\{/m', '/\\}�/m'), array('{{', '}}'), $existing_page_content);
                $existing_page_content = str_replace('{{{insertionpoint}}}', '', $existing_page_content);
            }
            $form_text .= Html::hidden('partial', 1);
        } elseif ($source_is_page) {
            // If the page is the source, free_text will just be
            // whatever in the page hasn't already been inserted
            // into the form.
            $free_text = trim($existing_page_content);
            // or get it from a form submission
        } elseif ($wgRequest->getCheck('sf_free_text')) {
            $free_text = $wgRequest->getVal('sf_free_text');
            if (!$free_text_was_included) {
                $wiki_page->addFreeTextSection();
            }
        } else {
            $free_text = null;
        }
        if ($wiki_page->freeTextOnlyInclude()) {
            $free_text = str_replace("<onlyinclude>", '', $free_text);
            $free_text = str_replace("</onlyinclude>", '', $free_text);
            $free_text = trim($free_text);
        }
        $page_text = '';
        // The first hook here is deprecated. Use the second.
        // Note: Hooks::run can take a third argument which indicates
        // a deprecated hook, but it expects a MediaWiki version, not
        // an extension version.
        Hooks::run('sfModifyFreeTextField', array(&$free_text, $existing_page_content));
        Hooks::run('sfBeforeFreeTextSubstitution', array(&$free_text, $existing_page_content, &$page_text));
        // Now that we have it, add free text to the page, and
        // substitute it into the form.
        if ($form_submitted) {
            $wiki_page->setFreeText($free_text);
            $page_text = $wiki_page->createPageText();
        }
        $escaped_free_text = Sanitizer::safeEncodeAttribute($free_text);
        $form_text = str_replace('!free_text!', $escaped_free_text, $form_text);
        // Add a warning in, if we're editing an existing page and that
        // page appears to not have been created with this form.
        if (!$is_query && is_null($page_name_formula) && $this->mPageTitle->exists() && $existing_page_content !== '' && !$source_page_matches_this_form) {
            $form_text = "\t" . '<div class="warningbox">' . wfMessage('sf_formedit_formwarning', $this->mPageTitle->getFullURL())->text() . "</div>\n<br clear=\"both\" />\n" . $form_text;
        }
        // Add form bottom, if no custom "standard inputs" have been defined.
        if (!$this->standardInputsIncluded) {
            if ($is_query) {
                $form_text .= SFFormUtils::queryFormBottom($form_is_disabled);
            } else {
                $form_text .= SFFormUtils::formBottom($form_submitted, $form_is_disabled);
            }
        }
        if (!$is_query) {
            $form_text .= Html::hidden('wpStarttime', wfTimestampNow());
            $article = new Article($this->mPageTitle, 0);
            $form_text .= Html::hidden('wpEdittime', $article->getTimestamp());
            $form_text .= Html::hidden('wpEditToken', $wgUser->getEditToken());
        }
        $form_text .= "\t</form>\n";
        $wgParser->replaceLinkHolders($form_text);
        Hooks::run('sfRenderingEnd', array(&$form_text));
        // Add general Javascript code.
        $javascript_text = "";
        Hooks::run('sfAddJavascriptToForm', array(&$javascript_text));
        // Send the autocomplete values to the browser, along with the
        // mappings of which values should apply to which fields.
        // If doing a replace, the page text is actually the modified
        // original page.
        if ($wgRequest->getCheck('partial')) {
            $page_text = $existing_page_content;
        }
        if (!$is_embedded) {
            $form_page_title = $wgParser->recursiveTagParse(str_replace("{{!}}", "|", $form_page_title));
        } else {
            $form_page_title = null;
        }
        // If the form has already been submitted, i.e. this is just
        // the redirect page, get rid of all the Javascript, to avoid
        // JS errors.
        if ($form_submitted) {
            $javascript_text = '';
        }
        //		$wgParser = $oldParser;
        return array($form_text, $javascript_text, $page_text, $form_page_title, $generated_page_name);
    }
    /**
     * Show the special page.
     *
     * @param $par Mixed: parameter passed to the special page or null
     */
    public function execute($par)
    {
        global $wgRequest, $wgOut, $wgUser;
        if (wfReadOnly()) {
            $wgOut->readOnlyPage();
            return;
        }
        $this->setHeaders();
        if ($wgRequest->wasPosted()) {
            // 1. Retrieve POST vars. First, we want "crOrigTitle", holding the
            // title of the page we're writing to, and "crRedirectTitle",
            // holding the title of the page we're redirecting to.
            $crOrigTitle = $wgRequest->getText('crOrigTitle');
            $crRedirectTitle = $wgRequest->getText('crRedirectTitle');
            // 2. We need to construct a "FauxRequest", or fake a request that
            // MediaWiki would otherwise get naturally by a client browser to
            // do whatever it has to do. Let's put together the params.
            $title = $crOrigTitle;
            // a. We know our title, so we can instantiate a "Title" and
            // "Article" object. We don't actually plug this into the
            // FauxRequest, but they're required for the writing process,
            // and they contain important information on the article in
            // question that's being edited.
            $crEditTitle = Title::newFromText($crOrigTitle);
            // First, construct "Title". "Article" relies on the former object being set.
            $crEditArticle = new Article($crEditTitle, 0);
            // Then, construct "Article". This is where most of the article's information is.
            $wpStarttime = wfTimestampNow();
            // POST var "wpStarttime" stores when the edit was started.
            $wpEdittime = $crEditArticle->getTimestamp();
            // POST var "wpEdittime" stores when the article was ''last edited''. This is used to check against edit conflicts, and also why we needed to construct "Article" so early. "Article" contains the article's last edittime.
            $wpTextbox1 = "#REDIRECT [[{$crRedirectTitle}]]\r\n";
            // POST var "wpTextbox1" stores the content that's actually going to be written. This is where we write the #REDIRECT [[Article]] stuff. We plug in $crRedirectTitle here.
            $wpSave = 1;
            $wpMinoredit = 1;
            // TODO: Decide on this; should this really be marked and hardcoded as a minor edit, or not? Or should we provide an option? --Digi 11/4/07
            $wpEditToken = htmlspecialchars($wgUser->editToken());
            // 3. Put together the params that we'll use in "FauxRequest" into a single array.
            $crRequestParams = array('title' => $title, 'wpStarttime' => $wpStarttime, 'wpEdittime' => $wpEdittime, 'wpTextbox1' => $wpTextbox1, 'wpSave' => $wpSave, 'wpMinoredit' => $wpMinoredit, 'wpEditToken' => $wpEditToken);
            // 4. Construct "FauxRequest"! Using a FauxRequest object allows
            // for a transparent interface of generated request params that
            // aren't retrieved from the client itself (i.e. $_REQUEST).
            // It's a very useful tool.
            $crRequest = new FauxRequest($crRequestParams, true);
            // 5. Construct "EditPage", which contains routines to write all
            // the data. This is where all the magic happens.
            $crEdit = new EditPage($crEditArticle);
            // We plug in the "Article" object here so EditPage can center on the article that we need to edit.
            // a. We have to plug in the correct information that we just
            // generated. While we fed EditPage with the correct "Article"
            // object, it doesn't have the correct "Title" object.
            // The "Title" object actually points to Special:CreateRedirect,
            // which don't do us any good. Instead, explicitly plug in the
            // correct objects; the objects "Article" and "Title" that we
            // generated earlier. This will center EditPage on the correct article.
            $crEdit->mArticle = $crEditArticle;
            $crEdit->mTitle = $crEditTitle;
            // b. Then import the "form data" (or the FauxRequest object that
            // we just constructed). EditPage now has all the information we
            // generated.
            $crEdit->importFormData($crRequest);
            $permErrors = $crEditTitle->getUserPermissionsErrors('edit', $wgUser);
            // Can this title be created?
            if (!$crEditTitle->exists()) {
                $permErrors = array_merge($permErrors, wfArrayDiff2($crEditTitle->getUserPermissionsErrors('create', $wgUser), $permErrors));
            }
            if ($permErrors) {
                wfDebug(__METHOD__ . ": User can't edit\n");
                $wgOut->addWikiText($crEdit->formatPermissionsErrorMessage($permErrors, 'edit'));
                wfProfileOut(__METHOD__);
                return;
            }
            $resultDetails = false;
            $status = $crEdit->internalAttemptSave($resultDetails, $wgUser->isAllowed('bot') && $wgRequest->getBool('bot', true));
            $value = $status->value;
            if ($value == EditPage::AS_SUCCESS_UPDATE || $value == EditPage::AS_SUCCESS_NEW_ARTICLE) {
                $wgOut->wrapWikiMsg("<div class=\"mw-createredirect-done\">\n\$1</div>", array('createredirect-redirect-done', $crOrigTitle, $crRedirectTitle));
            }
            switch ($value) {
                case EditPage::AS_SPAM_ERROR:
                    $crEdit->spamPageWithContent($resultDetails['spam']);
                    return;
                case EditPage::AS_BLOCKED_PAGE_FOR_USER:
                    $crEdit->blockedPage();
                    return;
                case EditPage::AS_READ_ONLY_PAGE_ANON:
                    $crEdit->userNotLoggedInPage();
                    return;
                case EditPage::AS_READ_ONLY_PAGE_LOGGED:
                case EditPage::AS_READ_ONLY_PAGE:
                    $wgOut->readOnlyPage();
                    return;
                case EditPage::AS_RATE_LIMITED:
                    $wgOut->rateLimited();
                    break;
                case EditPage::AS_NO_CREATE_PERMISSION:
                    $crEdit->noCreatePermission();
                    return;
            }
            $wgOut->mRedirect = '';
            $wgOut->mRedirectCode = '';
            // TODO: Implement error handling (i.e. "Edit conflict!" or "You don't have permissions to edit this page!") --Digi 11/4/07
        }
        $action = htmlspecialchars($this->getTitle()->getLocalURL());
        // Also retrieve "crTitle". If this GET var is found, we autofill the
        // "Redirect to:" field with that text.
        $crTitle = $wgRequest->getText('crRedirectTitle', $wgRequest->getText('crTitle', $par));
        $crTitle = Title::newFromText($crTitle);
        $crTitle = htmlspecialchars(isset($crTitle) ? $crTitle->getPrefixedText() : '');
        $msgPageTitle = wfMsgHtml('createredirect-page-title');
        $msgRedirectTo = wfMsgHtml('createredirect-redirect-to');
        $msgSave = wfMsgHtml('createredirect-save');
        // 2. Start rendering the output! The output is entirely the form.
        // It's all HTML, and may be self-explanatory.
        $wgOut->addHTML(wfMsgHtml('createredirect-instructions'));
        $wgOut->addHTML(<<<END
<form id="redirectform" name="redirectform" method="post" action="{$action}">
<table>
<tr>
<td><label for="crOrigTitle">{$msgPageTitle}</label></td>
<td><input type="text" name="crOrigTitle" id="crOrigTitle" size="60" tabindex="1" /></td>
</tr>
<tr>
<td><label for="crRedirectTitle">{$msgRedirectTo}</label></td>
<td><input type="text" name="crRedirectTitle" id="crRedirectTitle" value="{$crTitle}" size="60" tabindex="2" /></td>
</tr>
<tr>
<td></td>
<td><input type="submit" name="crWrite" id="crWrite" value="{$msgSave}" tabindex="4" /></td>
</tr>
</table>
</form>
END
);
    }