r9610 MediaWiki - Code Review archive

Repository:MediaWiki
Revision:r9609‎ | r9610 | r9611 >
Date:06:28, 24 June 2005
Author:vibber
Status:old
Tags:
Comment:
Convert image table:
* add and detect type & size fields
* convert UTF-8 in fields
* convert UTF-8 in filenames, leaving redirects from compatibility names
Modified paths:
  • /trunk/phase3/maintenance/upgrade1_5.php (modified) (history)

Diff [purge]

Index: trunk/phase3/maintenance/upgrade1_5.php
@@ -33,6 +33,8 @@
3434 $this->upgradePage();
3535 $this->upgradeLinks();
3636 $this->upgradeUser();
 37+ $this->upgradeImage();
 38+ #$this->upgradeOldImage();
3739 }
3840
3941
@@ -544,96 +546,128 @@
545547 $this->dbw->query( "ALTER TABLE $user_temp RENAME TO $user" );
546548 }
547549
548 -
549 - /**
550 - * Truncate a table.
551 - * @param string $table The table name to be truncated
552 - */
553 - function clearTable( $table ) {
554 - print "Clearing $table...\n";
555 - $tableName = $this->db->tableName( $table );
556 - $this->db->query( 'TRUNCATE $tableName' );
 550+ function upgradeImage() {
 551+ $fname = 'FiveUpgrade::upgradeImage';
 552+ $chunksize = 100;
 553+
 554+ extract( $this->dbw->tableNames( 'image', 'image_temp', 'image_old' ) );
 555+ $this->log( 'Creating temporary image_temp to merge into...' );
 556+ $this->dbw->query( <<<END
 557+CREATE TABLE $image_temp (
 558+ img_name varchar(255) binary NOT NULL default '',
 559+ img_size int(8) unsigned NOT NULL default '0',
 560+ img_width int(5) NOT NULL default '0',
 561+ img_height int(5) NOT NULL default '0',
 562+ img_metadata mediumblob NOT NULL,
 563+ img_bits int(3) NOT NULL default '0',
 564+ img_media_type ENUM("UNKNOWN", "BITMAP", "DRAWING", "AUDIO", "VIDEO", "MULTIMEDIA", "OFFICE", "TEXT", "EXECUTABLE", "ARCHIVE") default NULL,
 565+ img_major_mime ENUM("unknown", "application", "audio", "image", "text", "video", "message", "model", "multipart") NOT NULL default "unknown",
 566+ img_minor_mime varchar(32) NOT NULL default "unknown",
 567+ img_description tinyblob NOT NULL default '',
 568+ img_user int(5) unsigned NOT NULL default '0',
 569+ img_user_text varchar(255) binary NOT NULL default '',
 570+ img_timestamp char(14) binary NOT NULL default '',
 571+
 572+ PRIMARY KEY img_name (img_name),
 573+ INDEX img_size (img_size),
 574+ INDEX img_timestamp (img_timestamp)
 575+) TYPE=InnoDB
 576+END
 577+ , $fname);
 578+
 579+ $numimages = $this->dbw->selectField( 'image', 'count(*)', '', $fname );
 580+ $result = $this->dbr->select( 'image',
 581+ array(
 582+ 'img_name',
 583+ 'img_size',
 584+ 'img_description',
 585+ 'img_user',
 586+ 'img_user_text',
 587+ 'img_timestamp' ),
 588+ '',
 589+ $fname );
 590+ $add = array();
 591+ $this->setChunkScale( $chunksize, $numimages, 'image_temp', $fname );
 592+ while( $row = $this->dbr->fetchObject( $result ) ) {
 593+ // Fill in the new image info fields
 594+ $info = $this->imageInfo( $row->img_name );
 595+
 596+ // Update and convert encoding
 597+ $add[] = array(
 598+ 'img_name' => $this->conv( $row->img_name ),
 599+ 'img_size' => $row->img_size,
 600+ 'img_width' => $info['width'],
 601+ 'img_height' => $info['height'],
 602+ 'img_metadata' => "", // loaded on-demand
 603+ 'img_bits' => $info['bits'],
 604+ 'img_media_type' => $info['media'],
 605+ 'img_major_mime' => $info['major'],
 606+ 'img_minor_mime' => $info['minor'],
 607+ 'img_description' => $this->conv( $row->img_description ),
 608+ 'img_user' => $row->img_user,
 609+ 'img_user_text' => $this->conv( $row->img_user_text ),
 610+ 'img_timestamp' => $row->img_timestamp );
 611+
 612+ // If doing UTF8 conversion the file must be renamed
 613+ $this->renameFile( $row->img_name, 'wfImageDir' );
 614+ }
 615+ $this->lastChunk( $add );
 616+
 617+ $this->log( 'Renaming image to image_old and image_temp to image...' );
 618+ $this->dbw->query( "ALTER TABLE $image RENAME TO $image_old" );
 619+ $this->dbw->query( "ALTER TABLE $image_temp RENAME TO $image" );
 620+
 621+ $this->log( 'done with image table.' );
557622 }
558623
559 - /**
560 - * @param string $table Table to be converted
561 - * @param string $key Primary key, to identify fields in the UPDATE. If NULL, all fields will be used to match.
562 - * @param array $fields List of all fields to grab and convert. If null, will assume you want the $key, and will ask for DISTINCT.
563 - * @param array $timestamp A field which should be updated to the current timestamp on changed records.
564 - * @param callable $callback
565 - * @access private
566 - */
567 - function convertTable( $table, $key, $fields = null, $timestamp = null, $callback = null ) {
568 - $fname = 'FiveUpgrade::convertTable';
569 - if( $fields ) {
570 - $distinct = '';
 624+ function imageInfo( $name ) {
 625+ $filename = wfImageDir( $name ) . '/' . $name;
 626+ $info = array(
 627+ 'width' => 0,
 628+ 'height' => 0,
 629+ 'bits' => 0,
 630+ 'media' => '',
 631+ 'major' => '',
 632+ 'minor' => '' );
 633+
 634+ $magic =& wfGetMimeMagic();
 635+ $mime = $magic->guessMimeType( $filename, true );
 636+ list( $info['major'], $info['minor'] ) = explode( '/', $mime );
 637+
 638+ $info['media'] = $magic->getMediaType( $filename, $mime );
 639+
 640+ # Height and width
 641+ $gis = false;
 642+ if( $mime == 'image/svg' ) {
 643+ $gis = wfGetSVGsize( $this->imagePath );
 644+ } elseif( $magic->isPHPImageType( $mime ) ) {
 645+ $gis = getimagesize( $filename );
571646 } else {
572 - # If working on one key only, there will be multiple rows.
573 - # Use DISTINCT to return only one and save us some trouble.
574 - $fields = array( $key );
575 - $distinct = 'DISTINCT';
 647+ $this->log( "Surprising mime type: $mime" );
576648 }
577 - $condition = '';
578 - foreach( $fields as $field ) {
579 - if( $condition ) $condition .= ' OR ';
580 - $condition .= "$field RLIKE '[\x80-\xff]'";
 649+ if( $gis ) {
 650+ $info['width' ] = $gis[0];
 651+ $info['height'] = $gis[1];
581652 }
582 - $res = $this->dbw->selectArray(
583 - $table,
584 - array_merge( $fields, array( $key ) ),
585 - $condition,
586 - $fname,
587 - $distinct );
588 - print "Converting " . $this->dbw->numResults( $res ) . " rows from $table:\n";
589 - $n = 0;
590 - while( $s = $this->dbw->fetchObject( $res ) ) {
591 - $set = array();
592 - foreach( $fields as $field ) {
593 - $set[] = $this->toUtf8( $s->$field );
594 - }
595 - if( $timestamp ) {
596 - $set[$timestamp] = $this->db->timestamp();
597 - }
598 - if( $key ) {
599 - $keyCond = array( $key, $s->$key );
600 - } else {
601 - $keyCond = array();
602 - foreach( $fields as $field ) {
603 - $keyCond[$field] = $s->$field;
604 - }
605 - }
606 - $this->dbw->updateArray(
607 - $table,
608 - $set,
609 - $keyCond,
610 - $fname );
611 - if( ++$n % 100 == 0 ) echo "$n\n";
612 -
613 - if( is_callable( $callback ) ) {
614 - call_user_func( $callback, $s );
615 - }
 653+ if( isset( $gis['bits'] ) ) {
 654+ $info['bits'] = $gis['bits'];
616655 }
617 - echo "$n done.\n";
618 - $this->dbw->freeResult( $res );
 656+
 657+ return $info;
619658 }
620659
 660+
621661 /**
622 - * @param object $row
623 - * @access private
 662+ * Truncate a table.
 663+ * @param string $table The table name to be truncated
624664 */
625 - function imageRenameCallback( $row ) {
626 - $this->renameFile( $row->img_name, 'wfImageDir' );
 665+ function clearTable( $table ) {
 666+ print "Clearing $table...\n";
 667+ $tableName = $this->db->tableName( $table );
 668+ $this->db->query( 'TRUNCATE $tableName' );
627669 }
628670
629671 /**
630 - * @param object $row
631 - * @access private
632 - */
633 - function oldimageRenameCallback( $row ) {
634 - $this->renameFile( $row->oi_archive_name, 'wfImageArchiveDir' );
635 - }
636 -
637 - /**
638672 * Rename a given image or archived image file to the converted filename,
639673 * leaving a symlink for URL compatibility.
640674 *
@@ -642,7 +676,7 @@
643677 * @access private
644678 */
645679 function renameFile( $oldname, $subdirCallback ) {
646 - $newname = $this->toUtf8( $oldname );
 680+ $newname = $this->conv( $oldname );
647681 if( $newname == $oldname ) {
648682 // No need to rename; another field triggered this row.
649683 return;
@@ -651,20 +685,49 @@
652686 $oldpath = call_user_func( $subdirCallback, $oldname ) . '/' . $oldname;
653687 $newpath = call_user_func( $subdirCallback, $newname ) . '/' . $newname;
654688
655 - echo "Renaming $oldpath to $newpath... ";
 689+ $this->log( "$oldpath -> $newpath" );
656690 if( rename( $oldpath, $newpath ) ) {
657 - echo "ok\n";
658 - echo "Creating compatibility symlink from $newpath to $oldpath... ";
659 - if( symlink( $newpath, $oldpath ) ) {
660 - echo "ok\n";
661 - } else {
662 - echo " symlink failed!\n";
 691+ $relpath = $this->relativize( $newpath, dirname( $oldpath ) );
 692+ if( !symlink( $relpath, $oldpath ) ) {
 693+ $this->log( "... symlink failed!" );
663694 }
664695 } else {
665 - echo " rename failed!\n";
 696+ $this->log( "... rename failed!" );
666697 }
667698 }
668699
 700+ /**
 701+ * Generate a relative path name to the given file.
 702+ * Assumes Unix-style paths, separators, and semantics.
 703+ *
 704+ * @param string $path Absolute destination path including target filename
 705+ * @param string $from Absolute source path, directory only
 706+ * @return string
 707+ * @access private
 708+ * @static
 709+ */
 710+ function relativize( $path, $from ) {
 711+ $pieces = explode( '/', dirname( $path ) );
 712+ $against = explode( '/', $from );
 713+
 714+ // Trim off common prefix
 715+ while( count( $pieces ) && count( $against )
 716+ && $pieces[0] == $against[0] ) {
 717+ array_shift( $pieces );
 718+ array_shift( $against );
 719+ }
 720+
 721+ // relative dots to bump us to the parent
 722+ while( count( $against ) ) {
 723+ array_unshift( $pieces, '..' );
 724+ array_shift( $against );
 725+ }
 726+
 727+ array_push( $pieces, basename( $path ) );
 728+
 729+ return implode( '/', $pieces );
 730+ }
 731+
669732
670733 }
671734

Status & tagging log