Index: branches/img_metadata/phase3/includes/media/XMP.php |
— | — | @@ -29,8 +29,6 @@ |
30 | 30 | |
31 | 31 | private $xmlParser; |
32 | 32 | |
33 | | - protected $items; // Contains an array of all properties we try to extract. |
34 | | - |
35 | 33 | /* |
36 | 34 | * These are various mode constants. |
37 | 35 | * they are used to figure out what to do |
— | — | @@ -43,6 +41,7 @@ |
44 | 42 | const MODE_INITIAL = 0; |
45 | 43 | const MODE_IGNORE = 1; |
46 | 44 | const MODE_LI = 2; |
| 45 | + const MODE_QDESC = 9; |
47 | 46 | |
48 | 47 | // The following MODE constants are also used in the |
49 | 48 | // $items array to denote what type of property the item is. |
— | — | @@ -58,187 +57,10 @@ |
59 | 58 | |
60 | 59 | /** Constructor. |
61 | 60 | * |
62 | | - * Primary job is to intialize the items array |
63 | | - * which is used to determine which props to extract. |
| 61 | + * Primary job is to intialize the XMLParser |
64 | 62 | */ |
65 | 63 | function __construct() { |
66 | 64 | |
67 | | - /* |
68 | | - * $this->items keeps a list of all the items |
69 | | - * we are interested to extract, as well as |
70 | | - * information about the item like what type |
71 | | - * it is. |
72 | | - * |
73 | | - * Format is an array of namespaces, |
74 | | - * each containing an array of tags |
75 | | - * each tag is an array of information about the |
76 | | - * tag, including: |
77 | | - * * map_group - what group (used for precedence during conflicts) |
78 | | - * * mode - What type of item (self::MODE_SIMPLE usually, see above for all values) |
79 | | - * * validate - method to validate input. Could also post-process the input. (TODO: implement this) |
80 | | - * * choices - array of potential values (format of 'value' => true ) |
81 | | - * * children - for MODE_STRUCT items, allowed children. |
82 | | - * |
83 | | - * currently this just has a bunch of exif values as this class is only half-done |
84 | | - */ |
85 | | - |
86 | | - $this->items = array( |
87 | | - 'http://ns.adobe.com/exif/1.0/' => array( |
88 | | - 'ApertureValue' => array( |
89 | | - 'map_group' => 'exif', |
90 | | - 'mode' => self::MODE_SIMPLE, |
91 | | - 'validate' => 'validateRational' |
92 | | - ), |
93 | | - 'BrightnessValue' => array( |
94 | | - 'map_group' => 'exif', |
95 | | - 'mode' => self::MODE_SIMPLE, |
96 | | - 'validate' => 'validateRational' |
97 | | - ), |
98 | | - 'CompressedBitsPerPixel' => array( |
99 | | - 'map_group' => 'exif', |
100 | | - 'mode' => self::MODE_SIMPLE, |
101 | | - 'validate' => 'validateRational' |
102 | | - ), |
103 | | - 'DigitalZoomRatio' => array( |
104 | | - 'map_group' => 'exif', |
105 | | - 'mode' => self::MODE_SIMPLE, |
106 | | - 'validate' => 'validateRational' |
107 | | - ), |
108 | | - 'ExposureBiasValue' => array( |
109 | | - 'map_group' => 'exif', |
110 | | - 'mode' => self::MODE_SIMPLE, |
111 | | - 'validate' => 'validateRational' |
112 | | - ), |
113 | | - 'ExposureIndex' => array( |
114 | | - 'map_group' => 'exif', |
115 | | - 'mode' => self::MODE_SIMPLE, |
116 | | - 'validate' => 'validateRational' |
117 | | - ), |
118 | | - 'ExposureTime' => array( |
119 | | - 'map_group' => 'exif', |
120 | | - 'mode' => self::MODE_SIMPLE, |
121 | | - 'validate' => 'validateRational' |
122 | | - ), |
123 | | - 'FlashEnergy' => array( |
124 | | - 'map_group' => 'exif', |
125 | | - 'mode' => self::MODE_SIMPLE, |
126 | | - 'validate' => 'validateRational' |
127 | | - ), |
128 | | - 'FNumber' => array( |
129 | | - 'map_group' => 'exif', |
130 | | - 'mode' => self::MODE_SIMPLE, |
131 | | - 'validate' => 'validateRational' |
132 | | - ), |
133 | | - 'FocalLength' => array( |
134 | | - 'map_group' => 'exif', |
135 | | - 'mode' => self::MODE_SIMPLE, |
136 | | - 'validate' => 'validateRational' |
137 | | - ), |
138 | | - 'FocalPlaneXResolution' => array( |
139 | | - 'map_group' => 'exif', |
140 | | - 'mode' => self::MODE_SIMPLE, |
141 | | - 'validate' => 'validateRational' |
142 | | - ), |
143 | | - 'FocalPlaneYResolution' => array( |
144 | | - 'map_group' => 'exif', |
145 | | - 'mode' => self::MODE_SIMPLE, |
146 | | - 'validate' => 'validateRational' |
147 | | - ), |
148 | | - /* FIXME GPSAltitude */ |
149 | | - 'GPSDestBearing' => array( |
150 | | - 'map_group' => 'exif', |
151 | | - 'mode' => self::MODE_SIMPLE, |
152 | | - 'validate' => 'validateRational' |
153 | | - ), |
154 | | - 'GPSDestDistance' => array( |
155 | | - 'map_group' => 'exif', |
156 | | - 'mode' => self::MODE_SIMPLE, |
157 | | - 'validate' => 'validateRational' |
158 | | - ), |
159 | | - 'GPSDOP' => array( |
160 | | - 'map_group' => 'exif', |
161 | | - 'mode' => self::MODE_SIMPLE, |
162 | | - 'validate' => 'validateRational' |
163 | | - ), |
164 | | - 'GPSImgDirection' => array( |
165 | | - 'map_group' => 'exif', |
166 | | - 'mode' => self::MODE_SIMPLE, |
167 | | - 'validate' => 'validateRational' |
168 | | - ), |
169 | | - 'GPSSpeed' => array( |
170 | | - 'map_group' => 'exif', |
171 | | - 'mode' => self::MODE_SIMPLE, |
172 | | - 'validate' => 'validateRational' |
173 | | - ), |
174 | | - 'GPSTrack' => array( |
175 | | - 'map_group' => 'exif', |
176 | | - 'mode' => self::MODE_SIMPLE, |
177 | | - 'validate' => 'validateRational' |
178 | | - ), |
179 | | - 'MaxApertureValue' => array( |
180 | | - 'map_group' => 'exif', |
181 | | - 'mode' => self::MODE_SIMPLE, |
182 | | - 'validate' => 'validateRational' |
183 | | - ), |
184 | | - 'ShutterSpeedValue' => array( |
185 | | - 'map_group' => 'exif', |
186 | | - 'mode' => self::MODE_SIMPLE, |
187 | | - 'validate' => 'validateRational' |
188 | | - ), |
189 | | - 'SubjectDistance' => array( |
190 | | - 'map_group' => 'exif', |
191 | | - 'mode' => self::MODE_SIMPLE, |
192 | | - 'validate' => 'validateRational' |
193 | | - ), |
194 | | - |
195 | | - /* Flash */ |
196 | | - 'Flash' => array( |
197 | | - 'mode' => self::MODE_STRUCT, |
198 | | - 'children' => array( |
199 | | - 'Fired' => true, |
200 | | - 'Function' => true, |
201 | | - 'Mode' => true, |
202 | | - 'RedEyeMode' => true, |
203 | | - 'Return' => true, |
204 | | - ), |
205 | | - ), |
206 | | - 'Fired' => array( |
207 | | - 'map_group' => 'exif', |
208 | | - 'validate' => 'validateBoolean', |
209 | | - 'mode' => self::MODE_SIMPLE |
210 | | - ), |
211 | | - 'Function' => array( |
212 | | - 'map_group' => 'exif', |
213 | | - 'validate' => 'validateBoolean', |
214 | | - 'mode' => self::MODE_SIMPLE, |
215 | | - ), |
216 | | - 'Mode' => array( |
217 | | - 'map_group' => 'exif', |
218 | | - 'validate' => 'validateClosed', |
219 | | - 'mode' => self::MODE_SIMPLE, |
220 | | - 'choices' => array( '0' => true, '1' => true, |
221 | | - '2' => true, '3' => true ), |
222 | | - ), |
223 | | - 'Return' => array( |
224 | | - 'map_group' => 'exif', |
225 | | - 'validate' => 'validateClosed', |
226 | | - 'mode' => self::MODE_SIMPLE, |
227 | | - 'choices' => array( '0' => true, |
228 | | - '2' => true, '3' => true ), |
229 | | - ), |
230 | | - 'RedEyeMode' => array( |
231 | | - 'map_group' => 'exif', |
232 | | - 'validate' => 'validateBoolean', |
233 | | - 'mode' => self::MODE_SIMPLE, |
234 | | - ), |
235 | | - /* End Flash */ |
236 | | - 'ISOSpeedRatings' => array( |
237 | | - 'map_group' => 'exif', |
238 | | - 'mode' => self::MODE_SEQ, |
239 | | - ), |
240 | | - ), |
241 | | - ); |
242 | | - |
243 | 65 | if ( !function_exists('xml_parser_create_ns') ) { |
244 | 66 | // this should already be checked by this point |
245 | 67 | throw new MWException('XMP support requires XML Parser'); |
— | — | @@ -328,7 +150,9 @@ |
329 | 151 | |
330 | 152 | if ( $this->mode[0] === self::MODE_IGNORE ) return; |
331 | 153 | |
332 | | - if ( $this->mode[0] !== self::MODE_SIMPLE ) { |
| 154 | + if ( $this->mode[0] !== self::MODE_SIMPLE |
| 155 | + && $this->mode[0] !== self::MODE_QDESC |
| 156 | + ) { |
333 | 157 | throw new MWException('character data where not expected. (mode ' . $this->mode[0] . ')'); |
334 | 158 | } |
335 | 159 | |
— | — | @@ -395,7 +219,13 @@ |
396 | 220 | * @param $elm String namespace . space . tag name. |
397 | 221 | */ |
398 | 222 | private function endElementNested( $elm ) { |
399 | | - if ( $this->curItem[0] !== $elm ) { |
| 223 | + |
| 224 | + /* cur item must be the same as $elm, unless if in MODE_STRUCT |
| 225 | + in which case it could also be rdf:Description */ |
| 226 | + if ( $this->curItem[0] !== $elm |
| 227 | + && !( $elm === self::NS_RDF . ' Description' |
| 228 | + && $this->mode[0] === self::MODE_STRUCT ) |
| 229 | + ) { |
400 | 230 | throw new MWException("nesting mismatch. got a </$elm> but expected a </" . $this->curItem[0] . '>'); |
401 | 231 | } |
402 | 232 | array_shift( $this->curItem ); |
— | — | @@ -417,9 +247,28 @@ |
418 | 248 | } elseif ( $elm === self::NS_RDF . ' Bag' ) { |
419 | 249 | array_shift( $this->mode ); |
420 | 250 | } else { |
421 | | - throw new MWException( __METHOD__ . " expected <rdf:seq> or <rdf:bag> but instead got $elm." ); |
| 251 | + throw new MWException( __METHOD__ . " expected </rdf:seq> or </rdf:bag> but instead got $elm." ); |
422 | 252 | } |
423 | 253 | } |
| 254 | + /** end element while in MODE_QDESC |
| 255 | + * mostly when ending an element when we have a simple value |
| 256 | + * that has qualifiers |
| 257 | + * |
| 258 | + * @param $elm String namespace and element |
| 259 | + */ |
| 260 | + private function endElementModeQDesc( $elm ) { |
| 261 | + |
| 262 | + if ( $elm === self::NS_RDF . ' value' ) { |
| 263 | + list( $ns, $tag ) = explode( ' ', $this->curItem[0], 2 ); |
| 264 | + $this->saveValue( $ns, $tag, $this->charContent ); |
| 265 | + return; |
| 266 | + } else { |
| 267 | + array_shift( $this->mode ); |
| 268 | + array_shift( $this->curItem ); |
| 269 | + } |
| 270 | + |
| 271 | + |
| 272 | + } |
424 | 273 | /** Handler for hitting a closing element. |
425 | 274 | * |
426 | 275 | * generally just calls a helper function depending on what mode we're in. |
— | — | @@ -435,6 +284,11 @@ |
436 | 285 | return; |
437 | 286 | } |
438 | 287 | |
| 288 | + if ( $elm === self::NS_RDF . ' type' ) { |
| 289 | + //these aren't really supported properly yet. |
| 290 | + wfDebugLog('XMP', __METHOD__ . ' encoutered <rdf:type>'); |
| 291 | + } |
| 292 | + |
439 | 293 | switch( $this->mode[0] ) { |
440 | 294 | case self::MODE_IGNORE: |
441 | 295 | $this->endElementModeIgnore( $elm ); |
— | — | @@ -457,6 +311,9 @@ |
458 | 312 | case self::MODE_LI: |
459 | 313 | $this->endElementModeLi( $elm ); |
460 | 314 | break; |
| 315 | + case self::MODE_QDESC: |
| 316 | + $this->endElementModeQDesc( $elm ); |
| 317 | + break; |
461 | 318 | default: |
462 | 319 | wfDebugLog( 'XMP', __METHOD__ ." no mode (elm = $elm)"); |
463 | 320 | break; |
— | — | @@ -507,25 +364,49 @@ |
508 | 365 | /** Handle an opening element when in MODE_SIMPLE |
509 | 366 | * This should not happen often. This is for if a simple element |
510 | 367 | * already opened has a child element. Could happen for a |
511 | | - * qualified element, or if using overly verbose syntax. |
| 368 | + * qualified element. |
512 | 369 | * |
513 | 370 | * @param $elm String namespace and tag names seperated by space. |
514 | 371 | */ |
515 | | - private function startElementModeSimple( $elm ) { |
516 | | - if ( $elm === self::NS_RDF . ' Description' |
517 | | - || $elm === self::NS_RDF . ' value') |
518 | | - { |
519 | | - //fixme, better handling of value |
520 | | - array_unshift( $this->mode, self::MODE_SIMPLE ); |
| 372 | + private function startElementModeSimple( $elm, $attribs ) { |
| 373 | + if ( $elm === self::NS_RDF . ' Description' ) { |
| 374 | + //If this value has qualifiers |
| 375 | + array_unshift( $this->mode, self::MODE_QDESC ); |
521 | 376 | array_unshift( $this->curItem, $this->curItem[0] ); |
| 377 | + |
| 378 | + if ( isset( $attribs[self::NS_RDF . ' value'] ) ) { |
| 379 | + list( $ns, $tag ) = explode( ' ', $this->curItem[0], 2 ); |
| 380 | + $this->saveValue( $ns, $tag, $attribs[self::NS_RDF . ' value']); |
| 381 | + } |
| 382 | + } elseif ( $elm === self::NS_RDF . ' value' ) { |
| 383 | + //This should not be here. |
| 384 | + throw new MWException(__METHOD__ . ' Encountered <rdf:value> where it was unexpected.'); |
| 385 | + |
522 | 386 | } else { |
523 | 387 | //something else we don't recognize, like a qualifier maybe. |
| 388 | + wfDebugLog( 'XMP', __METHOD__ . " Encoutered element <$elm> where only expecting character data."); |
524 | 389 | array_unshift( $this->mode, self::MODE_IGNORE ); |
525 | 390 | array_unshift( $this->curItem, $elm ); |
526 | 391 | |
527 | 392 | } |
528 | 393 | |
529 | 394 | } |
| 395 | + /** Start an element when in MODE_QDESC. |
| 396 | + * This generally happens when a simple element has an inner |
| 397 | + * rdf:Description to hold qualifier elements. |
| 398 | + * |
| 399 | + * @param $elm String namespace and tag name separated by a space. |
| 400 | + * |
| 401 | + */ |
| 402 | + private function startElementModeQDesc( $elm ) { |
| 403 | + if ( $elm === self::NS_RDF . ' value' ) { |
| 404 | + return; //do nothing |
| 405 | + } else { |
| 406 | + //otherwise its a qualifier, which we ignore |
| 407 | + array_unshift( $this->mode, self::MODE_IGNORE ); |
| 408 | + array_unshift( $this->curItem, $elm ); |
| 409 | + } |
| 410 | + } |
530 | 411 | /** Starting an element when in MODE_INITIAL |
531 | 412 | * This usually happens when we hit an element inside |
532 | 413 | * the outer rdf:Description |
— | — | @@ -539,13 +420,13 @@ |
540 | 421 | private function startElementModeInitial( $ns, $tag, $attribs ) { |
541 | 422 | if ($ns !== self::NS_RDF) { |
542 | 423 | |
543 | | - if ( isset( $this->items[$ns][$tag] ) ) { |
544 | | - $mode = $this->items[$ns][$tag]['mode']; |
| 424 | + if ( isset( XMPInfo::$items[$ns][$tag] ) ) { |
| 425 | + $mode = XMPInfo::$items[$ns][$tag]['mode']; |
545 | 426 | array_unshift( $this->mode, $mode ); |
546 | 427 | array_unshift( $this->curItem, $ns . ' ' . $tag ); |
547 | 428 | if ( $mode === self::MODE_STRUCT ) { |
548 | | - $this->ancestorStruct = isset( $this->items[$ns][$tag]['map_name'] ) |
549 | | - ? $this->items[$ns][$tag]['map_name'] : $tag; |
| 429 | + $this->ancestorStruct = isset( XMPInfo::$items[$ns][$tag]['map_name'] ) |
| 430 | + ? XMPInfo::$items[$ns][$tag]['map_name'] : $tag; |
550 | 431 | } |
551 | 432 | if ( $this->charContent !== false ) { |
552 | 433 | // Something weird. |
— | — | @@ -572,16 +453,16 @@ |
573 | 454 | private function startElementModeStruct( $ns, $tag, $attribs ) { |
574 | 455 | if ($ns !== self::NS_RDF) { |
575 | 456 | |
576 | | - if ( isset( $this->items[$ns][$tag] ) ) { |
577 | | - if ( isset( $this->items[$ns][$this->ancestorStruct]['children'] ) |
578 | | - && !isset($this->items[$ns][$this->ancestorStruct]['children'][$tag]) ) |
| 457 | + if ( isset( XMPInfo::$items[$ns][$tag] ) ) { |
| 458 | + if ( isset( XMPInfo::$items[$ns][$this->ancestorStruct]['children'] ) |
| 459 | + && !isset(XMPInfo::$items[$ns][$this->ancestorStruct]['children'][$tag]) ) |
579 | 460 | { |
580 | 461 | //This assumes that we don't have inter-namespace nesting |
581 | 462 | //which we don't in all the properties we're interested in. |
582 | 463 | throw new MWException(" <$tag> appeared nested in <" . $this->ancestorStruct |
583 | 464 | . "> where it is not allowed."); |
584 | 465 | } |
585 | | - array_unshift( $this->mode, $this->items[$ns][$tag]['mode'] ); |
| 466 | + array_unshift( $this->mode, XMPInfo::$items[$ns][$tag]['mode'] ); |
586 | 467 | array_unshift( $this->curItem, $ns . ' ' . $tag ); |
587 | 468 | if ( $this->charContent !== false ) { |
588 | 469 | // Something weird. |
— | — | @@ -598,6 +479,8 @@ |
599 | 480 | |
600 | 481 | if ( $ns === self::NS_RDF && $tag === 'Description' ) { |
601 | 482 | $this->doAttribs( $attribs ); |
| 483 | + array_unshift( $this->mode, self::MODE_STRUCT ); |
| 484 | + array_unshift( $this->curItem, $this->curItem[0] ); |
602 | 485 | } |
603 | 486 | } |
604 | 487 | /** opening element in MODE_LI |
— | — | @@ -627,26 +510,25 @@ |
628 | 511 | */ |
629 | 512 | function startElement( $parser, $elm, $attribs ) { |
630 | 513 | |
631 | | - |
632 | 514 | if ($elm === self::NS_RDF . ' RDF' |
633 | 515 | || $elm === 'adobe:ns:meta/ xmpmeta' ) |
634 | 516 | { |
635 | 517 | /* ignore */ |
636 | 518 | return; |
637 | | - } |
638 | | - |
639 | | - if ( $elm === self::NS_RDF . ' Description' ) { |
| 519 | + } elseif ( $elm === self::NS_RDF . ' Description' ) { |
640 | 520 | if ( count( $this->mode ) === 0 ) { |
641 | 521 | //outer rdf:desc |
642 | 522 | array_unshift( $this->mode, self::MODE_INITIAL ); |
643 | | - } else { |
644 | | - //inner rdf:desc |
645 | | - // fixme this doesn't handle qualifiers right. |
646 | | - $this->doAttribs( $attribs ); |
647 | | - return; |
648 | 523 | } |
| 524 | + } elseif ( $elm === self::NS_RDF . ' type' ) { |
| 525 | + // This doesn't support rdf:type properly. |
| 526 | + // In practise I have yet to see a file that |
| 527 | + // uses this element, however it is mentioned |
| 528 | + // on page 25 of part 1 of the xmp standard. |
| 529 | + wfDebugLog( 'XMP', __METHOD__ . ' Encoutered <rdf:type> which isn\'t currently supported' ); |
649 | 530 | } |
650 | 531 | |
| 532 | + |
651 | 533 | list($ns, $tag) = explode( ' ', $elm, 2 ); |
652 | 534 | |
653 | 535 | switch( $this->mode[0] ) { |
— | — | @@ -654,7 +536,7 @@ |
655 | 537 | $this->startElementModeIgnore( $elm ); |
656 | 538 | break; |
657 | 539 | case self::MODE_SIMPLE: |
658 | | - $this->startElementModeSimple( $elm ); |
| 540 | + $this->startElementModeSimple( $elm, $attribs ); |
659 | 541 | break; |
660 | 542 | case self::MODE_INITIAL: |
661 | 543 | $this->startElementModeInitial( $ns, $tag, $attribs ); |
— | — | @@ -671,6 +553,9 @@ |
672 | 554 | case self::MODE_LI: |
673 | 555 | $this->startElementModeLi( $elm ); |
674 | 556 | break; |
| 557 | + case self::MODE_QDESC: |
| 558 | + $this->startElementModeQDesc( $elm ); |
| 559 | + break; |
675 | 560 | default: |
676 | 561 | throw new MWException('StartElement in unknown mode: ' . $this->mode[0] ); |
677 | 562 | break; |
— | — | @@ -686,14 +571,26 @@ |
687 | 572 | */ |
688 | 573 | private function doAttribs( $attribs ) { |
689 | 574 | foreach( $attribs as $name => $val ) { |
| 575 | + |
| 576 | + // first check for rdf:parseType attribute, as that can change |
| 577 | + // how the attributes are interperted. |
| 578 | + |
| 579 | + if ( $name === self::NS_RDF . ' parseType' |
| 580 | + && $val === 'Resource' |
| 581 | + && $this->mode[0] === self::MODE_SIMPLE ) |
| 582 | + { |
| 583 | + //this is equivelent to having an inner rdf:Description |
| 584 | + $this->mode[0] = self::MODE_QDESC; |
| 585 | + } |
| 586 | + |
690 | 587 | list($ns, $tag) = explode(' ', $name, 2); |
691 | 588 | if ( $ns === self::NS_RDF ) { |
692 | 589 | if ( $tag === 'value' || $tag === 'resource' ) { |
693 | | - //resource is for url. |
| 590 | + // resource is for url. |
694 | 591 | // value attribute is a weird way of just putting the contents. |
695 | 592 | $this->char( $val ); |
696 | 593 | } |
697 | | - } elseif ( isset( $this->items[$ns][$tag] ) ) { |
| 594 | + } elseif ( isset( XMPInfo::$items[$ns][$tag] ) ) { |
698 | 595 | if ( $this->mode[0] === self::MODE_SIMPLE ) { |
699 | 596 | throw new MWException( __METHOD__ |
700 | 597 | . " $ns:$tag found as attribute where not allowed" ); |
— | — | @@ -714,7 +611,7 @@ |
715 | 612 | */ |
716 | 613 | private function saveValue( $ns, $tag, $val ) { |
717 | 614 | |
718 | | - $info =& $this->items[$ns][$tag]; |
| 615 | + $info =& XMPInfo::$items[$ns][$tag]; |
719 | 616 | $finalName = isset( $info['map_name'] ) |
720 | 617 | ? $info['map_name'] : $tag; |
721 | 618 | if ( isset( $info['validate'] ) ) { |
Index: branches/img_metadata/phase3/includes/media/XMPInfo.php |
— | — | @@ -0,0 +1,183 @@ |
| 2 | +<?php |
| 3 | +/** |
| 4 | +* This class is just a container for a big array |
| 5 | +* used by XMPReader to determine which XMP items to |
| 6 | +* extract. |
| 7 | +*/ |
| 8 | +class XMPInfo { |
| 9 | + |
| 10 | + /** |
| 11 | + * XMPInfo::$items keeps a list of all the items |
| 12 | + * we are interested to extract, as well as |
| 13 | + * information about the item like what type |
| 14 | + * it is. |
| 15 | + * |
| 16 | + * Format is an array of namespaces, |
| 17 | + * each containing an array of tags |
| 18 | + * each tag is an array of information about the |
| 19 | + * tag, including: |
| 20 | + * * map_group - what group (used for precedence during conflicts) |
| 21 | + * * mode - What type of item (self::MODE_SIMPLE usually, see above for all values) |
| 22 | + * * validate - method to validate input. Could also post-process the input. (TODO: implement this) |
| 23 | + * * choices - array of potential values (format of 'value' => true ) |
| 24 | + * * children - for MODE_STRUCT items, allowed children. |
| 25 | + * |
| 26 | + * currently this just has a bunch of exif values as this class is only half-done |
| 27 | + */ |
| 28 | + |
| 29 | + static public $items = array( |
| 30 | + 'http://ns.adobe.com/exif/1.0/' => array( |
| 31 | + 'ApertureValue' => array( |
| 32 | + 'map_group' => 'exif', |
| 33 | + 'mode' => XMPReader::MODE_SIMPLE, |
| 34 | + 'validate' => 'validateRational' |
| 35 | + ), |
| 36 | + 'BrightnessValue' => array( |
| 37 | + 'map_group' => 'exif', |
| 38 | + 'mode' => XMPReader::MODE_SIMPLE, |
| 39 | + 'validate' => 'validateRational' |
| 40 | + ), |
| 41 | + 'CompressedBitsPerPixel' => array( |
| 42 | + 'map_group' => 'exif', |
| 43 | + 'mode' => XMPReader::MODE_SIMPLE, |
| 44 | + 'validate' => 'validateRational' |
| 45 | + ), |
| 46 | + 'DigitalZoomRatio' => array( |
| 47 | + 'map_group' => 'exif', |
| 48 | + 'mode' => XMPReader::MODE_SIMPLE, |
| 49 | + 'validate' => 'validateRational' |
| 50 | + ), |
| 51 | + 'ExposureBiasValue' => array( |
| 52 | + 'map_group' => 'exif', |
| 53 | + 'mode' => XMPReader::MODE_SIMPLE, |
| 54 | + 'validate' => 'validateRational' |
| 55 | + ), |
| 56 | + 'ExposureIndex' => array( |
| 57 | + 'map_group' => 'exif', |
| 58 | + 'mode' => XMPReader::MODE_SIMPLE, |
| 59 | + 'validate' => 'validateRational' |
| 60 | + ), |
| 61 | + 'ExposureTime' => array( |
| 62 | + 'map_group' => 'exif', |
| 63 | + 'mode' => XMPReader::MODE_SIMPLE, |
| 64 | + 'validate' => 'validateRational' |
| 65 | + ), |
| 66 | + 'FlashEnergy' => array( |
| 67 | + 'map_group' => 'exif', |
| 68 | + 'mode' => XMPReader::MODE_SIMPLE, |
| 69 | + 'validate' => 'validateRational' |
| 70 | + ), |
| 71 | + 'FNumber' => array( |
| 72 | + 'map_group' => 'exif', |
| 73 | + 'mode' => XMPReader::MODE_SIMPLE, |
| 74 | + 'validate' => 'validateRational' |
| 75 | + ), |
| 76 | + 'FocalLength' => array( |
| 77 | + 'map_group' => 'exif', |
| 78 | + 'mode' => XMPReader::MODE_SIMPLE, |
| 79 | + 'validate' => 'validateRational' |
| 80 | + ), |
| 81 | + 'FocalPlaneXResolution' => array( |
| 82 | + 'map_group' => 'exif', |
| 83 | + 'mode' => XMPReader::MODE_SIMPLE, |
| 84 | + 'validate' => 'validateRational' |
| 85 | + ), |
| 86 | + 'FocalPlaneYResolution' => array( |
| 87 | + 'map_group' => 'exif', |
| 88 | + 'mode' => XMPReader::MODE_SIMPLE, |
| 89 | + 'validate' => 'validateRational' |
| 90 | + ), |
| 91 | + /* FIXME GPSAltitude */ |
| 92 | + 'GPSDestBearing' => array( |
| 93 | + 'map_group' => 'exif', |
| 94 | + 'mode' => XMPReader::MODE_SIMPLE, |
| 95 | + 'validate' => 'validateRational' |
| 96 | + ), |
| 97 | + 'GPSDestDistance' => array( |
| 98 | + 'map_group' => 'exif', |
| 99 | + 'mode' => XMPReader::MODE_SIMPLE, |
| 100 | + 'validate' => 'validateRational' |
| 101 | + ), |
| 102 | + 'GPSDOP' => array( |
| 103 | + 'map_group' => 'exif', |
| 104 | + 'mode' => XMPReader::MODE_SIMPLE, |
| 105 | + 'validate' => 'validateRational' |
| 106 | + ), |
| 107 | + 'GPSImgDirection' => array( |
| 108 | + 'map_group' => 'exif', |
| 109 | + 'mode' => XMPReader::MODE_SIMPLE, |
| 110 | + 'validate' => 'validateRational' |
| 111 | + ), |
| 112 | + 'GPSSpeed' => array( |
| 113 | + 'map_group' => 'exif', |
| 114 | + 'mode' => XMPReader::MODE_SIMPLE, |
| 115 | + 'validate' => 'validateRational' |
| 116 | + ), |
| 117 | + 'GPSTrack' => array( |
| 118 | + 'map_group' => 'exif', |
| 119 | + 'mode' => XMPReader::MODE_SIMPLE, |
| 120 | + 'validate' => 'validateRational' |
| 121 | + ), |
| 122 | + 'MaxApertureValue' => array( |
| 123 | + 'map_group' => 'exif', |
| 124 | + 'mode' => XMPReader::MODE_SIMPLE, |
| 125 | + 'validate' => 'validateRational' |
| 126 | + ), |
| 127 | + 'ShutterSpeedValue' => array( |
| 128 | + 'map_group' => 'exif', |
| 129 | + 'mode' => XMPReader::MODE_SIMPLE, |
| 130 | + 'validate' => 'validateRational' |
| 131 | + ), |
| 132 | + 'SubjectDistance' => array( |
| 133 | + 'map_group' => 'exif', |
| 134 | + 'mode' => XMPReader::MODE_SIMPLE, |
| 135 | + 'validate' => 'validateRational' |
| 136 | + ), |
| 137 | + /* Flash */ |
| 138 | + 'Flash' => array( |
| 139 | + 'mode' => XMPReader::MODE_STRUCT, |
| 140 | + 'children' => array( |
| 141 | + 'Fired' => true, |
| 142 | + 'Function' => true, |
| 143 | + 'Mode' => true, |
| 144 | + 'RedEyeMode' => true, |
| 145 | + 'Return' => true, |
| 146 | + ), |
| 147 | + ), |
| 148 | + 'Fired' => array( |
| 149 | + 'map_group' => 'exif', |
| 150 | + 'validate' => 'validateBoolean', |
| 151 | + 'mode' => XMPReader::MODE_SIMPLE |
| 152 | + ), |
| 153 | + 'Function' => array( |
| 154 | + 'map_group' => 'exif', |
| 155 | + 'validate' => 'validateBoolean', |
| 156 | + 'mode' => XMPReader::MODE_SIMPLE, |
| 157 | + ), |
| 158 | + 'Mode' => array( |
| 159 | + 'map_group' => 'exif', |
| 160 | + 'validate' => 'validateClosed', |
| 161 | + 'mode' => XMPReader::MODE_SIMPLE, |
| 162 | + 'choices' => array( '0' => true, '1' => true, |
| 163 | + '2' => true, '3' => true ), |
| 164 | + ), |
| 165 | + 'Return' => array( |
| 166 | + 'map_group' => 'exif', |
| 167 | + 'validate' => 'validateClosed', |
| 168 | + 'mode' => XMPReader::MODE_SIMPLE, |
| 169 | + 'choices' => array( '0' => true, |
| 170 | + '2' => true, '3' => true ), |
| 171 | + ), |
| 172 | + 'RedEyeMode' => array( |
| 173 | + 'map_group' => 'exif', |
| 174 | + 'validate' => 'validateBoolean', |
| 175 | + 'mode' => XMPReader::MODE_SIMPLE, |
| 176 | + ), |
| 177 | + /* End Flash */ |
| 178 | + 'ISOSpeedRatings' => array( |
| 179 | + 'map_group' => 'exif', |
| 180 | + 'mode' => XMPReader::MODE_SEQ, |
| 181 | + ), |
| 182 | + ), |
| 183 | + ); |
| 184 | +} |
Property changes on: branches/img_metadata/phase3/includes/media/XMPInfo.php |
___________________________________________________________________ |
Added: svn:eol-style |
1 | 185 | + native |
Index: branches/img_metadata/phase3/includes/AutoLoader.php |
— | — | @@ -461,6 +461,7 @@ |
462 | 462 | 'TiffHandler' => 'includes/media/Tiff.php', |
463 | 463 | 'TransformParameterError' => 'includes/media/MediaTransformOutput.php', |
464 | 464 | 'XMPReader' => 'includes/media/XMP.php', |
| 465 | + 'XMPInfo' => 'includes/media/XMPInfo.php', |
465 | 466 | |
466 | 467 | # includes/normal |
467 | 468 | 'UtfNormal' => 'includes/normal/UtfNormal.php', |