+ /**
+ * Record an image upload in the upload log and the image table
+ */
+ function recordUpload( $oldver, $desc, $copyStatus = '', $source = '' ) {
+ global $wgUser, $wgLang, $wgTitle, $wgOut, $wgDeferredUpdateList;
+ global $wgUseCopyrightUpload, $wgUseSquid, $wgPostCommitUpdateList;
+
+ $fname = 'Image::recordUpload';
+ $dbw =& wfGetDB( DB_MASTER );
+
+ $this->checkDBSchema($dbw);
+
+ // Delete thumbnails and refresh the metadata cache
+ $this->purgeCache();
+
+ // Fail now if the image isn't there
+ if ( !$this->fileExists || $this->fromSharedDirectory ) {
+ wfDebug( "Image::recordUpload: File ".$this->imagePath." went missing!\n" );
+ return false;
+ }
+
+ if ( $wgUseCopyrightUpload ) {
+ $textdesc = '== ' . wfMsg ( 'filedesc' ) . " ==\n" . $desc . "\n" .
+ '== ' . wfMsg ( 'filestatus' ) . " ==\n" . $copyStatus . "\n" .
+ '== ' . wfMsg ( 'filesource' ) . " ==\n" . $source ;
+ } else {
+ $textdesc = $desc;
+ }
+
+ $now = $dbw->timestamp();
+
+ #split mime type
+ if (strpos($this->mime,'/')!==false) {
+ list($major,$minor)= explode('/',$this->mime,2);
+ }
+ else {
+ $major= $this->mime;
+ $minor= "unknown";
+ }
+
+ # Test to see if the row exists using INSERT IGNORE
+ # This avoids race conditions by locking the row until the commit, and also
+ # doesn't deadlock. SELECT FOR UPDATE causes a deadlock for every race condition.
+ $dbw->insert( 'image',
+ array(
+ 'img_name' => $this->name,
+ 'img_size'=> $this->size,
+ 'img_width' => $this->width,
+ 'img_height' => $this->height,
+ 'img_bits' => $this->bits,
+ 'img_media_type' => $this->type,
+ 'img_major_mime' => $major,
+ 'img_minor_mime' => $minor,
+ 'img_timestamp' => $now,
+ 'img_description' => $desc,
+ 'img_user' => $wgUser->getID(),
+ 'img_user_text' => $wgUser->getName(),
+ 'img_metadata' => $this->metadata,
+ ), $fname, 'IGNORE'
+ );
+ $descTitle = $this->getTitle();
+ $purgeURLs = array();
+
+ if ( $dbw->affectedRows() ) {
+ # Successfully inserted, this is a new image
+ $id = $descTitle->getArticleID();
+
+ if ( $id == 0 ) {
+ $article = new Article( $descTitle );
+ $article->insertNewArticle( $textdesc, $desc, false, false, true );
+ }
+ } else {
+ # Collision, this is an update of an image
+ # Insert previous contents into oldimage
+ $dbw->insertSelect( 'oldimage', 'image',
+ array(
+ 'oi_name' => 'img_name',
+ 'oi_archive_name' => $dbw->addQuotes( $oldver ),
+ 'oi_size' => 'img_size',
+ 'oi_width' => 'img_width',
+ 'oi_height' => 'img_height',
+ 'oi_bits' => 'img_bits',
+ 'oi_timestamp' => 'img_timestamp',
+ 'oi_description' => 'img_description',
+ 'oi_user' => 'img_user',
+ 'oi_user_text' => 'img_user_text',
+ ), array( 'img_name' => $this->name ), $fname
+ );
+
+ # Update the current image row
+ $dbw->update( 'image',
+ array( /* SET */
+ 'img_size' => $this->size,
+ 'img_width' => $this->width,
+ 'img_height' => $this->height,
+ 'img_bits' => $this->bits,
+ 'img_media_type' => $this->type,
+ 'img_major_mime' => $major,
+ 'img_minor_mime' => $minor,
+ 'img_timestamp' => $now,
+ 'img_description' => $desc,
+ 'img_user' => $wgUser->getID(),
+ 'img_user_text' => $wgUser->getName(),
+ 'img_metadata' => $this->metadata,
+ ), array( /* WHERE */
+ 'img_name' => $this->name
+ ), $fname
+ );
+
+ # Invalidate the cache for the description page
+ $descTitle->invalidateCache();
+ $purgeURLs[] = $descTitle->getInternalURL();
+ }
+
+ # Invalidate cache for all pages using this image
+ $linksTo = $this->getLinksTo();
+
+ if ( $wgUseSquid ) {
+ $u = SquidUpdate::newFromTitles( $linksTo, $purgeURLs );
+ array_push( $wgPostCommitUpdateList, $u );
+ }
+ Title::touchArray( $linksTo );
+
+ $log = new LogPage( 'upload' );
+ $log->addEntry( 'upload', $descTitle, $desc );
+
+ return true;
+ }
+
+ /**
+ * Get an array of Title objects which are articles which use this image
+ * Also adds their IDs to the link cache
+ *
+ * This is mostly copied from Title::getLinksTo()
+ */
+ function getLinksTo( $options = '' ) {
+ global $wgLinkCache;
+ $fname = 'Image::getLinksTo';
+ wfProfileIn( $fname );
+
+ if ( $options ) {
+ $db =& wfGetDB( DB_MASTER );
+ } else {
+ $db =& wfGetDB( DB_SLAVE );
+ }
+
+ extract( $db->tableNames( 'page', 'imagelinks' ) );
+ $encName = $db->addQuotes( $this->name );
+ $sql = "SELECT page_namespace,page_title,page_id FROM $page,$imagelinks WHERE page_id=il_from AND il_to=$encName $options";
+ $res = $db->query( $sql, $fname );
+
+ $retVal = array();
+ if ( $db->numRows( $res ) ) {
+ while ( $row = $db->fetchObject( $res ) ) {
+ if ( $titleObj = Title::makeTitle( $row->page_namespace, $row->page_title ) ) {
+ $wgLinkCache->addGoodLinkObj( $row->page_id, $titleObj );
+ $retVal[] = $titleObj;
+ }
+ }
+ }
+ $db->freeResult( $res );
+ return $retVal;
+ }
+ /**
+ * Retrive Exif data from the database
+ *
+ * Retrive Exif data from the database and prune unrecognized tags
+ * and/or tags with invalid contents
+ *
+ * @return array
+ */
+ function retrieveExifData () {
+ if ( $this->getMimeType() !== "image/jpeg" ) return array ();
+
+ wfSuppressWarnings();
+ $exif = exif_read_data( $this->imagePath );
+ wfRestoreWarnings();
+
+ foreach($exif as $k => $v) {
+ if ( !in_array($k, array_keys($this->exif->mFlatExif)) ) {
+ wfDebug( "Image::retrieveExifData: '$k' is not a valid Exif tag (type: '" . gettype($v) . "'; data: '$v')\n");
+ unset($exif[$k]);
+ }
+ }
+
+ foreach($exif as $k => $v) {
+ if ( !$this->exif->validate($k, $v) ) {
+ wfDebug( "Image::retrieveExifData: '$k' contained invalid data (type: '" . gettype($v) . "'; data: '$v')\n");
+ unset($exif[$k]);
+ }
+ }
+ return $exif;
+ }
+
+ function getExifData () {
+ global $wgRequest;
+ if ( $this->metadata === '0' )
+ return array();
+
+ $purge = $wgRequest->getVal( 'action' ) == 'purge';
+ $ret = unserialize ( $this->metadata );
+
+ $oldver = isset( $ret['MEDIAWIKI_EXIF_VERSION'] ) ? $ret['MEDIAWIKI_EXIF_VERSION'] : 0;
+ $newver = $this->exif->version();
+
+ if ( !count( $ret ) || $purge || $oldver != $newver ) {
+ $this->updateExifData( $newver );
+ }
+ if ( isset( $ret['MEDIAWIKI_EXIF_VERSION'] ) )
+ unset( $ret['MEDIAWIKI_EXIF_VERSION'] );
+
+ foreach($ret as $k => $v) {
+ $ret[$k] = $this->exif->format($k, $v);
+ }
+
+ return $ret;
+ }
+
+ function updateExifData( $version ) {
+ $fname = 'Image:updateExifData';
+
+ if ( $this->getImagePath() === false ) # Not a local image
+ return;
+
+ # Get EXIF data from image
+ $exif = $this->retrieveExifData();
+ if ( count( $exif ) ) {
+ $exif['MEDIAWIKI_EXIF_VERSION'] = $version;
+ $this->metadata = serialize( $exif );
+ } else {
+ $this->metadata = '0';
+ }
+
+ # Update EXIF data in database
+ $dbw =& wfGetDB( DB_MASTER );
+
+ $this->checkDBSchema($dbw);
+
+ $dbw->update( 'image',
+ array( 'img_metadata' => $this->metadata ),
+ array( 'img_name' => $this->name ),
+ $fname
+ );
+ }
+