summaryrefslogtreecommitdiff
path: root/includes/media/FormatMetadata.php
diff options
context:
space:
mode:
Diffstat (limited to 'includes/media/FormatMetadata.php')
-rw-r--r--includes/media/FormatMetadata.php98
1 files changed, 64 insertions, 34 deletions
diff --git a/includes/media/FormatMetadata.php b/includes/media/FormatMetadata.php
index 43569539..501bb9c2 100644
--- a/includes/media/FormatMetadata.php
+++ b/includes/media/FormatMetadata.php
@@ -1595,11 +1595,8 @@ class FormatMetadata extends ContextSource {
public function fetchExtendedMetadata( File $file ) {
global $wgMemc;
- wfProfileIn( __METHOD__ );
-
// If revision deleted, exit immediately
if ( $file->isDeleted( File::DELETED_FILE ) ) {
- wfProfileOut( __METHOD__ );
return array();
}
@@ -1614,7 +1611,7 @@ class FormatMetadata extends ContextSource {
$cachedValue = $wgMemc->get( $cacheKey );
if (
$cachedValue
- && wfRunHooks( 'ValidateExtendedMetadataCache', array( $cachedValue['timestamp'], $file ) )
+ && Hooks::run( 'ValidateExtendedMetadataCache', array( $cachedValue['timestamp'], $file ) )
) {
$extendedMetadata = $cachedValue['data'];
} else {
@@ -1624,17 +1621,16 @@ class FormatMetadata extends ContextSource {
if ( $this->singleLang ) {
$this->resolveMultilangMetadata( $extendedMetadata );
}
+ $this->discardMultipleValues( $extendedMetadata );
// Make sure the metadata won't break the API when an XML format is used.
// This is an API-specific function so it would be cleaner to call it from
// outside fetchExtendedMetadata, but this way we don't need to redo the
// computation on a cache hit.
- $this->sanitizeArrayForXml( $extendedMetadata );
+ $this->sanitizeArrayForAPI( $extendedMetadata );
$valueToCache = array( 'data' => $extendedMetadata, 'timestamp' => wfTimestampNow() );
$wgMemc->set( $cacheKey, $valueToCache, $maxCacheTime );
}
- wfProfileOut( __METHOD__ );
-
return $extendedMetadata;
}
@@ -1656,8 +1652,6 @@ class FormatMetadata extends ContextSource {
return $file->getExtendedMetadata() ?: array();
}
- wfProfileIn( __METHOD__ );
-
$uploadDate = wfTimestamp( TS_ISO_8601, $file->getTimestamp() );
$fileMetadata = array(
@@ -1685,19 +1679,6 @@ class FormatMetadata extends ContextSource {
);
}
- $common = $file->getCommonMetaArray();
-
- if ( $common !== false ) {
- foreach ( $common as $key => $value ) {
- $fileMetadata[$key] = array(
- 'value' => $value,
- 'source' => 'file-metadata',
- );
- }
- }
-
- wfProfileOut( __METHOD__ );
-
return $fileMetadata;
}
@@ -1714,9 +1695,8 @@ class FormatMetadata extends ContextSource {
protected function getExtendedMetadataFromHook( File $file, array $extendedMetadata,
&$maxCacheTime
) {
- wfProfileIn( __METHOD__ );
- wfRunHooks( 'GetExtendedMetadata', array(
+ Hooks::run( 'GetExtendedMetadata', array(
&$extendedMetadata,
$file,
$this->getContext(),
@@ -1731,8 +1711,6 @@ class FormatMetadata extends ContextSource {
}
}
- wfProfileOut( __METHOD__ );
-
return $extendedMetadata;
}
@@ -1777,6 +1755,32 @@ class FormatMetadata extends ContextSource {
}
/**
+ * Turns an XMP-style multivalue array into a single value by dropping all but the first value.
+ * If the value is not a multivalue array (or a multivalue array inside a multilang array), it is returned unchanged.
+ * See mediawiki.org/wiki/Manual:File_metadata_handling#Multi-language_array_format
+ * @param mixed $value
+ * @return mixed The value, or the first value if there were multiple ones
+ * @since 1.25
+ */
+ protected function resolveMultivalueValue( $value ) {
+ if ( !is_array( $value ) ) {
+ return $value;
+ } elseif ( isset( $value['_type'] ) && $value['_type'] === 'lang' ) { // if this is a multilang array, process fields separately
+ $newValue = array();
+ foreach ( $value as $k => $v ) {
+ $newValue[$k] = $this->resolveMultivalueValue( $v );
+ }
+ return $newValue;
+ } else { // _type is 'ul' or 'ol' or missing in which case it defaults to 'ul'
+ list( $k, $v ) = each( $value );
+ if ( $k === '_type' ) {
+ $v = current( $value );
+ }
+ return $v;
+ }
+ }
+
+ /**
* Takes an array returned by the getExtendedMetadata* functions,
* and resolves multi-language values in it.
* @param array $metadata
@@ -1794,18 +1798,40 @@ class FormatMetadata extends ContextSource {
}
/**
+ * Takes an array returned by the getExtendedMetadata* functions,
+ * and turns all fields into single-valued ones by dropping extra values.
+ * @param array $metadata
+ * @since 1.25
+ */
+ protected function discardMultipleValues( &$metadata ) {
+ if ( !is_array( $metadata ) ) {
+ return;
+ }
+ foreach ( $metadata as $key => &$field ) {
+ if ( $key === 'Software' || $key === 'Contact' ) {
+ // we skip some fields which have composite values. They are not particularly interesting
+ // and you can get them via the metadata / commonmetadata APIs anyway.
+ continue;
+ }
+ if ( isset( $field['value'] ) ) {
+ $field['value'] = $this->resolveMultivalueValue( $field['value'] );
+ }
+ }
+
+ }
+
+ /**
* Makes sure the given array is a valid API response fragment
- * (can be transformed into XML)
* @param array $arr
*/
- protected function sanitizeArrayForXml( &$arr ) {
+ protected function sanitizeArrayForAPI( &$arr ) {
if ( !is_array( $arr ) ) {
return;
}
$counter = 1;
foreach ( $arr as $key => &$value ) {
- $sanitizedKey = $this->sanitizeKeyForXml( $key );
+ $sanitizedKey = $this->sanitizeKeyForAPI( $key );
if ( $sanitizedKey !== $key ) {
if ( isset( $arr[$sanitizedKey] ) ) {
// Make the sanitized keys hopefully unique.
@@ -1819,20 +1845,24 @@ class FormatMetadata extends ContextSource {
unset( $arr[$key] );
}
if ( is_array( $value ) ) {
- $this->sanitizeArrayForXml( $value );
+ $this->sanitizeArrayForAPI( $value );
}
}
+
+ // Handle API metadata keys (particularly "_type")
+ $keys = array_filter( array_keys( $arr ), 'ApiResult::isMetadataKey' );
+ if ( $keys ) {
+ ApiResult::setPreserveKeysList( $arr, $keys );
+ }
}
/**
- * Turns a string into a valid XML identifier.
- * Used to ensure that keys of an associative array in the
- * API response do not break the XML formatter.
+ * Turns a string into a valid API identifier.
* @param string $key
* @return string
* @since 1.23
*/
- protected function sanitizeKeyForXml( $key ) {
+ protected function sanitizeKeyForAPI( $key ) {
// drop all characters which are not valid in an XML tag name
// a bunch of non-ASCII letters would be valid but probably won't
// be used so we take the easy way