Ejemplo n.º 1
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('&', '%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);
 }
 /**
  * Depending on the requested action this method will try to store/preview
  * the data in mOptions or retrieve the edit form.
  *
  * The form and target page will be available in mOptions after execution of
  * the method.
  *
  * Errors and warnings are logged in the API result under the 'errors' key.
  * The general request status is maintained in mStatus.
  *
  * @global $wgRequest
  * @global $wgOut
  * @global SFFormPrinter $sfgFormPrinter
  * @throws MWException
  */
 public function doAction()
 {
     global $wgOut, $wgParser, $wgRequest, $sfgFormPrinter;
     // if the wiki is read-only, do not save
     if (wfReadOnly()) {
         if ($this->mAction === self::ACTION_SAVE) {
             throw new MWException(wfMessage('sf_autoedit_readonly', wfReadOnlyReason())->parse());
         }
         // even if not saving notify client anyway. Might want to dislay a notice
         $this->logMessage(wfMessage('sf_autoedit_readonly', wfReadOnlyReason())->parse(), self::NOTICE);
     }
     // find the title of the form to be used
     $formTitle = $this->getFormTitle();
     // get the form content
     $formContent = StringUtils::delimiterReplace('<noinclude>', '</noinclude>', '', $this->getTextForPage($formTitle));
     // signals that the form was submitted
     // always true, else we would not be here
     $isFormSubmitted = $this->mAction === self::ACTION_SAVE || $this->mAction === self::ACTION_PREVIEW || $this->mAction === self::ACTION_DIFF;
     // the article id of the form to be used
     $formArticleId = $formTitle->getArticleID();
     // the name of the target page; might be empty when using the one-step-process
     $targetName = $this->mOptions['target'];
     // if the target page was not specified, try finding the page name formula
     // (Why is this not done in SFFormPrinter::formHTML?)
     if ($targetName === '') {
         // Parse the form to see if it has a 'page name' value set.
         if (preg_match('/{{{\\s*info.*page name\\s*=\\s*(.*)}}}/msU', $formContent, $matches)) {
             $pageNameElements = SFUtils::getFormTagComponents(trim($matches[1]));
             $targetNameFormula = $pageNameElements[0];
         } else {
             throw new MWException(wfMessage('sf_autoedit_notargetspecified')->parse());
         }
         $targetTitle = null;
     } else {
         $targetNameFormula = null;
         $targetTitle = Title::newFromText($targetName);
     }
     $preloadContent = '';
     // save $wgRequest for later restoration
     $oldRequest = $wgRequest;
     $pageExists = false;
     // preload data if not explicitly excluded and if the preload page exists
     if (!isset($this->mOptions['preload']) || $this->mOptions['preload'] !== false) {
         if (isset($this->mOptions['preload']) && is_string($this->mOptions['preload'])) {
             $preloadTitle = Title::newFromText($this->mOptions['preload']);
         } else {
             $preloadTitle = Title::newFromText($targetName);
         }
         if ($preloadTitle !== null && $preloadTitle->exists()) {
             // the content of the page that was specified to be used for preloading
             $preloadContent = $this->getTextForPage($preloadTitle);
             $pageExists = true;
         } else {
             if (isset($this->mOptions['preload'])) {
                 $this->logMessage(wfMessage('sf_autoedit_invalidpreloadspecified', $this->mOptions['preload'])->parse(), self::WARNING);
             }
         }
     }
     // Allow extensions to set/change the preload text, for new
     // pages.
     if (!$pageExists) {
         Hooks::run('sfEditFormPreloadText', array(&$preloadContent, $targetTitle, $formTitle));
     }
     // Flag to keep track of formHTML() runs.
     $formHtmlHasRun = false;
     if ($preloadContent !== '') {
         // @HACK - we need to set this for the preload to take
         // effect in the form.
         $pageExists = true;
         // Spoof $wgRequest for SFFormPrinter::formHTML().
         if (isset($_SESSION)) {
             $wgRequest = new FauxRequest($this->mOptions, true, $_SESSION);
         } else {
             $wgRequest = new FauxRequest($this->mOptions, true);
         }
         // Call SFFormPrinter::formHTML() to get at the form
         // HTML of the existing page.
         list($formHTML, $formJS, $targetContent, $form_page_title, $generatedTargetNameFormula) = $sfgFormPrinter->formHTML($formContent, $isFormSubmitted, $pageExists, $formArticleId, $preloadContent, $targetName, $targetNameFormula);
         // Parse the data to be preloaded from the form HTML of
         // the existing page.
         $data = $this->parseDataFromHTMLFrag($formHTML);
         // ...and merge/overwrite it with the new data.
         $this->mOptions = SFUtils::array_merge_recursive_distinct($data, $this->mOptions);
     }
     // We already preloaded stuff for saving/previewing -
     // do not do this again.
     if ($isFormSubmitted && !$wgRequest->getCheck('partial')) {
         $preloadContent = '';
         $pageExists = false;
     } else {
         // Source of the data is a page.
         $pageExists = is_a($targetTitle, 'Title') && $targetTitle->exists();
     }
     // Spoof $wgRequest for SFFormPrinter::formHTML().
     if (isset($_SESSION)) {
         $wgRequest = new FauxRequest($this->mOptions, true, $_SESSION);
     } else {
         $wgRequest = new FauxRequest($this->mOptions, true);
     }
     // get wikitext for submitted data and form
     list($formHTML, $formJS, $targetContent, $generatedFormName, $generatedTargetNameFormula) = $sfgFormPrinter->formHTML($formContent, $isFormSubmitted, $pageExists, $formArticleId, $preloadContent, $targetName, $targetNameFormula);
     // Restore original request.
     $wgRequest = $oldRequest;
     if ($generatedFormName !== '') {
         $formTitle = Title::newFromText($generatedFormName);
         $this->mOptions['formtitle'] = $formTitle->getText();
     }
     $this->mOptions['formHTML'] = $formHTML;
     $this->mOptions['formJS'] = $formJS;
     if ($isFormSubmitted) {
         // If the target page was not specified, see if
         // something was generated from the target name formula.
         if ($this->mOptions['target'] === '') {
             // If no name was generated, we cannot save => give up
             if ($generatedTargetNameFormula === '') {
                 throw new MWException(wfMessage('sf_autoedit_notargetspecified')->parse());
             }
             $this->mOptions['target'] = $this->generateTargetName($generatedTargetNameFormula);
         }
         // Lets other code process additional form-definition syntax
         Hooks::run('sfWritePageData', array($this->mOptions['form'], Title::newFromText($this->mOptions['target']), &$targetContent));
         $editor = $this->setupEditPage($targetContent);
         // Perform the requested action.
         if ($this->mAction === self::ACTION_PREVIEW) {
             $this->doPreview($editor);
         } else {
             if ($this->mAction === self::ACTION_DIFF) {
                 $this->doDiff($editor);
             } else {
                 $this->doStore($editor);
             }
         }
     } else {
         if ($this->mAction === self::ACTION_FORMEDIT) {
             $parserOutput = $wgParser->getOutput();
             if (method_exists($wgOut, 'addParserOutputMetadata')) {
                 $wgOut->addParserOutputMetadata($parserOutput);
             } else {
                 $wgOut->addParserOutputNoText($parserOutput);
             }
             $this->doFormEdit($formHTML, $formJS);
         }
     }
 }
