Tell regexp parser to use extra analysis on external link regexp;
[lhc/web/wiklou.git] / includes / Article.php
index e319524..5437d46 100644 (file)
@@ -69,6 +69,9 @@ class Article {
          * @return string $text|false the text requested
        */
        function getRevisionText( $row, $prefix = 'old_' ) {
+               $fname = 'Article::getRevisionText';
+               wfProfileIn( $fname );
+               
                # Get data
                $textField = $prefix . 'text';
                $flagsField = $prefix . 'flags';
@@ -91,7 +94,19 @@ class Article {
                        # as pages are saved if $wgCompressRevisions is set.
                        $text = gzinflate( $text );
                }
-               
+                       
+               if( in_array( 'object', $flags ) ) {
+                       # Generic compressed storage
+                       $obj = unserialize( $text );
+
+                       # Bugger, corrupted my test database by double-serializing
+                       if ( !is_object( $obj ) ) {
+                               $obj = unserialize( $obj );
+                       }
+
+                       $text = $obj->getText();
+               }
+       
                global $wgLegacyEncoding;
                if( $wgLegacyEncoding && !in_array( 'utf-8', $flags ) ) {
                        # Old revisions kept around in a legacy encoding?
@@ -99,11 +114,7 @@ class Article {
                        global $wgInputEncoding, $wgContLang;
                        $text = $wgContLang->iconv( $wgLegacyEncoding, $wgInputEncoding, $text );
                }
-               
-               if( in_array( 'link', $flags ) ) {
-                       # Handle link type
-                       $text = Article::followLink( $text );
-               }
+               wfProfileOut( $fname );
                return $text;
        }
 
@@ -137,131 +148,6 @@ class Article {
                return implode( ',', $flags );
        }
 
-       /**
-        * Returns the text associated with a "link" type old table row
-        * @static
-        * @param mixed $link
-        * @return string $text|false
-        */
-       function followLink( $link ) {
-               # Split the link into fields and values
-               $lines = explode( '\n', $link );
-               $hash = '';
-               $locations = array();
-               foreach ( $lines as $line ) {
-                       # Comments
-                       if ( $line{0} == '#' ) {
-                               continue;
-                       }
-                       # Field/value pairs
-                       if ( preg_match( '/^(.*?)\s*:\s*(.*)$/', $line, $matches ) ) {
-                               $field = strtolower($matches[1]);
-                               $value = $matches[2];
-                               if ( $field == 'hash' ) {
-                                       $hash = $value;
-                               } elseif ( $field == 'location' ) {
-                                       $locations[] = $value;
-                               }
-                       }
-               }
-
-               if ( $hash === '' ) {
-                       return false;
-               }
-
-               # Look in each specified location for the text
-               $text = false;
-               foreach ( $locations as $location ) {
-                       $text = Article::fetchFromLocation( $location, $hash );
-                       if ( $text !== false ) {
-                               break;
-                       }
-               }
-
-               return $text;
-       }
-
-       /**
-        * @static
-        * @param $location
-        * @param $hash
-        */
-       function fetchFromLocation( $location, $hash ) {
-               global $wgLoadBalancer;
-               $fname = 'fetchFromLocation';
-               wfProfileIn( $fname );
-
-               $p = strpos( $location, ':' );
-               if ( $p === false ) {
-                       wfProfileOut( $fname );
-                       return false;
-               }
-
-               $type = substr( $location, 0, $p );
-               $text = false;
-               switch ( $type ) {
-                       case 'mysql':
-                               # MySQL locations are specified by mysql://<machineID>/<dbname>/<tblname>/<index>
-                               # Machine ID 0 is the current connection
-                               if ( preg_match( '/^mysql:\/\/(\d+)\/([A-Za-z_]+)\/([A-Za-z_]+)\/([A-Za-z_]+)$/',
-                                 $location, $matches ) ) {
-                                       $machineID = $matches[1];
-                                       $dbName = $matches[2];
-                                       $tblName = $matches[3];
-                                       $index = $matches[4];
-                                       if ( $machineID == 0 ) {
-                                               # Current connection
-                                               $db =& $this->getDB();
-                                       } else {
-                                               # Alternate connection
-                                               $db =& $wgLoadBalancer->getConnection( $machineID );
-
-                                               if ( array_key_exists( $machineId, $wgKnownMysqlServers ) ) {
-                                                       # Try to open, return false on failure
-                                                       $params = $wgKnownDBServers[$machineId];
-                                                       $db = Database::newFromParams( $params['server'], $params['user'], $params['password'],
-                                                               $dbName, 1, DBO_IGNORE );
-                                               }
-                                       }
-                                       if ( $db->isOpen() ) {
-                                               $index = $db->strencode( $index );
-                                               $res = $db->query( "SELECT blob_data FROM $dbName.$tblName " .
-                                                       "WHERE blob_index='$index' " . $this->getSelectOptions(), $fname );
-                                               $row = $db->fetchObject( $res );
-                                               $text = $row->text_data;
-                                       }
-                               }
-                               break;
-                       case 'file':
-                               # File locations are of the form file://<filename>, relative to the current directory
-                               if ( preg_match( '/^file:\/\/(.*)$', $location, $matches ) )
-                               $filename = strstr( $location, 'file://' );
-                               $text = @file_get_contents( $matches[1] );
-               }
-               if ( $text !== false ) {
-                       # Got text, now we need to interpret it
-                       # The first line contains information about how to do this
-                       $p = strpos( $text, '\n' );
-                       $type = substr( $text, 0, $p );
-                       $text = substr( $text, $p + 1 );
-                       switch ( $type ) {
-                               case 'plain':
-                                       break;
-                               case 'gzip':
-                                       $text = gzinflate( $text );
-                                       break;
-                               case 'object':
-                                       $object = unserialize( $text );
-                                       $text = $object->getItem( $hash );
-                                       break;
-                               default:
-                                       $text = false;
-                       }
-               }
-               wfProfileOut( $fname );
-               return $text;
-       }
-
        /**
         * Note that getContent/loadContent may follow redirects if
         * not told otherwise, and so may cause a change to mTitle.
@@ -410,25 +296,21 @@ class Article {
        }
 
        /**
-        * Load the revision (including cur_text) into this object
-       */
-       function loadContent( $noredir = false ) {
-               global $wgOut, $wgRequest;
-
-               if ( $this->mContentLoaded ) return;
-               
-               $dbr =& $this->getDB();
-               # Query variables :P
-               $oldid = $wgRequest->getVal( 'oldid' );
-               $redirect = $wgRequest->getVal( 'redirect' );
-
-               $fname = 'Article::loadContent';
+        * Return the oldid of the article that is to be shown.
+        * For requests with a "direction", this is not the oldid of the
+        * query
+        */
+       function getOldID() {
+               global $wgRequest, $wgOut;
+               static $lastid;
 
-               # Pre-fill content with error message so that if something
-               # fails we'll have something telling us what we intended.
+               if ( isset( $lastid ) ) {
+                       return $lastid;
+               }
 
-               $t = $this->mTitle->getPrefixedText();
+               $oldid = $wgRequest->getVal( 'oldid' );
                if ( isset( $oldid ) ) {
+                       $dbr =& $this->getDB();
                        $oldid = IntVal( $oldid );
                        if ( $wgRequest->getVal( 'direction' ) == 'next' ) {
                                $nextid = $this->mTitle->getNextRevisionID( $oldid );
@@ -445,7 +327,32 @@ class Article {
                                        # TODO
                                }
                        }
+                       $lastid = $oldid;
                }
+               return @$oldid; # "@" to be able to return "unset" without PHP complaining
+       }
+
+
+       /**
+        * Load the revision (including cur_text) into this object
+       */
+       function loadContent( $noredir = false ) {
+               global $wgOut, $wgRequest;
+
+               if ( $this->mContentLoaded ) return;
+               
+               $dbr =& $this->getDB();
+               # Query variables :P
+               $oldid = $this->getOldID();
+               $redirect = $wgRequest->getVal( 'redirect' );
+
+               $fname = 'Article::loadContent';
+
+               # Pre-fill content with error message so that if something
+               # fails we'll have something telling us what we intended.
+
+               $t = $this->mTitle->getPrefixedText();
+
                if ( isset( $oldid ) ) {
                        $t .= ',oldid='.$oldid;
                }
@@ -504,8 +411,7 @@ class Article {
                        $this->mCounter = $s->cur_counter;
                        $this->mTimestamp = wfTimestamp(TS_MW,$s->cur_timestamp);
                        $this->mTouched = wfTimestamp(TS_MW,$s->cur_touched);
-                       $this->mTitle->mRestrictions = explode( ',', trim( $s->cur_restrictions ) );
-                       $this->mTitle->mRestrictionsLoaded = true;
+                       $this->mTitle->loadRestrictions( $s->cur_restrictions );
                } else { # oldid set, retrieve historical version
                        $s = $dbr->selectRow( 'old', $this->getOldContentFields(), array( 'old_id' => $oldid ),
                                $fname, $this->getSelectOptions() );
@@ -583,8 +489,7 @@ class Article {
                        $this->mCounter = $s->cur_counter;
                        $this->mTimestamp = wfTimestamp(TS_MW,$s->cur_timestamp);
                        $this->mTouched = wfTimestamp(TS_MW,$s->cur_touched);
-                       $this->mTitle->mRestrictions = explode( ',', trim( $s->cur_restrictions ) );
-                       $this->mTitle->mRestrictionsLoaded = true;
+                       $this->mTitle->loadRestrictions( $s->cur_restrictions );
                } else { # oldid set, retrieve historical version
                        $s = $dbr->selectRow( 'old', $this->getOldContentFields(), array( 'old_id' => $oldid ),
                                $fname, $this->getSelectOptions() );
@@ -776,14 +681,14 @@ class Article {
         * the given title.
        */
        function view() {
-               global $wgUser, $wgOut, $wgRequest, $wgOnlySysopsCanPatrol;
+               global $wgUser, $wgOut, $wgRequest, $wgOnlySysopsCanPatrol, $wgLang;
                global $wgLinkCache, $IP, $wgEnableParserCache, $wgStylePath, $wgUseRCPatrol;
                $sk = $wgUser->getSkin();
 
                $fname = 'Article::view';
                wfProfileIn( $fname );
                # Get variables from query string
-               $oldid = $wgRequest->getVal( 'oldid' );
+               $oldid = $this->getOldID();
                $diff = $wgRequest->getVal( 'diff' );
                $rcid = $wgRequest->getVal( 'rcid' );
 
@@ -871,8 +776,10 @@ class Article {
                                $targetUrl = $rt->escapeLocalURL();
                                $titleText = htmlspecialchars( $rt->getPrefixedText() );
                                $link = $sk->makeLinkObj( $rt );
-                               $wgOut->addHTML( '<img valign="center" src="'.$imageUrl.'" />' .
+
+                               $wgOut->addHTML( '<img valign="center" src="'.$imageUrl.'" alt="#REDIRECT" />' .
                                  '<span class="redirectText">'.$link.'</span>' );
+
                        } else if ( $pcache ) {
                                # Display content and save to parser cache
                                $wgOut->addPrimaryWikiText( $text, $this );
@@ -1370,14 +1277,20 @@ class Article {
                }
 
                $confirm = $wgRequest->getBool( 'wpConfirmProtect' ) && $wgRequest->wasPosted();
+               $moveonly = $wgRequest->getBool( 'wpMoveOnly' );
                $reason = $wgRequest->getText( 'wpReasonProtect' );
 
                if ( $confirm ) {
+                       $restrictions = "move=" . $limit;
+                       if( !$moveonly ) {
+                               $restrictions .= ":edit=" . $limit;
+                       }
+                       
                        $dbw =& wfGetDB( DB_MASTER );
                        $dbw->update( 'cur',
                                array( /* SET */
                                        'cur_touched' => $dbw->timestamp(),
-                                       'cur_restrictions' => (string)$limit
+                                       'cur_restrictions' => $restrictions
                                ), array( /* WHERE */
                                        'cur_id' => $id
                                ), 'Article::protect'
@@ -1410,6 +1323,7 @@ class Article {
 
                $check = '';
                $protcom = '';
+               $moveonly = '';
 
                if ( $limit === '' ) {
                        $wgOut->setPageTitle( wfMsg( 'confirmunprotect' ) );
@@ -1423,6 +1337,7 @@ class Article {
                        $wgOut->setSubtitle( wfMsg( 'protectsub', $sub ) );
                        $wgOut->addWikiText( wfMsg( 'confirmprotecttext' ) );
                        $check = htmlspecialchars( wfMsg( 'confirmprotect' ) );
+                       $moveonly = htmlspecialchars( wfMsg( 'protectmoveonly' ) );
                        $protcom = htmlspecialchars( wfMsg( 'protectcomment' ) );
                        $formaction = $this->mTitle->escapeLocalURL( 'action=protect' . $par );
                }
@@ -1450,7 +1365,19 @@ class Article {
                        <td>
                                <label for='wpConfirmProtect'>{$check}</label>
                        </td>
-               </tr>
+               </tr> " );
+               if($moveonly != '') {
+                       $wgOut->AddHTML( "
+               <tr>
+                       <td align='right'>
+                               <input type='checkbox' name='wpMoveOnly' value='1' id='wpMoveOnly' />
+                       </td>
+                       <td>
+                               <label for='wpMoveOnly'>{$moveonly}</label>
+                       </td>
+               </tr> " );
+               }
+               $wgOut->addHTML( "
                <tr>
                        <td>&nbsp;</td>
                        <td>