| Current File : /home/jvzmxxx/wiki1/extensions/Wikibase/repo/includes/LinkedData/EntityDataFormatProvider.php |
<?php
namespace Wikibase\Repo\LinkedData;
use ApiMain;
use DerivativeContext;
use DerivativeRequest;
use RequestContext;
use Wikimedia\Purtle\RdfWriterFactory;
/**
* Service for getting information about supported data formats.
*
* @since 0.5
*
* @license GPL-2.0+
* @author Daniel Kinzler
* @author Thomas Pellissier Tanon
* @author Anja Jentzsch < anja.jentzsch@wikimedia.de >
* @author Marius Hoch < hoo@online.de >
*/
class EntityDataFormatProvider {
/**
* White list of supported formats.
*
* @var string[]|null
*/
private $formatWhiteList = null;
/**
* @var null|array Associative array from MIME type to format name
* @note: initialized by initFormats()
*/
private $mimeTypes = null;
/**
* @var null|array Associative array from file extension to format name
* @note: initialized by initFormats()
*/
private $fileExtensions = null;
/**
* @var RdfWriterFactory
*/
private $rdfWriterFactory;
public function __construct() {
$this->rdfWriterFactory = new RdfWriterFactory();
}
/**
* @param string[]|null $formatWhiteList
*/
public function setFormatWhiteList( array $formatWhiteList = null ) {
$this->formatWhiteList = $formatWhiteList;
// force re-init of format maps
$this->fileExtensions = null;
$this->mimeTypes = null;
}
/**
* @return string[]|null
*/
public function getFormatWhiteList() {
return $this->formatWhiteList;
}
/**
* Returns the list of supported MIME types that can be used to specify the
* output format.
*
* @return string[]
*/
public function getSupportedMimeTypes() {
$this->initFormats();
return array_keys( $this->mimeTypes );
}
/**
* Returns the list of supported file extensions that can be used
* to specify a format.
*
* @return string[]
*/
public function getSupportedExtensions() {
$this->initFormats();
return array_keys( $this->fileExtensions );
}
/**
* Returns the list of supported formats using their canonical names.
*
* @return string[]
*/
public function getSupportedFormats() {
$this->initFormats();
return array_unique( array_merge(
array_values( $this->mimeTypes ),
array_values( $this->fileExtensions )
) );
}
/**
* Returns a canonical format name. Used to normalize the format identifier.
*
* @param string $format the format as a file extension or MIME type.
*
* @return string|null the canonical format name, or null of the format is not supported
*/
public function getFormatName( $format ) {
$this->initFormats();
$format = trim( strtolower( $format ) );
if ( array_key_exists( $format, $this->mimeTypes ) ) {
return $this->mimeTypes[$format];
}
if ( array_key_exists( $format, $this->fileExtensions ) ) {
return $this->fileExtensions[$format];
}
if ( in_array( $format, $this->mimeTypes ) ) {
return $format;
}
if ( in_array( $format, $this->fileExtensions ) ) {
return $format;
}
return null;
}
/**
* Returns a file extension suitable for $format, or null if no such extension is known.
*
* @param string $format A canonical format name, as returned by getFormatName() or getSupportedFormats().
*
* @return string|null
*/
public function getExtension( $format ) {
$this->initFormats();
$ext = array_search( $format, $this->fileExtensions );
return $ext === false ? null : $ext;
}
/**
* Returns a MIME type suitable for $format, or null if no such extension is known.
*
* @param string $format A canonical format name, as returned by getFormatName() or getSupportedFormats().
*
* @return string|null
*/
public function getMimeType( $format ) {
$this->initFormats();
$type = array_search( $format, $this->mimeTypes );
return $type === false ? null : $type;
}
/**
* Initializes the internal mapping of MIME types and file extensions to format names.
*/
private function initFormats() {
if ( $this->mimeTypes !== null && $this->fileExtensions !== null ) {
return;
}
$this->mimeTypes = array();
$this->fileExtensions = array();
$api = $this->newApiMain( "dummy" );
$formatNames = $api->getModuleManager()->getNames( 'format' );
foreach ( $formatNames as $name ) {
if ( $this->formatWhiteList !== null && !in_array( $name, $this->formatWhiteList ) ) {
continue;
}
$mimes = self::getApiMimeTypes( $name );
$ext = self::getApiFormatName( $name );
foreach ( $mimes as $mime ) {
if ( !isset( $this->mimeTypes[$mime] ) ) {
$this->mimeTypes[$mime] = $name;
}
}
$this->fileExtensions[ $ext ] = $name;
}
$formats = $this->rdfWriterFactory->getSupportedFormats();
foreach ( $formats as $name ) {
// check whitelist, and don't override API formats
if ( ( $this->formatWhiteList !== null
&& !in_array( $name, $this->formatWhiteList ) )
|| in_array( $name, $this->mimeTypes )
|| in_array( $name, $this->fileExtensions )
) {
continue;
}
// use all mime types. to improve content negotiation
foreach ( $this->rdfWriterFactory->getMimeTypes( $name ) as $mime ) {
if ( !isset( $this->mimeTypes[$mime] ) ) {
$this->mimeTypes[$mime] = $name;
}
}
// only one file extension, to keep purging simple
$ext = $this->rdfWriterFactory->getFileExtension( $name );
if ( !isset( $this->fileExtensions[$ext] ) ) {
$this->fileExtensions[$ext] = $name;
}
}
}
/**
* Normalizes the format specifier; Converts mime types to API format names.
*
* @param String $format the format as supplied in the request
*
* @return String|null the normalized format name, or null if the format is unknown
*/
private static function getApiFormatName( $format ) {
$format = trim( strtolower( $format ) );
if ( $format === 'application/vnd.php.serialized' ) {
$format = 'php';
} elseif ( $format === 'text/text' || $format === 'text/plain' ) {
$format = 'txt';
} else {
// hack: just trip the major part of the mime type
$format = preg_replace( '@^(text|application)?/@', '', $format );
}
return $format;
}
/**
* Converts API format names to MIME types.
*
* @param String $format the API format name
*
* @return String[]|null the MIME types for the given format
*/
private static function getApiMimeTypes( $format ) {
$format = trim( strtolower( $format ) );
$type = null;
switch ( $format ) {
case 'php':
return array( 'application/vnd.php.serialized' );
case 'txt':
return array( "text/text", "text/plain" );
case 'javascript':
return array( "text/javascript" );
default:
return array( "application/$format" );
}
}
/**
* Returns an ApiMain module that acts as a context for the formatting and serialization.
*
* @param String $format The desired output format, as a format name that ApiBase understands.
*
* @return ApiMain
*/
private function newApiMain( $format ) {
// Fake request params to ApiMain, with forced format parameters.
// We can override additional parameters here, as needed.
$params = array(
'format' => $format,
);
$context = new DerivativeContext( RequestContext::getMain() ); //XXX: ugly
$req = new DerivativeRequest( $context->getRequest(), $params );
$context->setRequest( $req );
$api = new ApiMain( $context );
return $api;
}
}