Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
96.61% covered (success)
96.61%
57 / 59
84.62% covered (warning)
84.62%
11 / 13
CRAP
0.00% covered (danger)
0.00%
0 / 1
MediaInfoSpecificComponentsRdfBuilder
96.61% covered (success)
96.61%
57 / 59
84.62% covered (warning)
84.62%
11 / 13
26
0.00% covered (danger)
0.00%
0 / 1
 __construct
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 addEntity
75.00% covered (warning)
75.00%
3 / 4
0.00% covered (danger)
0.00%
0 / 1
2.06
 aboutId
100.00% covered (success)
100.00%
3 / 3
100.00% covered (success)
100.00%
1 / 1
1
 addTypes
100.00% covered (success)
100.00%
2 / 2
100.00% covered (success)
100.00%
1 / 1
1
 addFileMetadataFromEntityId
85.71% covered (warning)
85.71%
6 / 7
0.00% covered (danger)
0.00%
0 / 1
3.03
 addFileMetadataFromFile
100.00% covered (success)
100.00%
10 / 10
100.00% covered (success)
100.00%
1 / 1
2
 addFileSpecificType
100.00% covered (success)
100.00%
4 / 4
100.00% covered (success)
100.00%
1 / 1
2
 getFileSpecificType
100.00% covered (success)
100.00%
9 / 9
100.00% covered (success)
100.00%
1 / 1
6
 addEncodingFormat
100.00% covered (success)
100.00%
3 / 3
100.00% covered (success)
100.00%
1 / 1
1
 addFileUrl
100.00% covered (success)
100.00%
3 / 3
100.00% covered (success)
100.00%
1 / 1
1
 addFileUrlAlt
100.00% covered (success)
100.00%
4 / 4
100.00% covered (success)
100.00%
1 / 1
1
 addDuration
100.00% covered (success)
100.00%
5 / 5
100.00% covered (success)
100.00%
1 / 1
2
 addPositiveIntegerValue