Ejemplo n.º 3
0
 /**
  *	This method will try to store the data in mOptions.
  *
  * It will return true on success or an error message on failure.
  * The used form and target page will be available in mOptions after
  * execution of the method.
  *
  * This method also sets HTTP response headers according to the result.
  *
  * @param bool $prefillFromExisting If this is set, existing values in the page will be used to prefill the form.
  * @return true or an error message
  */
 public function storeSemanticData($prefillFromExisting = true)
 {
     global $wgOut, $wgRequest;
     // If the wiki is read-only we might as well stop right away
     if (wfReadOnly()) {
         return $this->reportError(wfMsg('sf_autoedit_readonly', wfReadOnlyReason()));
     }
     // ensure 'form' key exists
     if (!array_key_exists('form', $this->mOptions)) {
         $this->mOptions['form'] = null;
     }
     // ensure 'target' key exists
     if (!array_key_exists('target', $this->mOptions)) {
         $this->mOptions['target'] = null;
     }
     // If we have no target article and no form we might as well stop right away
     if (!$this->mOptions['target'] && !$this->mOptions['form']) {
         return $this->reportError(wfMsg('sf_autoedit_notargetspecified'));
     }
     // check if form was specified
     if (!$this->mOptions['form']) {
         // If no form was specified, find the default one for
         // this page.
         $title = Title::newFromText($this->mOptions['target']);
         $form_names = SFFormLinker::getDefaultFormsForPage($title);
         // if no form can be found, return
         if (count($form_names) == 0) {
             return $this->reportError(wfMsg('sf_autoedit_noformfound'));
         }
         // if more than one form found, return
         if (count($form_names) > 1) {
             return $this->reportError(wfMsg('sf_autoedit_toomanyformsfound'));
         }
         // There should now be exactly one form.
         $this->mOptions['form'] = $form_names[0];
     }
     // we only care for the form's body
     $wgOut->setArticleBodyOnly(true);
     $formedit = new SFFormEdit();
     $data = array();
     $oldRequest = $wgRequest;
     // Get the form definition and target page (if there is one),
     // as specified in the options string, then create the actual
     // HTML form from them, and call that form to modify or create
     // the page.
     if ($prefillFromExisting) {
         $wgRequest = new FauxRequest($this->mOptions, true);
         // get the Semantic Form
         if ($this->mOptions['target']) {
             $formedit->execute($this->mOptions['form'] . '/' . $this->mOptions['target']);
         } else {
             $formedit->execute($this->mOptions['form']);
         }
         // extract its data
         $form = $this->parseDataFromHTMLFrag($data, trim($wgOut->getHTML()), 'sfForm');
         if (!$form) {
             // something went wrong
             $wgRequest = $oldRequest;
             return $this->reportError(wfMsg('sf_autoedit_nosemanticform', array($this->mOptions['target'], $this->mOptions['form'])));
         }
     } else {
         self::addToArray($data, "wpSave", "Save");
     }
     // and modify as specified
     $data = SFUtils::array_merge_recursive_distinct($data, $this->mOptions);
     ////////////////////////////////////////////////////////////////////////
     // Store the modified form
     // $wgOut->clearHTML();
     $wgRequest = new FauxRequest($data, true);
     // get the MW form
     if ($this->mOptions['target']) {
         $formedit->execute($this->mOptions['form'] . '/' . $this->mOptions['target'], false);
     } else {
         $formedit->execute($this->mOptions['form'], false);
     }
     $this->mOptions['form'] = $formedit->mForm;
     $this->mOptions['target'] = $formedit->mTarget;
     $wgRequest = $oldRequest;
     if ($formedit->mError) {
         return $this->reportError($formedit->mError);
     } else {
         if (!headers_sent()) {
             header("X-Location: " . $wgOut->getRedirect());
             header("X-Form: " . $formedit->mForm);
             header("X-Target: " . $formedit->mTarget);
         }
         if ($this->isApiQuery()) {
             $this->getResult()->addValue(null, 'result', array('code' => '200', 'location' => $wgOut->getRedirect(), 'form' => $formedit->mForm, 'target' => $formedit->mTarget));
         }
     }
     return true;
 }
