r23929 MediaWiki - Code Review archive

Repository:MediaWiki
Revision:r23928‎ | r23929 | r23930 >
Date:00:38, 10 July 2007
Author:suuch
Status:old
Tags:
Comment:
Initial commit that reproduces 1.10 implementation functionality
Modified paths:
  • /trunk/phase3/includes/filerepo/ICRepo.php (added) (history)

Diff [purge]

Index: trunk/phase3/includes/filerepo/ICRepo.php
@@ -0,0 +1,312 @@
 2+<?php
 3+
 4+/**
 5+ * A repository for files accessible via InstantCommons.
 6+ */
 7+
 8+class ICRepo extends LocalRepo {
 9+ var $directory, $url, $hashLevels, $cache;
 10+ var $fileFactory = array( 'ICFile', 'newFromTitle' );
 11+ var $oldFileFactory = false;
 12+
 13+ function __construct( $info ) {
 14+ parent::__construct( $info );
 15+ // Required settings
 16+ $this->directory = $info['directory'];
 17+ $this->url = $info['url'];
 18+ $this->hashLevels = $info['hashLevels'];
 19+ if(isset($info['cache'])){
 20+ $this->cache = getcwd().'/images/'.$info['cache'];
 21+ }
 22+ }
 23+}
 24+
 25+/**
 26+ * A file loaded from InstantCommons
 27+ */
 28+class ICFile extends LocalFile{
 29+ static function newFromTitle($title,$repo){
 30+ return new self($title, $repo);
 31+ }
 32+
 33+ /**
 34+ * Returns true if the file comes from the local file repository.
 35+ *
 36+ * @return bool
 37+ */
 38+ function isLocal() {
 39+ return true;
 40+ }
 41+
 42+ function load(){
 43+ if (!$this->dataLoaded ) {
 44+ if ( !$this->loadFromCache() ) {
 45+ if(!$this->loadFromDB()){
 46+ $this->loadFromIC();
 47+ }
 48+ $this->saveToCache();
 49+ }
 50+ $this->dataLoaded = true;
 51+ }
 52+ }
 53+
 54+ /**
 55+ * Load file metadata from the DB
 56+ */
 57+ function loadFromDB() {
 58+ wfProfileIn( __METHOD__ );
 59+
 60+ # Unconditionally set loaded=true, we don't want the accessors constantly rechecking
 61+ $this->dataLoaded = true;
 62+
 63+ $dbr = $this->repo->getSlaveDB();
 64+
 65+ $row = $dbr->selectRow( 'ic_image', $this->getCacheFields( 'img_' ),
 66+ array( 'img_name' => $this->getName() ), __METHOD__ );
 67+ if ( $row ) {
 68+ if (trim($row->img_media_type)==NULL) {
 69+ $this->upgradeRow();
 70+ $this->upgraded = true;
 71+ }
 72+ $this->loadFromRow( $row );
 73+ //This means that these files are local so the repository locations are local
 74+ $this->setUrlPathLocal();
 75+ $this->fileExists = true;
 76+ //var_dump($this); exit;
 77+ } else {
 78+ $this->fileExists = false;
 79+ }
 80+
 81+ wfProfileOut( __METHOD__ );
 82+
 83+ return $this->fileExists;
 84+ }
 85+
 86+ /**
 87+ * Fix assorted version-related problems with the image row by reloading it from the file
 88+ */
 89+ function upgradeRow() {
 90+ wfProfileIn( __METHOD__ );
 91+
 92+ $this->loadFromIC();
 93+
 94+ $dbw = $this->repo->getMasterDB();
 95+ list( $major, $minor ) = self::splitMime( $this->mime );
 96+
 97+ wfDebug(__METHOD__.': upgrading '.$this->getName()." to the current schema\n");
 98+
 99+ $dbw->update( 'ic_image',
 100+ array(
 101+ 'img_width' => $this->width,
 102+ 'img_height' => $this->height,
 103+ 'img_bits' => $this->bits,
 104+ 'img_media_type' => $this->type,
 105+ 'img_major_mime' => $major,
 106+ 'img_minor_mime' => $minor,
 107+ 'img_metadata' => $this->metadata,
 108+ ), array( 'img_name' => $this->getName() ),
 109+ __METHOD__
 110+ );
 111+ $this->saveToCache();
 112+ wfProfileOut( __METHOD__ );
 113+ }
 114+
 115+ function exists(){
 116+ $this->load();
 117+ return $this->fileExists;
 118+
 119+ }
 120+
 121+ /**
 122+ * Fetch the file from the repository. Check local ic_images table first. If not available, check remote server
 123+ */
 124+ function loadFromIC(){
 125+ # Unconditionally set loaded=true, we don't want the accessors constantly rechecking
 126+ $this->dataLoaded = true;
 127+ $icUrl = $this->repo->directory.'&media='.$this->title->mDbkeyform;
 128+ if($h = @fopen($icUrl, 'rb')){
 129+ $contents = fread($h, 3000);
 130+ $image = $this->api_xml_to_array($contents);
 131+ if($image['fileExists']){
 132+ foreach($image as $property=>$value){
 133+ if($property=="url"){$value=$this->repo->url.$value; }
 134+ $this->$property = $value;
 135+ }
 136+ if($this->curl_file_get_contents($this->repo->url.$image['url'], $this->repo->cache.'/'.$image['name'])){
 137+ //Record the image
 138+ $this->recordDownload("Downloaded with InstantCommons");
 139+
 140+ //Then cache it
 141+ }else{//set fileExists back to false
 142+ $this->fileExists = false;
 143+ }
 144+ }
 145+ }
 146+ }
 147+
 148+
 149+ function setUrlPathLocal(){
 150+ global $wgScriptPath;
 151+ $path = $wgScriptPath.'/'.substr($this->repo->cache, strlen($wgScriptPath));
 152+ $this->repo->url = $path;//.'/'.rawurlencode($this->title->mDbkeyform);
 153+ $this->repo->directory = $this->repo->cache;//.'/'.rawurlencode($this->title->mDbkeyform);
 154+
 155+ }
 156+
 157+ function getThumbPath( $suffix=false ){
 158+ $path = $this->repo->cache;
 159+ if ( $suffix !== false ) {
 160+ $path .= '/thumb/' . rawurlencode( $suffix );
 161+ }
 162+ return $path;
 163+ }
 164+ function getThumbUrl( $suffix=false ){
 165+ global $wgScriptPath;
 166+ $path = $wgScriptPath.'/'.substr($this->repo->cache, strlen($wgScriptPath));
 167+ if ( $suffix !== false ) {
 168+ $path .= '/thumb/' . rawurlencode( $suffix );
 169+ }
 170+ return $path;
 171+ }
 172+
 173+ /**
 174+ * Convert the InstantCommons Server API XML Response to an associative array
 175+ */
 176+ function api_xml_to_array($xml){
 177+ preg_match("/<instantcommons><image(.*?)<\/instantcommons>/",$xml,$match);
 178+ preg_match_all("/(.*?=\".*?\")/",$match[1], $matches);
 179+ foreach($matches[1] as $match){
 180+ list($key,$value) = split("=",$match);
 181+ $image[trim($key,'<" ')]=trim($value,' "');
 182+ }
 183+ return $image;
 184+ }
 185+
 186+ /**
 187+ * Use cURL to read the content of a URL into a string
 188+ * @param string $url - the URL to fetch
 189+ * @param resource $fp - filename to write file contents to
 190+ * @param boolean $bg - call cURL in the background (don't hang page until complete)
 191+ * @param int $timeout - cURL connect timeout
 192+ */
 193+ function curl_file_get_contents($url, $fp, $bg=TRUE, $timeout = 1){//ref: http://groups-beta.google.com/group/comp.lang.php/browse_thread/thread/8efbbaced3c45e3c/d63c7891cf8e380b?lnk=raot
 194+ {//call curl in the background to download the file
 195+ $cmd = 'curl '.wfEscapeShellArg($url).' -o '.$fp.' &';
 196+ wfDebug('Curl download initiated='.$cmd );
 197+ $success = false;
 198+ $file_contents = array();
 199+ $file_contents['err'] = wfShellExec($cmd, $file_contents['return']);
 200+ if($file_contents['err']==0){//Success
 201+ $success = true;
 202+ }
 203+ }
 204+ return $success;
 205+ }
 206+
 207+ function getMasterDB() {
 208+ if ( !isset( $this->dbConn ) ) {
 209+ $class = 'Database' . ucfirst( $this->dbType );
 210+ $this->dbConn = new $class( $this->dbServer, $this->dbUser,
 211+ $this->dbPassword, $this->dbName, false, $this->dbFlags,
 212+ $this->tablePrefix );
 213+ }
 214+ return $this->dbConn;
 215+ }
 216+
 217+
 218+
 219+ /**
 220+ * Record a file upload in the upload log and the image table
 221+ */
 222+ private function recordDownload($comment='', $timestamp = false ){
 223+ global $wgUser;
 224+
 225+ $dbw = $this->repo->getMasterDB();
 226+
 227+ if ( $timestamp === false ) {
 228+ $timestamp = $dbw->timestamp();
 229+ }
 230+ list( $major, $minor ) = self::splitMime( $this->mime );
 231+
 232+ # Test to see if the row exists using INSERT IGNORE
 233+ # This avoids race conditions by locking the row until the commit, and also
 234+ # doesn't deadlock. SELECT FOR UPDATE causes a deadlock for every race condition.
 235+ $dbw->insert( 'ic_image',
 236+ array(
 237+ 'img_name' => $this->getName(),
 238+ 'img_size'=> $this->size,
 239+ 'img_width' => intval( $this->width ),
 240+ 'img_height' => intval( $this->height ),
 241+ 'img_bits' => $this->bits,
 242+ 'img_media_type' => $this->type,
 243+ 'img_major_mime' => $major,
 244+ 'img_minor_mime' => $minor,
 245+ 'img_timestamp' => $timestamp,
 246+ 'img_description' => $comment,
 247+ 'img_user' => $wgUser->getID(),
 248+ 'img_user_text' => $wgUser->getName(),
 249+ 'img_metadata' => $this->metadata,
 250+ ),
 251+ __METHOD__,
 252+ 'IGNORE'
 253+ );
 254+
 255+ if( $dbw->affectedRows() == 0 ) {
 256+ # Collision, this is an update of a file
 257+ # Update the current image row
 258+ $dbw->update( 'ic_image',
 259+ array( /* SET */
 260+ 'img_size' => $this->size,
 261+ 'img_width' => intval( $this->width ),
 262+ 'img_height' => intval( $this->height ),
 263+ 'img_bits' => $this->bits,
 264+ 'img_media_type' => $this->media_type,
 265+ 'img_major_mime' => $this->major_mime,
 266+ 'img_minor_mime' => $this->minor_mime,
 267+ 'img_timestamp' => $timestamp,
 268+ 'img_description' => $comment,
 269+ 'img_user' => $wgUser->getID(),
 270+ 'img_user_text' => $wgUser->getName(),
 271+ 'img_metadata' => $this->metadata,
 272+ ), array( /* WHERE */
 273+ 'img_name' => $this->getName()
 274+ ), __METHOD__
 275+ );
 276+ } else {
 277+ # This is a new file
 278+ # Update the image count
 279+ $site_stats = $dbw->tableName( 'site_stats' );
 280+ $dbw->query( "UPDATE $site_stats SET ss_images=ss_images+1", __METHOD__ );
 281+ }
 282+
 283+ $descTitle = $this->getTitle();
 284+ $article = new Article( $descTitle );
 285+
 286+ # Add the log entry
 287+ $log = new LogPage( 'icdownload' );
 288+ $log->addEntry( 'InstantCommons download', $descTitle, $comment );
 289+
 290+ if( $descTitle->exists() ) {
 291+ # Create a null revision
 292+ $nullRevision = Revision::newNullRevision( $dbw, $descTitle->getArticleId(), $log->getRcComment(), false );
 293+ $nullRevision->insertOn( $dbw );
 294+
 295+ # Invalidate the cache for the description page
 296+ $descTitle->invalidateCache();
 297+ $descTitle->purgeSquid();
 298+ }
 299+
 300+
 301+ # Commit the transaction now, in case something goes wrong later
 302+ # The most important thing is that files don't get lost, especially archives
 303+ $dbw->immediateCommit();
 304+
 305+ # Invalidate cache for all pages using this file
 306+ $update = new HTMLCacheUpdate( $this->getTitle(), 'imagelinks' );
 307+ $update->doUpdate();
 308+
 309+ return true;
 310+ }
 311+
 312+}
 313+

Follow-up revisions

RevisionCommit summaryAuthorDate
r24096Merged revisions 23910-24094 via svnmerge from...david22:38, 14 July 2007

Status & tagging log