/** * Executes special page rendering and data processing * * @param $sub Mixed: MediaWiki supplied sub-page path * @throws PermissionsError */ public function execute($sub) { $out = $this->getOutput(); $user = $this->getUser(); $request = $this->getRequest(); // Begin output $this->setHeaders(); // Make sure the user is logged in if (!$user->isLoggedIn()) { throw new PermissionsError('read'); } // Handle discarding $draft = Draft::newFromID($request->getIntOrNull('discard')); if ($draft->exists()) { // Discard draft $draft->discard(); // Redirect to the article editor or view if returnto was set $section = $request->getIntOrNull('section'); $urlSection = $section !== null ? "§ion={$section}" : ''; switch ($request->getText('returnto')) { case 'edit': $title = Title::newFromDBKey($draft->getTitle()); $out->redirect(wfExpandURL($title->getEditURL() . $urlSection)); break; case 'view': $title = Title::newFromDBKey($draft->getTitle()); $out->redirect(wfExpandURL($title->getFullURL() . $urlSection)); break; } } // Show list of drafts, or a message that there are none if (Drafts::display() == 0) { $out->addWikiMsg('drafts-view-nonesaved'); } }
public function execute() { if ($this->getUser()->isAnon()) { $this->dieUsage('You must be logged in to save drafts.', 'notloggedin'); } $params = $this->extractRequestParams(); $draft = Draft::newFromID($params['id']); $draft->setToken($params['drafttoken']); $draft->setTitle(Title::newFromText($params['title'])); $draft->setSection($params['section'] == '' ? null : $params['section']); $draft->setStartTime($params['starttime']); $draft->setEditTime($params['edittime']); $draft->setSaveTime(wfTimestampNow()); $draft->setScrollTop($params['scrolltop']); $draft->setText($params['text']); $draft->setSummary($params['summary']); $draft->setMinorEdit($params['minoredit']); $draft->save(); $this->getResult()->addValue(null, $this->getModuleName(), array('id' => $draft->getID())); }
/** * Executes special page rendering and data processing * * @param $sub Mixed: MediaWiki supplied sub-page path */ public function execute($sub) { global $wgRequest, $wgOut, $wgUser; // Begin output $this->setHeaders(); // Make sure the user is logged in if (!$wgUser->isLoggedIn()) { // If not, let them know they need to $wgOut->loginToUse(); // Continue return true; } // Handle discarding $draft = Draft::newFromID($wgRequest->getIntOrNull('discard')); if ($draft->exists()) { // Discard draft $draft->discard(); // Redirect to the article editor or view if returnto was set $section = $wgRequest->getIntOrNull('section'); $urlSection = $section !== null ? "§ion={$section}" : ''; switch ($wgRequest->getText('returnto')) { case 'edit': $title = Title::newFromDBKey($draft->getTitle()); $wgOut->redirect(wfExpandURL($title->getEditURL() . $urlSection)); break; case 'view': $title = Title::newFromDBKey($draft->getTitle()); $wgOut->redirect(wfExpandURL($title->getFullURL() . $urlSection)); break; } } // Show list of drafts, or a message that there are none if (Drafts::display() == 0) { $wgOut->addHTML(wfMsgHTML('drafts-view-nonesaved')); } }
public static function listDrafts(&$title = null, $user = null) { global $wgOut, $wgRequest, $wgUser, $wgLang; //added twice? $wgOut->addScript('<style type="text/css" media="all">/*<![CDATA[*/ @import "' . wfGetPad('/extensions/min/f/extensions/Drafts/Drafts.css?rev=') . WH_SITEREV . '"; /*]]>*/</style>'); // Get draftID $currentDraft = Draft::newFromID($wgRequest->getIntOrNull('draft')); //based on user preference $adv = $wgUser->getOption('defaulteditor', '') == 'advanced' ? '&advanced=true' : ''; // Output HTML for list of drafts $drafts = Draft::getDrafts($title, $user); if (count($drafts) > 0) { global $egDraftsLifeSpan; // Internationalization wfLoadExtensionMessages('Drafts'); // Add a summary, on Special:Drafts only if (!$title || $title->getNamespace() == NS_SPECIAL) { $wgOut->wrapWikiMsg('<div class="mw-drafts-summary">$1</div>', array('drafts-view-summary', $wgLang->formatNum($egDraftsLifeSpan))); } // Build XML $wgOut->addHTML(Xml::openElement('table', array('cellpadding' => 5, 'cellspacing' => 0, 'border' => 0, 'id' => 'drafts-list-table', 'class' => 'section_text', 'style' => 'margin-top:15px'))); $wgOut->addHTML(Xml::openElement('tr')); $wgOut->addHTML(Xml::element('th', array('align' => 'left', 'nowrap' => 'nowrap', 'style' => 'text-align:center;'), wfMsg('drafts-view-article'))); $wgOut->addHTML(Xml::element('th', array('align' => 'left', 'nowrap' => 'nowrap', 'style' => 'text-align:center;'), wfMsg('drafts-view-saved'))); $wgOut->addHTML(Xml::element('th', array(), wfMsg('edit'))); $wgOut->addHTML(Xml::element('th', array(), wfMsg('discard'))); $wgOut->addHTML(Xml::closeElement('tr')); // Add existing drafts for this page and user $index = 0; foreach ($drafts as $draft) { // Get article title text $htmlTitle = $draft->getTitle()->getEscapedText(); // Build Article Load link if ($draft->getHTML5()) { $params = 'h5e=true&draft=' . urlencode($draft->getID()); if ($draft->getTitle()->getArticleID() == 0) { $params .= "&create-new-article=true"; } $urlLoad = $draft->getTitle()->getFullUrl($params); } else { $urlLoad = $draft->getTitle()->getFullUrl('action=edit' . $adv . '&draft=' . urlencode($draft->getID())); } // Build discard link $urlDiscard = sprintf('%s?discard=%s&token=%s', SpecialPage::getTitleFor('Drafts')->getFullUrl(), urlencode($draft->getID()), urlencode($wgUser->editToken())); // If in edit mode, return to editor if ($wgRequest->getText('action') == 'edit' || $wgRequest->getText('action') == 'submit') { $urlDiscard .= '&returnto=' . urlencode('edit'); } // Append section to titles and links if ($draft->getSection() !== null) { // Detect section name $lines = explode("\n", $draft->getText()); // If there is any content in the section if (count($lines) > 0) { $htmlTitle .= '#' . htmlspecialchars(trim(trim(substr($lines[0], 0, 255), '='))); } // Modify article link and title $urlLoad .= '§ion=' . urlencode($draft->getSection()); $urlDiscard .= '§ion=' . urlencode($draft->getSection()); } // Build XML if ($index % 2 == 1) { $wgOut->addHTML(Xml::openElement('tr', array('style' => 'background: #eee;'))); } else { $wgOut->addHTML(Xml::openElement('tr', array('style' => ''))); } $wgOut->addHTML(Xml::openElement('td', array('align' => 'left', 'class' => 'draftpage'))); $wgOut->addHTML(Xml::element('a', array('href' => $urlLoad, 'style' => 'font-weight:' . ($currentDraft->getID() == $draft->getID() ? 'bold' : 'normal')), $htmlTitle)); $wgOut->addHTML(Xml::closeElement('td')); $wgOut->addHTML(Xml::element('td', array('align' => 'left', 'nowrap' => 'nowrap', 'class' => 'draftsaved'), $wgLang->timeanddate($draft->getSaveTime(), true))); // edit link $wgOut->addHTML(Xml::openElement('td', array('align' => 'left', 'nowrap' => 'nowrap', 'class' => 'draftedit'))); $wgOut->addHTML(Xml::element('a', array('href' => $urlLoad), wfMsg('edit'))); $wgOut->addHTML(Xml::closeElement('td')); $wgOut->addHTML(Xml::openElement('td', array('align' => 'left', 'nowrap' => 'nowrap', 'class' => 'draftdiscard'))); $wgOut->addHTML(Xml::element('a', array('href' => $urlDiscard, 'onclick' => "if( true || !wgAjaxSaveDraft.insync ) return confirm('" . Xml::escapeJsString(wfMsgHTML('drafts-discard-warn', $draft->getTitle()->getText())) . "')"), wfMsg('drafts-view-discard'))); $wgOut->addHTML(Xml::closeElement('td')); $wgOut->addHTML(Xml::closeElement('tr')); $index++; } $wgOut->addHTML(Xml::closeElement('table')); // Return number of drafts return count($drafts); } return 0; }
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; }
/** * Outputs a table of existing drafts * * @param $title Object: [optional] Title of article, defaults to all articles * @param $userID Integer: [optional] ID of user, defaults to current user * @return Number of drafts in the table */ public static function display($title = null, $userID = null) { global $wgOut, $wgRequest, $wgUser, $wgLang; // Gets draftID $currentDraft = Draft::newFromID($wgRequest->getIntOrNull('draft')); // Output HTML for list of drafts $drafts = Drafts::get($title, $userID); if (count($drafts) > 0) { global $egDraftsLifeSpan; // Internationalization // Add a summary, on Special:Drafts only if (!$title || $title->getNamespace() == NS_SPECIAL) { $wgOut->wrapWikiMsg('<div class="mw-drafts-summary">$1</div>', array('drafts-view-summary', $wgLang->formatNum($egDraftsLifeSpan))); } // Build XML $wgOut->addHTML(Xml::openElement('table', array('cellpadding' => 5, 'cellspacing' => 0, 'width' => '100%', 'border' => 0, 'id' => 'drafts-list-table'))); $wgOut->addHTML(Xml::openElement('tr')); $wgOut->addHTML(Xml::element('th', array('width' => '75%', 'nowrap' => 'nowrap'), wfMsg('drafts-view-article'))); $wgOut->addHTML(Xml::element('th', null, wfMsg('drafts-view-saved'))); $wgOut->addHTML(Xml::element('th')); $wgOut->addHTML(Xml::closeElement('tr')); // Add existing drafts for this page and user foreach ($drafts as $draft) { // Get article title text $htmlTitle = $draft->getTitle()->getEscapedText(); // Build Article Load link $urlLoad = $draft->getTitle()->getFullURL('action=edit&draft=' . urlencode($draft->getID())); // Build discard link $urlDiscard = SpecialPage::getTitleFor('Drafts')->getFullURL(sprintf('discard=%s&token=%s', urlencode($draft->getID()), urlencode($wgUser->editToken()))); // If in edit mode, return to editor if ($wgRequest->getText('action') == 'edit' || $wgRequest->getText('action') == 'submit') { $urlDiscard .= '&returnto=' . urlencode('edit'); } // Append section to titles and links if ($draft->getSection() !== null) { // Detect section name $lines = explode("\n", $draft->getText()); // If there is any content in the section if (count($lines) > 0) { $htmlTitle .= '#' . htmlspecialchars(trim(trim(substr($lines[0], 0, 255), '='))); } // Modify article link and title $urlLoad .= '§ion=' . urlencode($draft->getSection()); $urlDiscard .= '§ion=' . urlencode($draft->getSection()); } // Build XML $wgOut->addHTML(Xml::openElement('tr')); $wgOut->addHTML(Xml::openElement('td')); $wgOut->addHTML(Xml::element('a', array('href' => $urlLoad, 'style' => 'font-weight:' . ($currentDraft->getID() == $draft->getID() ? 'bold' : 'normal')), $htmlTitle)); $wgOut->addHTML(Xml::closeElement('td')); $wgOut->addHTML(Xml::element('td', null, $wgLang->timeanddate($draft->getSaveTime(), true))); $wgOut->addHTML(Xml::openElement('td')); $jsClick = "if( wgDraft.getState() !== 'unchanged' )" . "return confirm('" . Xml::escapeJsString(wfMsgHTML('drafts-view-warn')) . "')"; $wgOut->addHTML(Xml::element('a', array('href' => $urlDiscard, 'onclick' => $jsClick), wfMsg('drafts-view-discard'))); $wgOut->addHTML(Xml::closeElement('td')); $wgOut->addHTML(Xml::closeElement('tr')); } $wgOut->addHTML(Xml::closeElement('table')); // Return number of drafts return count($drafts); } return 0; }
/** * AJAX function export DraftHooks::AjaxSave * Respond to ajax queries */ public static function AjaxSave($dtoken, $etoken, $id, $title, $section, $starttime, $edittime, $scrolltop, $text, $summary, $minoredit) { global $wgUser, $wgRequest; // Verify token if ($wgUser->editToken() == $etoken) { // Create Draft $draft = Draft::newFromID($id); // Load draft with info $draft->setToken($dtoken); $draft->setTitle(Title::newFromText($title)); $draft->setSection($section == '' ? null : $section); $draft->setStartTime($starttime); $draft->setEditTime($edittime); $draft->setSaveTime(wfTimestampNow()); $draft->setScrollTop($scrolltop); $draft->setText($text); $draft->setSummary($summary); $draft->setMinorEdit($minoredit); // Save draft $draft->save(); // Return draft id to client (used for next save) return (string) $draft->getID(); } else { // Return failure return '-1'; } }
/** * EditPage::showEditForm:initial hook * Load draft... */ public static function loadForm(EditPage $editpage) { global $wgRequest; $context = $editpage->getArticle()->getContext(); $user = $context->getUser(); if (!$user->getOption('extensionDrafts_enable', 'true')) { return true; } //XXCHANGED $isGuidedEditor = isset($editpage->mGuided) && $editpage->mGuided; $adv = $isGuidedEditor ? "" : "&advanced=true"; $wgRequest->setVal("guidededitor", $isGuidedEditor); // Check permissions $request = $context->getRequest(); if ($user->isAllowed('edit') && $user->isLoggedIn()) { // Get draft $draft = Draft::newFromID($request->getIntOrNull('draft')); // Load form values if ($draft->exists()) { // Override initial values in the form with draft data $editpage->textbox1 = $draft->getText(); $editpage->summary = $draft->getSummary(); $editpage->scrolltop = $draft->getScrollTop(); $editpage->minoredit = $draft->getMinorEdit() ? true : false; } // Save draft on non-save submission if ($request->getVal('action') == 'submit' && $user->getEditToken() == $request->getText('wpEditToken') && is_null($request->getText('wpDraftTitle'))) { // If the draft wasn't specified in the url, try using a // form-submitted one if (!$draft->exists()) { $draft = Draft::newFromID($request->getIntOrNull('wpDraftID')); } // Load draft with info $draft->setTitle(Title::newFromText($request->getText('wpDraftTitle'))); $draft->setSection($request->getInt('wpSection')); $draft->setStartTime($request->getText('wpStarttime')); $draft->setEditTime($request->getText('wpEdittime')); $draft->setSaveTime(wfTimestampNow()); $draft->setScrollTop($request->getInt('wpScrolltop')); $draft->setText($request->getText('wpTextbox1')); $draft->setSummary($request->getText('wpSummary')); $draft->setMinorEdit($request->getInt('wpMinoredit', 0)); // Save draft $draft->save(); // Use the new draft id $request->setVal('draft', $draft->getID()); } } $out = $context->getOutput(); $numDrafts = Drafts::num($context->getTitle()); // Show list of drafts if ($numDrafts > 0) { if ($request->getText('action') !== 'submit') { $out->addHTML(Xml::openElement('div', array('id' => 'drafts-list-box', 'class' => 'minor_section'))); $out->addHTML(Xml::element('h3', null, $context->msg('drafts-view-existing')->text())); Drafts::display($context->getTitle()); $out->addHTML(Xml::closeElement('div')); } else { $jsWarn = "if( !wgAjaxSaveDraft.insync ) return confirm('" . Xml::escapeJsString($context->msg('drafts-view-warn')->escaped()) . "')"; $link = Xml::element('a', array('href' => $context->getTitle()->getFullURL('action=edit'), 'onclick' => $jsWarn), $context->msg('drafts-view-notice-link')->numParams($numDrafts)->text()); $out->addHTML($context->msg('drafts-view-notice')->rawParams($link)->escaped()); } } // Continue return true; }