Ejemplo n.º 4
0
 /**
  * Depending on the requested action this method will try to store/preview
  * the data in mOptions or retrieve the edit form.
  *
  * The form and target page will be available in mOptions after execution of
  * the method.
  *
  * Errors and warnings are logged in the API result under the 'errors' key.
  * The general request status is maintained in mStatus.
  *
  * @global $wgRequest
  * @global $wgOut
  * @global $sfgFormPrinter
  * @throws MWException
  */
 public function doAction()
 {
     global $wgOut, $wgRequest, $sfgFormPrinter;
     // if the wiki is read-only, do not save
     if (wfReadOnly()) {
         if ($this->mAction === self::ACTION_SAVE) {
             throw new MWException(wfMessage('sf_autoedit_readonly', wfReadOnlyReason())->parse());
         }
         // even if not saving notify client anyway. Might want to dislay a notice
         $this->logMessage(wfMessage('sf_autoedit_readonly', wfReadOnlyReason())->parse(), self::NOTICE);
     }
     // find the title of the form to be used
     $formTitle = $this->getFormTitle();
     // get the form content
     $formContent = StringUtils::delimiterReplace('<noinclude>', '</noinclude>', '', WikiPage::factory($formTitle)->getRawText());
     // signals that the form was submitted
     // always true, else we would not be here
     $isFormSubmitted = $this->mAction === self::ACTION_SAVE || $this->mAction === self::ACTION_PREVIEW;
     // the article id of the form to be used
     $formArticleId = $formTitle->getArticleID();
     // source of the data is a page
     $isPageSource = true;
     // the name of the target page; might be empty when using the one-step-process
     $targetName = $this->mOptions['target'];
     // if the target page was not specified, try finding the page name formula
     // (Why is this not done in SFFormPrinter::formHTML?)
     if ($targetName === '') {
         // parse the form to see if it has a 'page name' value set
         if (preg_match('/{{{info.*page name\\s*=\\s*(.*)}}}/m', $formContent, $matches)) {
             $pageNameElements = SFUtils::getFormTagComponents($matches[1]);
             $targetNameFormula = $pageNameElements[0];
         } else {
             throw new MWException(wfMessage('sf_autoedit_notargetspecified')->parse());
         }
         $targetTitle = null;
     } else {
         $targetNameFormula = null;
         $targetTitle = Title::newFromText($targetName);
     }
     $preloadContent = '';
     // save $wgRequest for later restoration
     $oldRequest = $wgRequest;
     // preload data if not explicitly excluded and if the preload page exists
     if (!isset($this->mOptions['preload']) || $this->mOptions['preload'] !== false) {
         if (!isset($this->mOptions['preload']) || $this->mOptions['preload'] === true) {
             $preloadTitle = Title::newFromText($targetName);
         } else {
             $preloadTitle = Title::newFromText($this->mOptions['preload']);
         }
         if ($preloadTitle !== null && $preloadTitle->exists()) {
             // the content of the page that was specified to be used for preloading
             $preloadContent = WikiPage::factory($preloadTitle)->getRawText();
             wfRunHooks('sfEditFormPreloadText', array(&$preloadContent, $targetTitle, $formTitle));
             $isPageSource = true;
             // spoof $wgRequest for SFFormPrinter::formHTML
             $wgRequest = new FauxRequest($this->mOptions, true);
             // save wgOut for later restoration
             $oldOut = $wgOut;
             // spoof wgOut; if we took the general $wgOut some JS modules
             // might attach themselves twice and thus be called twice
             $wgOut = new OutputPage(RequestContext::getMain());
             // call SFFormPrinter::formHTML to get at the form html of the existing page
             list($formHTML, $formJS, $targetContent, $form_page_title, $generatedTargetNameFormula) = $sfgFormPrinter->formHTML($formContent, $isFormSubmitted, $isPageSource, $formArticleId, $preloadContent, $targetName, $targetNameFormula);
             // restore wgOut
             $wgOut = $oldOut;
             // parse the data to be preloaded from the form html of the
             // existing page
             $data = $this->parseDataFromHTMLFrag($formHTML);
             // and merge/overwrite it with the new data
             $this->mOptions = SFUtils::array_merge_recursive_distinct($data, $this->mOptions);
         } else {
             if (isset($this->mOptions['preload'])) {
                 $this->logMessage(wfMessage('sf_autoedit_invalidpreloadspecified', $this->mOptions['preload'])->parse(), self::WARNING);
             }
         }
     }
     // we already preloaded stuff for saving/previewing, do not do it again
     if ($this->mAction === self::ACTION_SAVE || $this->mAction === self::ACTION_PREVIEW) {
         $preloadContent = '';
         $isPageSource = false;
     }
     // spoof wgRequest for SFFormPrinter::formHTML
     $wgRequest = new FauxRequest($this->mOptions, true);
     // get wikitext for submitted data and form
     list($formHTML, $formJS, $targetContent, $generatedFormName, $generatedTargetNameFormula) = $sfgFormPrinter->formHTML($formContent, $isFormSubmitted, $isPageSource, $formArticleId, $preloadContent, $targetName, $targetNameFormula);
     // restore original request
     $wgRequest = $oldRequest;
     if ($generatedFormName !== '') {
         $formTitle = Title::newFromText($generatedFormName);
         $this->mOptions['form'] = $formTitle->getText();
     }
     $this->mOptions['formHTML'] = $formHTML;
     $this->mOptions['formJS'] = $formJS;
     if ($this->mAction === self::ACTION_SAVE || $this->mAction === self::ACTION_PREVIEW) {
         // if the target page was not specified, see if something was generated
         // from the target name formula
         if ($this->mOptions['target'] === '') {
             // if no name was generated, we can not save => give up
             if ($generatedTargetNameFormula === '') {
                 throw new MWException(wfMessage('sf_autoedit_notargetspecified')->parse());
             }
             $this->mOptions['target'] = $this->generateTargetName($generatedTargetNameFormula);
         }
         // Lets other code process additional form-definition syntax
         wfRunHooks('sfWritePageData', array($this->mOptions['form'], Title::newFromText($this->mOptions['target']), &$targetContent));
         $editor = $this->setupEditPage($targetContent);
         // perform the requested action
         if ($this->mAction === self::ACTION_PREVIEW) {
             $this->doPreview($editor);
         } else {
             $this->doStore($editor);
         }
     } else {
         if ($this->mAction === self::ACTION_FORMEDIT) {
             $this->doFormEdit($formHTML, $formJS);
         }
     }
 }