php - Mediawiki stopping a page from saving and redirecting back to edit page with an error message

213

My wiki articles contain a link to a specific dataset. I want to enforce that these links are unique (as in no one can create a new page with a link that is present in another page.) I have already written most of the code for this extension. I created a table 'unique_external_links' that stores the url as an index and the page id that the URL lives in.

Here is a part of the code I wrote:

$wgHooks['ParserFirstCallInit'][] = 'UniqueURLSetupParserFunction';
$wgHooks['LoadExtensionSchemaUpdates'][] = 'fnExternalLinksDBHook';
// Allow translation of the parser function name
$wgExtensionMessagesFiles['UniqueUrl'] = dirname( __FILE__ ) . '/UniqueUrl.i18n.php';

// Tell MediaWiki that the parser function exists.
function UniqueURLSetupParserFunction( &$parser ) {
   $parser->setFunctionHook( 'example', 'UniqueURLParserFunction' );
   return true;
}

function UniqueURLParserFunction( $parser, $param1 = '', $param2 = '' ) {

   // The input parameters are wikitext with templates expanded.
   // The output should be wikitext too.
   global $wgRequest, $wgOut;
   $return_url = $wgRequest->getRequestURL();
   $pid = $param2;
   $param1 = trim($param1);
   $url_pattern = '/^(https?:\/\/)?([\da-z\.-]+)\.([a-z\.]{2,6})([\/\w \.-]*)*\/?$/';
   $match = preg_match($url_pattern, $param1);
   if (!$match) {
      // return ERROR not a valid URL!
   }
   $patterns = array('/^(https?:\/\/)/', '/\/$/');
   $replace = array('','');
   $url = preg_replace($patterns, $replace, $param1); 
   if (empty($param2)) {  // creating a new page
      try {
         $dbw = wfGetDB( DB_MASTER );
         $res = $dbw->insert('unique_external_links',
                array('link_url' => $url , 'page_id' => $pid));
      } catch(Exception $e) {
         // return ERROR page with this link already exists!
      }
   } else {  //Trying to edit existing page
      $dbr = wfGetDB( DB_SLAVE );
      $res = $dbr->select(
        'unique_external_links',                                   
        array( 'link_url' ),            
        'link_url = "' .$url.'" AND page_id = "' .$pid.'"'                              
      );
      if ($dbr->numRows($res) == 0) {
        try {
           $dbw = wfGetDB( DB_MASTER );
           $res = $dbw->insert('unique_external_links',
                  array('link_url' => $url , 'page_id' => $pid));
        } catch(Exception $e) {
           //return ERROR Dataset Already Exists
           $response = $wgRequest -> response();
           $response -> header('Location: '.$return_url);
           return $return_url;
        }
      }else {
         //just editing page, not changing link, all is good
         return $param1;
      }
   }
   return $param1;

}

First off, I apologize for the sloppy code, really just slapped this together very quickly with no prior extension experience... As you can see there are places where I have the comment //return ERROR I would like to stop media wiki from saving the page if one of those conditions are true. Instead of saving, I would like to return the user to the edit page with a message telling them there is a problem with the link they are providing.

Any ideas? I looked around a lot but couldn't find anything similar, I assume it is because I don't know really what question to ask. I am aware that there are hooks like 'ArticleSave', but i didn't know how I would use that in conjunction with a parser.

Any help would be great! Even if its telling me to completely re-do what I did because its all wrong haha.

EDIT: I fixed this problem by throwing MWExceptions at those places where I wanted to return an error. I then went to Exceptions.php and updated the MWExceptionhandler to take a different action when it sees that the exception message matches the ones I am throwing from this extension. This is hacky I admit.. But what can you do sometimes..

903

Answer

Solution:

Writing this extension as a parser function is probably the wrong direction. If you want to reject edits, use the EditFilter hook. You may want to take a look at the SpamBlacklist extension as a model, as it also looks at links to decide whether to reject an edit.

Also, the one issue I see with your extension is that, once a page has been saved with one of these unique links, there's nothing in place to remove rows from unique_external_links even if the link (or the entire page!) is removed, making it sometimes impossible to reinsert a link that's been removed. You'll probably want to fix that.

People are also looking for solutions to the problem: php - Passing HTML Input Value To The Form Action in a New Window Using Javascript

Source

Didn't find the answer?

Our community is visited by hundreds of web development professionals every day. Ask your question and get a quick answer for free.

Ask a Question

Write quick answer

Do you know the answer to this question? Write a quick response to it. With your help, we will make our community stronger.

Similar questions

Find the answer in similar questions on our website.