100.00% covered (success)
100.00%
4 / 4
100.00% covered (success)
100.00%
1 / 1
3
1<?php
2
3namespace Wikibase\MediaInfo\Rdf;
4
5use MediaWiki\FileRepo\File\File;
6use MediaWiki\FileRepo\RepoGroup;
7use Wikibase\DataModel\Entity\EntityDocument;
8use Wikibase\MediaInfo\Content\MediaInfoHandler;
9use Wikibase\MediaInfo\DataModel\MediaInfo;
10use Wikibase\MediaInfo\DataModel\MediaInfoId;
11use Wikibase\Repo\Rdf\EntityRdfBuilder;
12use Wikibase\Repo\Rdf\RdfVocabulary;
13use Wikimedia\Purtle\RdfWriter;
14
15/**
16 * RDF builder for MediaInfo
17 */
18class MediaInfoSpecificComponentsRdfBuilder implements EntityRdfBuilder {
19
20    public function __construct(
21        private readonly RdfVocabulary $vocabulary,
22        private readonly RdfWriter $writer,
23        private readonly MediaInfoHandler $mediaInfoHandler,
24        private readonly RepoGroup $repoGroup,
25    ) {
26    }
27
28    /**
29     * Map some aspect of an Entity to the RDF graph.
30     *
31     * @param EntityDocument $entity the entity to output.
32     */
33    public function addEntity( EntityDocument $entity ) {
34        if ( !$entity instanceof MediaInfo ) {
35            return;
36        }
37
38        $this->addTypes( $entity->getId() );
39        $this->addFileMetadataFromEntityId( $entity->getId() );
40    }
41
42    /**
43     * Start an "about" clause for the given ID in the RDF writer.
44     *
45     * @param MediaInfoId $id
46     * @return RDFWriter for chaining
47     */
48    private function aboutId( MediaInfoId $id ): RdfWriter {
49        $mediaLName = $this->vocabulary->getEntityLName( $id );
50
51        $mediaRepository = $this->vocabulary->getEntityRepositoryName( $id );
52
53        return $this->writer->about( $this->vocabulary->entityNamespaceNames[$mediaRepository], $mediaLName );
54    }
55
56    /**
57     * Produce MediaInfo types
58     */
59    private function addTypes( MediaInfoId $id ) {
60        $this->aboutId( $id )
61            ->a( RdfVocabulary::NS_SCHEMA_ORG, 'MediaObject' );
62    }
63
64    /**
65     * Add file metadata to RDF representation
66     */
67    private function addFileMetadataFromEntityId( MediaInfoId $id ) {
68        $fileTitle = $this->mediaInfoHandler->getTitleForId( $id );
69        if ( $fileTitle === null ) {
70            return;
71        }
72        $file = $this->repoGroup->findFile( $fileTitle );
73        if ( $file === false ) {
74            return;
75        }
76        $this->addFileMetadataFromFile( $id, $file );
77    }
78
79    private function addFileMetadataFromFile( MediaInfoId $id, File $file ) {
80        $this->addFileSpecificType( $id, $file );
81        $this->addEncodingFormat( $id, $file );
82        $this->addFileUrl( $id, $file );
83        $this->addFileUrlAlt( $id, $file );
84
85        $this->addPositiveIntegerValue( $id, 'contentSize', $file->getSize() );
86        if ( $file->isMultipage() ) {
87            $this->addPositiveIntegerValue( $id, 'numberOfPages', $file->pageCount() );
88            // Width and height of a file is not always the same for all pages of multi-pages files
89        } else {
90            $this->addPositiveIntegerValue( $id, 'height', $file->getHeight() );
91            $this->addPositiveIntegerValue( $id, 'width', $file->getWidth() );
92        }
93        $this->addDuration( $id, $file );
94    }
95
96    private function addFileSpecificType( MediaInfoId $id, File $file ) {
97        $specificType = $this->getFileSpecificType( $file );
98        if ( $specificType !== null ) {
99            $this->aboutId( $id )
100                ->a( RdfVocabulary::NS_SCHEMA_ORG, $specificType );
101        }
102    }
103
104    private function getFileSpecificType( File $file ): ?string {
105        switch ( $file->getMediaType() ) {
106            case MEDIATYPE_BITMAP:
107            case MEDIATYPE_DRAWING:
108                return 'ImageObject';
109            case MEDIATYPE_AUDIO:
110                return 'AudioObject';
111            case MEDIATYPE_VIDEO:
112                return 'VideoObject';
113            default:
114                return null;
115        }
116    }
117
118    private function addEncodingFormat( MediaInfoId $id, File $file ) {
119        $this->aboutId( $id )
120            ->say( RdfVocabulary::NS_SCHEMA_ORG, 'encodingFormat' )
121            ->value( $file->getMimeType() );
122    }
123
124    private function addFileUrl( MediaInfoId $id, File $file ) {
125        $this->aboutId( $id )
126            ->say( RdfVocabulary::NS_SCHEMA_ORG, 'contentUrl' )
127            ->is( $file->getCanonicalUrl() );
128    }
129
130    private function addFileUrlAlt( MediaInfoId $id, File $file ) {
131        $url = $this->vocabulary->getMediaFileURI( $file->getTitle()->getText() );
132
133        $this->aboutId( $id )
134            ->say( RdfVocabulary::NS_SCHEMA_ORG, 'url' )
135            ->is( $url );
136    }
137
138    private function addDuration( MediaInfoId $id, File $file ) {
139        $duration = $file->getLength();
140        if ( $duration > 0 ) {
141            $this->aboutId( $id )
142                ->say( RdfVocabulary::NS_SCHEMA_ORG, 'duration' )
143                ->value( 'PT' . $duration . 'S', 'xsd', 'duration' );
144        }
145    }
146
147    /**
148     * @param MediaInfoId $id
149     * @param string $schemaProperty
150     * @param int $value
151     */
152    private function addPositiveIntegerValue( MediaInfoId $id, $schemaProperty, $value ) {
153        if ( is_int( $value ) && $value > 0 ) {
154            $this->aboutId( $id )
155                ->say( RdfVocabulary::NS_SCHEMA_ORG, $schemaProperty )
156                ->value( (string)$value, 'xsd', 'integer' );
157        }
158    }
159}