Foxtrott has uploaded a new change for review. https://gerrit.wikimedia.org/r/59072
Change subject: Adds EXIF data to media files ...................................................................... Adds EXIF data to media files For files which have EXIF data this patch creates a subobject and stores the EXIF data in it. Change-Id: I343ab8f4df511fe7a9e8e3bebb47f12927a57b71 --- M SemanticExtraSpecialProperties.hooks.php M SemanticExtraSpecialProperties.i18n.php M SemanticExtraSpecialProperties.php 3 files changed, 592 insertions(+), 358 deletions(-) git pull ssh://gerrit.wikimedia.org:29418/mediawiki/extensions/SemanticExtraSpecialProperties refs/changes/72/59072/1 diff --git a/SemanticExtraSpecialProperties.hooks.php b/SemanticExtraSpecialProperties.hooks.php index 2b57ff2..fbd98ae 100644 --- a/SemanticExtraSpecialProperties.hooks.php +++ b/SemanticExtraSpecialProperties.hooks.php @@ -1,394 +1,625 @@ <?php /** - * Helper class for implementing core functionality + * Helper class for implementing core functionality * - * @author Leo Wallentin, mwjames + * @author Leo Wallentin, mwjames, Stephan Gambke */ class SemanticESP { - /** - * @brief Initializes all properties, hooks into smwInitProperties. - * - * @return true - */ - public static function sespInitProperties() { + static private $mPropertyTypesToExifTags = array( + '_num' => array( + 'OriginalImageHeight', + 'OriginalImageWidth', + 'PixelXDimension', + 'PixelYDimension', + 'ImageWidth', + 'ImageLength', + 'Rating', + ), + '_dat' => array( + 'DateTime', + 'DateTimeOriginal', + 'DateTimeDigitized', + 'DateTimeReleased', + 'DateTimeExpires', + 'GPSDateStamp', + 'dc-date', + 'DateTimeMetadata', + ), + '_txt' => array( + 'Compression', + 'PhotometricInterpretation', + 'Orientation', + 'PlanarConfiguration', + 'YCbCrPositioning', + 'XResolution', + 'YResolution', + 'ExifVersion', + 'FlashpixVersion', + 'ColorSpace', + 'ComponentsConfiguration', + 'ExposureProgram', + 'SubjectDistance', + 'MeteringMode', + 'LightSource', + 'Flash', + 'FocalPlaneResolutionUnit', + 'SensingMethod', + 'FileSource', + 'SceneType', + 'CustomRendered', + 'ExposureMode', + 'WhiteBalance', + 'SceneCaptureType', + 'GainControl', + 'Contrast', + 'Saturation', + 'Sharpness', + 'SubjectDistanceRange', + 'Make', + 'Model', + 'Software', + 'ExposureTime', + 'ISOSpeedRatings', + 'FNumber', + 'FocalLength', + 'FocalLengthIn35mmFilm', + 'MaxApertureValue', + 'iimCategory', + 'SubjectNewsCode', + 'Urgency', + 'ImageDescription', + 'Artist', + 'Copyright', + 'RelatedSoundFile', + 'ImageUniqueID', + 'SpectralSensitivity', + 'GPSSatellites', + 'GPSVersionID', + 'GPSMapDatum', + 'Keywords', + 'WorldRegionDest', + 'CountryDest', + 'CountryCodeDest', + 'ProvinceOrStateDest', + 'CityDest', + 'SublocationDest', + 'WorldRegionCreated', + 'CountryCreated', + 'CountryCodeCreated', + 'ProvinceOrStateCreated', + 'CityCreated', + 'SublocationCreated', + 'ObjectName', + 'SpecialInstructions', + 'Headline', + 'Credit', + 'Source', + 'EditStatus', + 'FixtureIdentifier', + 'LocationDest', + 'LocationDestCode', + 'Writer', + 'JPEGFileComment', + 'iimSupplementalCategory', + 'OriginalTransmissionRef', + 'Identifier', + 'dc-contributor', + 'dc-coverage', + 'dc-publisher', + 'dc-relation', + 'dc-rights', + 'dc-source', + 'dc-type', + 'Lens', + 'SerialNumber', + 'CameraOwnerName', + 'Label', + 'Nickname', + 'RightsCertificate', + 'CopyrightOwner', + 'UsageTerms', + 'WebStatement', + 'OriginalDocumentID', + 'LicenseUrl', + 'MorePermissionsUrl', + 'AttributionUrl', + 'PreferredAttributionName', + 'PNGFileComment', + 'Disclaimer', + 'ContentWarning', + 'GIFFileComment', + 'SceneCode', + 'IntellectualGenre', + 'Event', + 'OrginisationInImage', + 'PersonInImage', + 'ObjectCycle', + 'Copyrighted', + 'LanguageCode', + ), + ); - // Page author - SMWDIProperty::registerProperty( '___EUSER', '_wpg', - wfMsgForContent('sesp-property-author') ); - SMWDIProperty::registerPropertyAlias( '___EUSER', 'Page author' ); + /** + * @brief Initializes all properties, hooks into smwInitProperties. + * + * @return true + */ + public static function sespInitProperties() { - // Page creator - SMWDIProperty::registerProperty( '___CUSER', '_wpg', - wfMsgForContent('sesp-property-first-author') ); - SMWDIProperty::registerPropertyAlias( '___CUSER', 'Page creator' ); + // Page author + SMWDIProperty::registerProperty( '___EUSER', '_wpg', wfMsgForContent( 'sesp-property-author' ) ); + SMWDIProperty::registerPropertyAlias( '___EUSER', 'Page author' ); - // Revision ID - SMWDIProperty::registerProperty( '___REVID', '_num', - wfMsgForContent('sesp-property-revision-id') ); - SMWDIProperty::registerPropertyAlias( '___REVID', 'Revision ID' ); + // Page creator + SMWDIProperty::registerProperty( '___CUSER', '_wpg', wfMsgForContent( 'sesp-property-first-author' ) ); + SMWDIProperty::registerPropertyAlias( '___CUSER', 'Page creator' ); - //View count - SMWDIProperty::registerProperty( '___VIEWS', '_num', - wfMsgForContent('sesp-property-view-count') ); - SMWDIProperty::registerPropertyAlias( '___VIEWS', 'Number of page views' ); + // Revision ID + SMWDIProperty::registerProperty( '___REVID', '_num', wfMsgForContent( 'sesp-property-revision-id' ) ); + SMWDIProperty::registerPropertyAlias( '___REVID', 'Revision ID' ); - //Sub pages - SMWDIProperty::registerProperty( '___SUBP', '_wpg', - wfMsgForContent('sesp-property-subpages') ); - SMWDIProperty::registerPropertyAlias( '___SUBP', 'Subpage' ); + // View count + SMWDIProperty::registerProperty( '___VIEWS', '_num', wfMsgForContent( 'sesp-property-view-count' ) ); + SMWDIProperty::registerPropertyAlias( '___VIEWS', 'Number of page views' ); - //Number of revisions - SMWDIProperty::registerProperty( '___NREV', '_num', - wfMsgForContent('sesp-property-revisions') ); - SMWDIProperty::registerPropertyAlias( '___NREV', 'Number of revisions' ); + // Sub pages + SMWDIProperty::registerProperty( '___SUBP', '_wpg', wfMsgForContent( 'sesp-property-subpages' ) ); + SMWDIProperty::registerPropertyAlias( '___SUBP', 'Subpage' ); - //Number of talk page revisions - SMWDIProperty::registerProperty( '___NTREV', '_num', - wfMsgForContent('sesp-property-talk-revisions') ); - SMWDIProperty::registerPropertyAlias( '___NTREV', 'Number of talk page revisions' ); + // Number of revisions + SMWDIProperty::registerProperty( '___NREV', '_num', wfMsgForContent( 'sesp-property-revisions' ) ); + SMWDIProperty::registerPropertyAlias( '___NREV', 'Number of revisions' ); - // MIME type - SMWDIProperty::registerProperty( '___MIMETYPE', '_str', - wfMsgForContent('sesp-property-mimetype') ); - SMWDIProperty::registerPropertyAlias( '___MIMETYPE', 'MIME type' ); + // Number of talk page revisions + SMWDIProperty::registerProperty( '___NTREV', '_num', wfMsgForContent( 'sesp-property-talk-revisions' ) ); + SMWDIProperty::registerPropertyAlias( '___NTREV', 'Number of talk page revisions' ); - // MIME type - SMWDIProperty::registerProperty( '___MEDIATYPE', '_str', - wfMsgForContent('sesp-property-mediatype') ); - SMWDIProperty::registerPropertyAlias( '___MEDIATYPE', 'Media type' ); + // MIME type + SMWDIProperty::registerProperty( '___MIMETYPE', '_txt', wfMsgForContent( 'sesp-property-mimetype' ) ); + SMWDIProperty::registerPropertyAlias( '___MIMETYPE', 'MIME type' ); - // SHORTURL type - SMWDIProperty::registerProperty( '___SHORTURL', '_uri', - wfMsgForContent('sesp-property-shorturl') ); - SMWDIProperty::registerPropertyAlias( '___SHORTURL', 'Short URL' ); + // MIME type + SMWDIProperty::registerProperty( '___MEDIATYPE', '_txt', wfMsgForContent( 'sesp-property-mediatype' ) ); + SMWDIProperty::registerPropertyAlias( '___MEDIATYPE', 'Media type' ); - // METADATA types - SMWDIProperty::registerProperty( '___EXIFDATETIME', '_dat', - wfMsgForContent('exif-datetimeoriginal') ); - SMWDIProperty::registerPropertyAlias( '___EXIFDATETIME', 'Exposure date' ); + // SHORTURL type + SMWDIProperty::registerProperty( '___SHORTURL', '_uri', wfMsgForContent( 'sesp-property-shorturl' ) ); + SMWDIProperty::registerPropertyAlias( '___SHORTURL', 'Short URL' ); - SMWDIProperty::registerProperty( '___EXIFSOFTWARE', '_str', - wfMsgForContent('exif-software') ); - SMWDIProperty::registerPropertyAlias( '___EXIFSOFTWARE', 'Software' ); + // User registration date + SMWDIProperty::registerProperty( '___USERREG', '_dat', wfMsgForContent( 'sesp-property-user-registration-date' ) ); + SMWDIProperty::registerPropertyAlias( '___USERREG', 'User registration date' ); - //User registration date - SMWDIProperty::registerProperty( '___USERREG', '_dat', - wfMsgForContent('sesp-property-user-registration-date') ); - SMWDIProperty::registerPropertyAlias( '___USERREG', 'User registration date' ); + // Image METADATA types + self::registerProperty( '___EXIFDATA', '_wpg', 'sesp-property-exif-data' ); + foreach ( self::$mPropertyTypesToExifTags as $type => $exifTags) { + foreach ( $exifTags as $exifTag ) { + self::registerExifProperty( $exifTag, $type ); + } + } + // Compatibility wit previous SESP versions + SMWDIProperty::registerPropertyAlias( '___EXIFDATETIMEORIGINAL', 'Exposure date' ); + SMWDIProperty::registerPropertyAlias( '___EXIFSOFTWARE', 'Software' ); - return true; - } // end sespInitProperties() + return true; + } // end sespInitProperties() - /** - * @brief Adds the properties, hooks into SMWStore::updateDataBefore. - * - * @param SMWStore $store - * @param SMWChangeSet $changes - * - * @return true - * - */ - public function sespUpdateDataBefore ( $store, $data ) { - global $sespSpecialProperties, $wgDisableCounters; + /** + * @brief Adds the properties, hooks into SMWStore::updateDataBefore. + * + * @param SMWStore $store + * @param SMWSemanticData $data + * + * @return true + * + */ + public static function sespUpdateDataBefore( SMWStore $store, SMWSemanticData $data ) { + global $sespSpecialProperties, $wgDisableCounters; - // just some compat mode - global $smwgPageSpecialProperties2; - if ( isset( $smwgPageSpecialProperties2) && !isset( $sespSpecialProperties ) ) - $sespSpecialProperties = $smwgPageSpecialProperties2; + // just some compat mode + global $smwgPageSpecialProperties2; - /* Get array of properties to set */ - if ( !isset( $sespSpecialProperties ) ) { - wfDebug( __METHOD__ . ": SESP array is not specified, please add the following\n" ); - wfDebug( "variables to your LocalSettings.php:\n" ); - wfDebug( "\$sespSpecialProperties\n" ); - return true; - } + if ( isset( $smwgPageSpecialProperties2 ) && !isset( $sespSpecialProperties ) ) { + $sespSpecialProperties = $smwgPageSpecialProperties2; + } - /* Get current title and wikipage */ - $subject = $data->getSubject(); - $title = Title::makeTitle( $subject->getNamespace(), $subject->getDBkey() ); - $wikipage = WikiPage::factory($title); + /* Get array of properties to set */ + if ( !isset( $sespSpecialProperties ) ) { + wfDebug( __METHOD__ . ": SESP array is not specified, please add the following\n" ); + wfDebug( "variables to your LocalSettings.php:\n" ); + wfDebug( "\$sespSpecialProperties\n" ); + return true; + } - // return if $title or $wikipage is null - if ( is_null( $title ) || is_null( $wikipage) ) { - return true; - } + /* Get current title and wikipage */ + $subject = $data->getSubject(); + $title = Title::makeTitle( $subject->getNamespace(), $subject->getDBkey() ); + $wikipage = WikiPage::factory( $title ); - /**************************/ - /* CUSER (First author) */ - /**************************/ - if ( in_array( '_CUSER', $sespSpecialProperties ) ) { + // return if $title or $wikipage is null + if ( is_null( $title ) || is_null( $wikipage ) ) { + return true; + } - // TODO: remove else branch when compatibility to MW pre1.20 is dropped - if ( method_exists( $wikipage, 'getCreator') ) { + /**************************/ + /* CUSER (First author) */ + /**************************/ + if ( in_array( '_CUSER', $sespSpecialProperties ) ) { - $firstAuthor = $wikipage->getCreator(); + // TODO: remove else branch when compatibility to MW pre1.20 is dropped + if ( method_exists( $wikipage, 'getCreator' ) ) { - } else { + $firstAuthor = $wikipage->getCreator(); + } else { - $firstRevision = $title->getFirstRevision(); - if ( $firstRevision !== null ) { - $firstAuthor = User::newFromId( $firstRevision->getRawUser () ); + $firstRevision = $title->getFirstRevision(); + + if ( $firstRevision !== null ) { + $firstAuthor = User::newFromId( $firstRevision->getRawUser() ); + } + } + + if ( $firstAuthor ) { + $property = new SMWDIProperty( '___CUSER' ); + $dataItem = SMWDIWikiPage::newFromTitle( $firstAuthor->getUserPage() ); + $data->addPropertyObjectValue( $property, $dataItem ); + } + } // end if _CUSER + + /**************************/ + /* REVID (Revision ID) */ + /**************************/ + if ( in_array( '_REVID', $sespSpecialProperties ) ) { + $property = new SMWDIProperty( '___REVID' ); + $dataItem = new SMWDINumber( $wikipage->getId() ); + $data->addPropertyObjectValue( $property, $dataItem ); + } + + /********************************/ + /* VIEWS (Number of page views) */ + /********************************/ + if ( in_array( '_VIEWS', $sespSpecialProperties ) && !$wgDisableCounters ) { + $property = new SMWDIProperty( '___VIEWS' ); + $dataItem = new SMWDINumber( $wikipage->getCount() ); + $data->addPropertyObjectValue( $property, $dataItem ); + } + + /*****************************/ + /* EUSER (Page contributors) */ + /*****************************/ + if ( in_array( '_EUSER', $sespSpecialProperties ) ) { + /* Create property */ + $property = new SMWDIProperty( '___EUSER' ); + /* Get options */ + global $wgSESPExcludeBots; + if ( !isset( $wgSESPExcludeBots ) ) + $wgSESPExcludeBots = false; + + /* Get author from current revision */ + $u = User::newFromId( $wikipage->getUser() ); + /* Get authors from earlier revisions */ + $authors = $wikipage->getContributors(); + + while ( $u ) { + if ( !( in_array( 'bot', $u->getRights() ) && $wgSESPExcludeBots ) // exclude bots? + && !$u->isAnon() ) { // no anonymous users (hidden users are not returned) + /* Add values */ + $dataItem = SMWDIWikiPage::newFromTitle( $u->getUserPage() ); + $data->addPropertyObjectValue( $property, $dataItem ); + }// if + $u = $authors->current(); + $authors->next(); + }// while u + } + + /******************************/ + /* NREV (Number of revisions) */ + /******************************/ + if ( in_array( '_NREV', $sespSpecialProperties ) ) { + /* Create property */ + $property = new SMWDIProperty( '___NREV' ); + /* Get number of revisions */ + $dbr =& wfGetDB( DB_SLAVE ); + $num = $dbr->estimateRowCount( "revision", "*", array( "rev_page" => $title->getArticleID() ) ); + + /* Add values */ + $dataItem = new SMWDINumber( $num ); + $data->addPropertyObjectValue( $property, $dataItem ); + } + + /*****************************************/ + /* NTREV (Number of talk page revisions) */ + /*****************************************/ + if ( in_array( '_NTREV', $sespSpecialProperties ) ) { + /* Create property */ + $property = new SMWDIProperty( '___NTREV' ); + /* Get number of revisions */ + if ( !isset( $dbr ) ){ + $dbr = & wfGetDB( DB_SLAVE ); + } + + $talkPage = $title->getTalkPage(); + $num = $dbr->estimateRowCount( "revision", "*", array( "rev_page" => $talkPage->getArticleID() ) ); + + /* Add values */ + $dataItem = new SMWDINumber( $num ); + $data->addPropertyObjectValue( $property, $dataItem ); + } + + /************************/ + /* SUBP (Get sub pages) */ + /************************/ + if ( in_array( '_SUBP', $sespSpecialProperties ) ) { + /* Create property */ + $property = new SMWDIProperty( '___SUBP' ); + $subpages = $title->getSubpages( -1 ); // -1 = no limit. Returns TitleArray object + + /* Add values */ + foreach ( $subpages as $t ) { + $dataItem = SMWDIWikiPage::newFromTitle( $t ); + $data->addPropertyObjectValue( $property, $dataItem ); + } // end foreach + } // end _SUBP + + /************************/ + /* MIMETYPE */ + /************************/ + if ( $title->inNamespace( NS_FILE ) && in_array( '_MIMETYPE', $sespSpecialProperties ) ) { + + // Build image page instance + $imagePage = new ImagePage( $title ); + $file = $imagePage->getFile(); + $mimetype = $file->getMimeType(); + $mediaType = MimeMagic::singleton()->findMediaType( $mimetype ); + list( $mimetypemajor, $mimetypeminor ) = $file->splitMime( $mimetype ); + + // MIMETYPE + $property = new SMWDIProperty( '___MIMETYPE' ); + $dataItem = new SMWDIString( $mimetypeminor ); + $data->addPropertyObjectValue( $property, $dataItem ); + + // MEDIATYPE + $property = new SMWDIProperty( '___MEDIATYPE' ); + $dataItem = new SMWDIString( $mediaType ); + $data->addPropertyObjectValue( $property, $dataItem ); + } // end if MIMETYPE + + /************************/ + /* IMAGEMETA */ + /************************/ + if ( in_array( '_METADATA', $sespSpecialProperties ) ) { + self::updateImageMetaData( $store, $data ); + } + + /************************/ + /* SHORTURL */ + /************************/ + // FIXME: handle internal and external links + + if ( in_array( '_SHORTURL', $sespSpecialProperties ) && class_exists( 'ShortUrlUtils' ) ) { + global $wgShortUrlPrefix; + + if ( !is_string( $wgShortUrlPrefix ) ) { + $urlPrefix = SpecialPage::getTitleFor( 'ShortUrl' )->getFullUrl() . '/'; + } else { + $urlPrefix = $wgShortUrlPrefix; + } + + if ( ShortUrlUtils::needsShortUrl( $title ) ) { + $shortId = ShortUrlUtils::encodeTitle( $title ); + $shortURL = $urlPrefix . $shortId; + + $property = new SMWDIProperty( '___SHORTURL' ); + $dataItem = new SMWDIUri( 'http', $shortURL, '', '' ); + + $data->addPropertyObjectValue( $property, $dataItem ); + } + + } // end if SHORTURL + + /************************/ + /* USERREG */ + /************************/ + + if ( in_array( '_USERREG', $sespSpecialProperties ) && $title->inNamespace( NS_USER ) ) { + + $property = new SMWDIProperty( '___USERREG' ); + + $u = User::newFromName( $title->getText() ); + if ( $u ) { + + $d = $u->getRegistration(); // Mediawiki timestamp (20110125223011) + $d = wfTimestamp( TS_ISO_8601, $d ); + $d = new DateTime( $d ); + + $dataItem = new SMWDITime( SMWDITime::CM_GREGORIAN, $d->format( 'Y' ), $d->format( 'm' ), $d->format( 'd' ), $d->format( 'H' ), $d->format( 'i' ) ); + $data->addPropertyObjectValue( $property, $dataItem ); + } + + } // end USERREG + + return true; + } // end sespUpdateDataBefore() + + /** + * @brief Adds the exif properties + * + * @param SMWStore $store + * @param SMWSemanticData $data + * + */ + public static function updateImageMetaData( SMWStore $store, SMWSemanticData $data ) { + + // Get current wikipage and title + $subject = $data->getSubject(); + $title = $subject->getTitle(); + + // return if not in File namespece + if ( !$title->inNamespace( NS_FILE ) ) { + return; + } + + // get exif data + $imagePage = new ImagePage( $title ); + $file = $imagePage->getFile(); + $exif = unserialize( $file->getMetadata() ); + + if ( !is_array( $exif ) || count( $exif ) === 0 ) { + return; + } + + $exif[ 'ImageWidth' ] = $file->getWidth(); + $exif[ 'ImageLength' ] = $file->getHeight(); + + $formattedExif = FormatMetadata::getFormattedData( $exif ); + + // log exif data to log if log group exif is specified + wfDebugLog( 'exif', "\n" . $title->getFullText() . "\nFORMATTED EXIF DATA: " . var_export($formattedExif, true), false ); + + // create semantic data container for EXIF data subobject + $diSubobject = new SMWDIWikiPage( + $subject->getDBkey(), + $subject->getNamespace(), + $subject->getInterwiki(), + 'EXIF_data' ); + + $subData = new SMWContainerSemanticData( $diSubobject ); + + // populate the container + + foreach ( $formattedExif as $key => $value ) { + + $propId = self::exifIdToPropId( $key ) ; + $propTypeId = SMWDIProperty::getPredefinedPropertyTypeId( $propId ); + + switch ( $propTypeId ) { + case '_dat': + + $val = $exif[$key]; + + if ( $val == '0000:00:00 00:00:00' || $val == ' : : : : ' ) { + // ignore unknown dates + continue 2; + } elseif ( preg_match( '/^(?:\d{4}):(?:\d\d):(?:\d\d) (?:\d\d):(?:\d\d):(?:\d\d)$/D', $val ) ) { + // Full date. Us as is. + } elseif ( preg_match( '/^(?:\d{4}):(?:\d\d):(?:\d\d) (?:\d\d):(?:\d\d)$/D', $val ) ) { + // No second field. Still format the same + // since timeanddate doesn't include seconds anyways, + // but second still available in api + $val .= ':00'; + } elseif ( preg_match( '/^(?:\d{4}):(?:\d\d):(?:\d\d)$/D', $val ) ) { + // If only the date but not the time is filled in. + $val = substr( $val, 0, 4 ) . ':' . + substr( $val, 5, 2 ) . ':' . + substr( $val, 8, 2 ) . ' 00:00:00'; + } else { + // continue and try to parse anyway + } + + $datetime = new DateTime( $val ); + + if ( $datetime ) { + $dataItem = new SMWDITime( + SMWDITime::CM_GREGORIAN, + $datetime->format( 'Y' ), + $datetime->format( 'n' ), + $datetime->format( 'j' ), + $datetime->format( 'G' ), + $datetime->format( 'i' ), + $datetime->format( 's' ) + ); + } else { + continue 2; + } + + break; + case '_txt': + $dataItem = new SMWDIBlob( $value ); + break; + case '_num': + $dataItem = new SMWDINumber( $exif[$key] ); + break; + default: + continue 2; // need to exit 2 levels, PHP considers switch a loop o_O + } + + $property = new SMWDIProperty( $propId ); + $subData->addPropertyObjectValue( $property, $dataItem ); + } + +// // EXIFLATLON +// /* +// //TODO +// if ( array_key_exists( 'GPSLatitudeRef', $exif ) || array_key_exists( 'GPSLongitudeRef', $exif ) ) { +// } */// EXIFLATLON + + $data->addSubSemanticData( $subData ); + + // Store subobject to the semantic data instance + $data->addPropertyObjectValue( + new SMWDIProperty( SMWDIProperty::TYPE_SUBOBJECT ), new SMWDIContainer( $subData ) + ); + + $data->addPropertyObjectValue( + new SMWDIProperty( '___EXIFDATA' ), //SMWDIProperty( SMWDIProperty::TYPE_WIKIPAGE ), + $diSubobject + ); } - } + /** + * Registers a predefined property for SMW. + * + * This method registers a property with the given id using the message + * in the wiki content language identified by the msgKey as property name. + * The message in English is registered as an alias property name. + * + * For backward compatibility an alternative alias may be registered. + * TODO: Remove alternative alias in some future version + * + * @since 0.2.8 + * + * @param string $id property id + * @param string $typeid SMW type id + * @param string $msgKey lookup key for the message used as property name + * @param String $altAlias alternative alias + */ + protected static function registerProperty ( $id, $typeid, $msgKey, $altAlias = null ) { - if ($firstAuthor) { - $property = new SMWDIProperty( '___CUSER' ); - $dataItem = SMWDIWikiPage::newFromTitle( $firstAuthor->getUserPage() ); - $data->addPropertyObjectValue( $property, $dataItem ); - } + $message = wfMessage( $msgKey ); + SMWDIProperty::registerProperty( $id, $typeid, $message->text(), true ); - } // end if _CUSER + $message->inLanguage( 'en' ); + SMWDIProperty::registerPropertyAlias( $id, $message->text() ); - /**************************/ - /* REVID (Revision ID) */ - /**************************/ - if ( in_array( '_REVID', $sespSpecialProperties ) ) { - $property = new SMWDIProperty( '___REVID' ); - $dataItem = new SMWDINumber( $wikipage->getId() ); - $data->addPropertyObjectValue( $property, $dataItem ); - } - - /********************************/ - /* VIEWS (Number of page views) */ - /********************************/ - if ( in_array( '_VIEWS', $sespSpecialProperties ) && !$wgDisableCounters ) { - $property = new SMWDIProperty( '___VIEWS' ); - $dataItem = new SMWDINumber( $wikipage->getCount() ); - $data->addPropertyObjectValue ( $property, $dataItem ); - } - - /*****************************/ - /* EUSER (Page contributors) */ - /*****************************/ - if ( in_array( '_EUSER', $sespSpecialProperties ) ) { - /* Create property */ - $property = new SMWDIProperty( '___EUSER' ); - /* Get options */ - global $wgSESPExcludeBots; - if ( !isset( $wgSESPExcludeBots ) ) - $wgSESPExcludeBots = false; - - /* Get author from current revision */ - $u = User::newFromId( $wikipage->getUser() ); - /* Get authors from earlier revisions */ - $authors = $wikipage->getContributors(); - - while ( $u ) { - if ( !(in_array( 'bot', $u->getRights() ) && $wgSESPExcludeBots) //exclude bots? - && !$u->isAnon() ) { //no anonymous users (hidden users are not returned) - /* Add values*/ - $dataItem = SMWDIWikiPage::newFromTitle( $u->getUserPage() ); - $data->addPropertyObjectValue( $property, $dataItem ); - }//if - $u = $authors->current(); - $authors->next(); - }//while u - } - - /******************************/ - /* NREV (Number of revisions) */ - /******************************/ - if ( in_array( '_NREV', $sespSpecialProperties ) ) { - /* Create property */ - $property = new SMWDIProperty( '___NREV' ); - /* Get number of revisions */ - $dbr =& wfGetDB( DB_SLAVE ); - $num = $dbr->estimateRowCount( "revision", "*", array( "rev_page" => $title->getArticleID() ) ); - - /* Add values */ - $dataItem = new SMWDINumber( $num ); - $data->addPropertyObjectValue ( $property, $dataItem ); - } - - /*****************************************/ - /* NTREV (Number of talk page revisions) */ - /*****************************************/ - if ( in_array( '_NTREV', $sespSpecialProperties ) ) { - /* Create property */ - $property = new SMWDIProperty( '___NTREV' ); - /* Get number of revisions */ - if ( !isset( $dbr ) ) - $dbr =& wfGetDB( DB_SLAVE ); - $talkPage = $title->getTalkPage (); - $num = $dbr->estimateRowCount( "revision", "*", array( "rev_page" => $talkPage->getArticleID() ) );; - - /* Add values */ - $dataItem = new SMWDINumber( $num ); - $data->addPropertyObjectValue( $property, $dataItem ); - } - - /************************/ - /* SUBP (Get sub pages) */ - /************************/ - if ( in_array( '_SUBP', $sespSpecialProperties ) ) { - /* Create property */ - $property = new SMWDIProperty( '___SUBP' ); - $subpages = $title->getSubpages ( -1 ); //-1 = no limit. Returns TitleArray object - - /* Add values*/ - foreach ( $subpages as $t ) { - $dataItem = SMWDIWikiPage::newFromTitle( $t ); - $data->addPropertyObjectValue( $property, $dataItem ); - } // end foreach - } // end _SUBP - - /************************/ - /* MIMETYPE */ - /************************/ - if ( $title->inNamespace( NS_FILE ) && in_array( '_MIMETYPE', $sespSpecialProperties ) ) { - - // Build image page instance - $imagePage = new ImagePage( $title ); - $file = $imagePage->getFile(); - $mimetype = $file->getMimeType(); - $mediaType = MimeMagic::singleton()->findMediaType($mimetype); - list( $mimetypemajor, $mimetypeminor ) = $file->splitMime($mimetype); - - // MIMETYPE - $property = new SMWDIProperty( '___MIMETYPE' ); - $dataItem = new SMWDIString( $mimetypeminor ); - $data->addPropertyObjectValue ($property, $dataItem); - - // MEDIATYPE - $property = new SMWDIProperty( '___MEDIATYPE' ); - $dataItem = new SMWDIString( $mediaType ); - $data->addPropertyObjectValue ($property, $dataItem); - - } // end if MIMETYPE - - /************************/ - /* IMAGEMETA */ - /************************/ - - if ( $title->inNamespace( NS_FILE ) && in_array( '_METADATA', $sespSpecialProperties ) ) { - $imagePage = new ImagePage( $title ); - $file = $imagePage->getFile(); - $metadata = $file->getMetadata(); - - - if ( $metadata === ExifBitmapHandler::OLD_BROKEN_FILE || - $metadata === ExifBitmapHandler::BROKEN_FILE /*|| - ExifBitmapHandler::isMetadataValid( $file, $metadata ) === ExifBitmapHandler::METADATA_BAD //Too picky... */ ) { - // So we don't try and display metadata from PagedTiffHandler - // for example when using InstantCommons. - return true; - } - - $exif = unserialize( $metadata ); - if ( $exif ) { - if ( count( $exif ) ) { - - // EXIFDATETIME - if ( array_key_exists( 'DateTimeOriginal', $exif ) || array_key_exists( 'DateTime', $exif ) ) { - $property = new SMWDIProperty( '___EXIFDATETIME' ); - if ( array_key_exists( 'DateTimeOriginal', $exif ) ) { - $exifstr = $exif['DateTimeOriginal']; - } else { - $exifstr = $exif['DateTime']; - } - $datetime = self::convertexifdate( $exifstr ); - - if ( $datetime ) { - $dataItem = new SMWDITime( SMWDITime::CM_GREGORIAN, $datetime->format('Y'), $datetime->format('n'), $datetime->format('j'), $datetime->format('G'), $datetime->format('i') ); - $data->addPropertyObjectValue ($property, $dataItem); - } - } - - // EXIFSOFTWARE - if ( array_key_exists( 'Software', $exif ) || ( array_key_exists( 'metadata', $exif ) && array_key_exists( 'Software', $exif['metadata'] )) ) { - - $str = array_key_exists( 'Software', $exif ) ? $exif['Software'] : $exif['metadata']['Software']; - if ( is_array( $str) ) { - $str = array_key_exists( 'x-default', $str ) ? $str['x-default'] : $str[0]; - } - if ( !$str ) - return true; - - $property = new SMWDIProperty( '___EXIFSOFTWARE' ); - $dataItem = new SMWDIString( $str ); - $data->addPropertyObjectValue ($property, $dataItem); - } - - // EXIFLATLON -/* -//TODO - if ( array_key_exists( 'GPSLatitudeRef', $exif ) || array_key_exists( 'GPSLongitudeRef', $exif ) ) { - } *///EXIFLATLON - - } - } - }//IMAGEMETA - - /************************/ - /* SHORTURL */ - /************************/ -//FIXME handle internal and external links - - if ( in_array( '_SHORTURL', $sespSpecialProperties ) && class_exists( 'ShortUrlUtils' ) ) { - global $wgShortUrlPrefix; - - if ( !is_string( $wgShortUrlPrefix ) ) { - $urlPrefix = SpecialPage::getTitleFor( 'ShortUrl' )->getFullUrl() . '/'; - } else { - $urlPrefix = $wgShortUrlPrefix; - } - - if ( ShortUrlUtils::needsShortUrl( $title ) ) { - $shortId = ShortUrlUtils::encodeTitle( $title ); - $shortURL = $urlPrefix . $shortId; - - $property = new SMWDIProperty( '___SHORTURL' ); - $dataItem = new SMWDIUri( 'http', $shortURL, '', '' ); - - $data->addPropertyObjectValue ($property, $dataItem); - } else { - } - - } // end if SHORTURL - - /************************/ - /* USERREG */ - /************************/ - - if ( in_array( '_USERREG', $sespSpecialProperties ) && $title->inNamespace( NS_USER ) ) { - - $property = new SMWDIProperty( '___USERREG' ); - - $u = User::newFromName($title->getText()); - if ( $u ) { - - $d = $u->getRegistration(); // Mediawiki timestamp (20110125223011) - $d = wfTimestamp( TS_ISO_8601, $d ); - $d = new DateTime($d); - - $dataItem = new SMWDITime ( SMWDITime::CM_GREGORIAN,$d->format('Y'),$d->format('m'),$d->format('d'),$d->format('H'),$d->format('i') ); - $data->addPropertyObjectValue ($property, $dataItem); - + if ( $altAlias !== null ) { + SMWDIProperty::registerPropertyAlias( $id, $altAlias ); + } } - } // end USERREG + protected static function exifIdToPropId ( $exifId ) { + return '___EXIF' . strtoupper($exifId); + } - - return true; - } // end sespUpdateDataBefore() + protected static function registerExifProperty ( $exifId, $typeid, $altAlias = null ) { + self::registerProperty( self::exifIdToPropId( $exifId ), $typeid, 'exif-' . strtolower($exifId), $altAlias); + } - - /* Make Exif dates something SMW can store */ - function convertexifdate ( $exifString ) { - $exifPieces = explode(":", $exifString); - if ( $exifPieces[0] && $exifPieces[1] && $exifPieces[2] ) { - $res = new DateTime($exifPieces[0] . "-" . $exifPieces[1] . - "-" . $exifPieces[2] . ":" . $exifPieces[3] . ":" . $exifPieces[4]); - return $res; - } else { - return false; - } - } + /** + * Make Exif dates something SMW can store + */ + protected static function convertexifdate( $exifString ) { + $exifPieces = explode( ":", $exifString ); + if ( $exifPieces[0] && $exifPieces[1] && $exifPieces[2] ) { + $res = new DateTime( $exifPieces[0] . "-" . $exifPieces[1] . + "-" . $exifPieces[2] . ":" . $exifPieces[3] . ":" . $exifPieces[4] ); + return $res; + } else { + return false; + } + } } // end of class SemanticESP diff --git a/SemanticExtraSpecialProperties.i18n.php b/SemanticExtraSpecialProperties.i18n.php index 1ee3025..c3ca5cc 100644 --- a/SemanticExtraSpecialProperties.i18n.php +++ b/SemanticExtraSpecialProperties.i18n.php @@ -25,6 +25,8 @@ 'sesp-property-mediatype' => 'Media type', 'sesp-property-shorturl' => 'Short URL', 'sesp-property-user-registration-date' => 'User registration date', + + 'sesp-property-exif-data' => 'EXIF data', ); /** Message documentation (Message documentation) @@ -45,6 +47,8 @@ 'sesp-property-mediatype' => 'The name of the special property that stores the media type of a file', 'sesp-property-shorturl' => 'The name of the special property that stores the short URL of a page, if the extensions ShortURL is installed', 'sesp-property-user-registration-date' => 'The name of the special property that stores a users registration date on a user page', + + 'sesp-property-exif-data' => 'The name of the special property that stores a reference to the EXIF data of a file', ); /** Breton (brezhoneg) diff --git a/SemanticExtraSpecialProperties.php b/SemanticExtraSpecialProperties.php index 0ac999a..b7a1ec7 100644 --- a/SemanticExtraSpecialProperties.php +++ b/SemanticExtraSpecialProperties.php @@ -21,7 +21,7 @@ die( '<b>Error:</b> This version of Semantic Extra Special Properties requires MediaWiki 1.19 or above.' ); } -if ( ! defined( 'SMW_VERSION' ) ) { +if ( !defined( 'SMW_VERSION' ) ) { die( '<b>Error:</b> This version of Semantic Extra Special Properties requires <a href="http://semantic-mediawiki.org/wiki/Semantic_MediaWiki">Semantic MediaWiki</a> installed.<br />' ); } @@ -29,7 +29,7 @@ die( '<b>Error:</b> This version of Semantic Extra Special Properties requires Semantic MediaWiki 1.7 or above.' ); } -define( 'SESP_VERSION', '0.2.7' ); +define( 'SESP_VERSION', '0.2.8 alpha' ); $wgExtensionCredits['semantic'][] = array( 'path' => __FILE__, @@ -43,13 +43,12 @@ $dir = dirname( __FILE__ ) . '/'; /** - * Message class - */ -$wgExtensionMessagesFiles['SemanticESP' ] = $dir . 'SemanticExtraSpecialProperties.i18n.php'; + * Message class + */ +$wgExtensionMessagesFiles['SemanticESP'] = $dir . 'SemanticExtraSpecialProperties.i18n.php'; -$wgAutoloadClasses[ 'SemanticESP' ] = $dir . 'SemanticExtraSpecialProperties.hooks.php'; +$wgAutoloadClasses['SemanticESP'] = $dir . 'SemanticExtraSpecialProperties.hooks.php'; /* Hook into SMW */ -$wgHooks['smwInitProperties' ][] = 'SemanticESP::sespInitProperties'; +$wgHooks['smwInitProperties'][] = 'SemanticESP::sespInitProperties'; $wgHooks['SMWStore::updateDataBefore'][] = 'SemanticESP::sespUpdateDataBefore'; - -- To view, visit https://gerrit.wikimedia.org/r/59072 To unsubscribe, visit https://gerrit.wikimedia.org/r/settings Gerrit-MessageType: newchange Gerrit-Change-Id: I343ab8f4df511fe7a9e8e3bebb47f12927a57b71 Gerrit-PatchSet: 1 Gerrit-Project: mediawiki/extensions/SemanticExtraSpecialProperties Gerrit-Branch: master Gerrit-Owner: Foxtrott <s7ep...@gmail.com> _______________________________________________ MediaWiki-commits mailing list MediaWiki-commits@lists.wikimedia.org https://lists.wikimedia.org/mailman/listinfo/mediawiki-commits