source: extensions/AMetaData/JpegMetaData/Common/XmlData.class.php @ 17554

Last change on this file since 17554 was 17554, checked in by grum, 12 years ago

feature:2701
bug:2702
bug:2720
bug:2722

  • Property svn:executable set to *
File size: 12.7 KB
Line 
1<?php
2/*
3 * --:: JPEG MetaDatas ::-------------------------------------------------------
4 *
5 *  Author    : Grum
6 *   email    : grum at piwigo.org
7 *   website  : http://photos.grum.fr
8 *
9 *   << May the Little SpaceFrog be with you ! >>
10 *
11 *
12 * +-----------------------------------------------------------------------+
13 * | JpegMetaData - a PHP based Jpeg Metadata manager                      |
14 * +-----------------------------------------------------------------------+
15 * | Copyright(C) 2010  Grum - http://www.grum.fr                          |
16 * +-----------------------------------------------------------------------+
17 * | This program is free software; you can redistribute it and/or modify  |
18 * | it under the terms of the GNU General Public License as published by  |
19 * | the Free Software Foundation                                          |
20 * |                                                                       |
21 * | This program is distributed in the hope that it will be useful, but   |
22 * | WITHOUT ANY WARRANTY; without even the implied warranty of            |
23 * | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU      |
24 * | General Public License for more details.                              |
25 * |                                                                       |
26 * | You should have received a copy of the GNU General Public License     |
27 * | along with this program; if not, write to the Free Software           |
28 * | Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, |
29 * | USA.                                                                  |
30 * +-----------------------------------------------------------------------+
31 *
32 *
33 * -----------------------------------------------------------------------------
34 *
35 * The XmlData class is used to read Xml data in a tree structure
36 * The class read the Xml data from a string, and build a tree made with XmlNode
37 * objects
38 *
39 * The XmlNode class is used to manage the nodes properties, like name, value,
40 * attributes, ...
41 *
42 * -----------------------------------------------------------------------------
43 *
44 * The XmlData class provides theses public functions :
45 *  - isValid
46 *  - isLoaded
47 *  - hasNodes
48 *  - getFirstNode
49 *  - getLastNode
50 *  - setXmlData
51 *
52 * The XmlNode class provides theses public functions :
53 *  - getName
54 *  - getLevel
55 *  - getValue
56 *  - setName
57 *  - setValue
58 *  - hasAttributes
59 *  - getAttributes
60 *  - getAttribute
61 *  - setAttribute
62 *  - delAttribute
63 *  - addAttribute
64 *  - hasChilds
65 *  - getChilds
66 *  - addChild
67 *  - getFirstChild
68 *  - getLastChild
69 *  - getPreviousNode
70 *  - setPreviousNode
71 *  - getNextNode
72 *  - setNextNode
73 *
74 * -----------------------------------------------------------------------------
75 */
76
77  class XmlNode
78  {
79    private $name = "";
80    private $attributes = Array();
81    private $childs = Array();
82    private $level = 0;
83    private $previousNode = null;
84    private $nextNode = null;
85    private $value=NULL;
86
87    /**
88     * the XmlNode constructor need a name for the node, and optionally the node
89     * level in the tree
90     *
91     * @param String $name              : node name
92     * @param Integer $level (optional) : node level, by default set to zero
93     */
94    function __construct($name, $level=0)
95    {
96      $this->name=$name;
97      $this->level=$level;
98    }
99
100    /**
101     * free memory before destroying the object...
102     */
103    function __destruct()
104    {
105      $this->previousNode=null;
106      $this->nextNode=null;
107      unset($this->previousNode);
108      unset($this->nextNode);
109      unset($this->attributes);
110      unset($this->childs);
111      unset($this->value);
112      unset($this->name);
113      unset($this->level);
114    }
115
116    /**
117     * returns the name of the node
118     *
119     * @return String
120     */
121    public function getName()
122    {
123      return($this->name);
124    }
125
126    /**
127     * returns the level of the node
128     *
129     * @return Integer
130     */
131    public function getLevel()
132    {
133      return($this->level);
134    }
135
136    /**
137     * returns the value of the node
138     *
139     * @return the type depends of the node
140     */
141    public function getValue()
142    {
143      return($this->value);
144    }
145
146    /**
147     * set the name of the node
148     *
149     * @param String $value : the name of the node
150     * @return String
151     */
152    public function setName($value)
153    {
154      $this->name = $value;
155      return($this->name);
156    }
157
158    /**
159     * set the value of the node
160     *
161     * @param $value : the value can be of any type
162     */
163    public function setValue($value)
164    {
165      $this->value=$value;
166      return($this->value);
167    }
168
169    /**
170     * return true if the node has attributes
171     *
172     * @return Boolean
173     */
174    public function hasAttributes()
175    {
176      return(count($this->attributes)>0);
177    }
178
179    /**
180     * return an array of attributes
181     *
182     * @return Array : key = name of the attribute, value = value for attribute
183     */
184    public function getAttributes()
185    {
186      return($this->attributes);
187    }
188
189    /**
190     * return value for an attribute
191     * if the given attribute doesn't exist, return an empty string
192     *
193     * @param String $name : the attribute name
194     * @return String
195     */
196    public function getAttribute($name)
197    {
198      if(array_key_exists($name, $this->attributes))
199        return($this->attributes[$name]);
200      else
201        return("");
202    }
203
204    /**
205     * set the value for an attribute
206     * the attribute must exist, otherwise uses the addAttribute function
207     *
208     * @param String $name : the name of the attribute to set to value
209     * @param $value       : the value to set for the attribute
210     * @return Boolean : false if the attribute doesn't exist
211     */
212    public function setAttribute($name, $value)
213    {
214      if(array_key_exists($name, $this->attributes))
215      {
216        $this->attributes[$name]=$value;
217        return(true);
218      }
219      else
220        return(false);
221    }
222
223    /**
224     * add an attribute
225     * the attribute must exist, otherwise uses the addAttribute function
226
227     * @param String $name : the name of the new attribute
228     * @param $value       : the value of the new attribute
229     */
230    public function addAttribute($name, $value)
231    {
232      $this->attributes[]=Array(
233        'name'  => $name,
234        'value' => $value
235      );
236    }
237
238    /**
239     * delete an attribute
240     * return true of the attribute has been deleted, otherwise false
241
242     * @param String $name : the name the attribute to delete; if null value is given, delete ALL attributes
243     * @return Boolean
244     */
245    public function delAttribute($name)
246    {
247      if(array_key_exists($name, $this->attributes))
248      {
249        unset($this->attributes[$name]);
250        return(true);
251      }
252      else
253      {
254        return(false);
255      }
256    }
257
258    /**
259     * delete all attributes
260     * return true of the attribute has been deleted, otherwise false
261     *
262     * @return Boolean
263     */
264    public function delAttributes()
265    {
266      $this->attributes=array();
267      return(true);
268    }
269
270    /**
271     * returns true if the node have childs
272
273     * @return Boolean
274     */
275    public function hasChilds()
276    {
277      return(count($this->childs)>0);
278    }
279
280    /**
281     * returns an array of childs
282
283     * @return Array of XmlNode
284     */
285    public function getChilds()
286    {
287      return($this->childs);
288    }
289
290    /**
291     * add a new child (added as the last child)
292     *
293     * @param XmlNode $node : the child must be an instanciated XmlNode
294     */
295    public function addChild(XmlNode $node)
296    {
297      $this->childs[]=$node;
298    }
299
300    /**
301     * returns the first child
302     *
303     * @return XmlNode or null
304     */
305    public function getFirstChild()
306    {
307      if($this->hasChilds())
308        return($this->childs[0]);
309      else
310        return(null);
311    }
312
313    /**
314     * returns the last child
315     *
316     * @return XmlNode or null
317     */
318    public function getLastChild()
319    {
320      if($this->hasChilds())
321        return($this->childs[count($this->childs)-1]);
322      else
323        return(null);
324    }
325
326    /**
327     * set the previous node
328     *
329     * @param XmlNode $node : must be an instanciated XmlNode
330     * @return XmlNode : the previous node
331     */
332    public function setPreviousNode(XmlNode $node)
333    {
334      $this->previousNode = $node;
335      return($this->previousNode);
336    }
337
338    /**
339     * returns the previous node
340     *
341     * @return XmlNode or null
342     */
343    public function getPreviousNode()
344    {
345      return($this->previousNode);
346    }
347
348    /**
349     * set the next node
350     *
351     * @param XmlNode $node : must be an instanciated XmlNode
352     * @return XmlNode : the next node
353     */
354    public function setNextNode(XmlNode $node)
355    {
356      $this->nextNode = $node;
357      return($this->nextNode);
358    }
359
360    /**
361     * returns the next node
362     *
363     * @return XmlNode or null
364     */
365    public function getNextNode()
366    {
367      return($this->nextNode);
368    }
369
370
371  }
372
373  class XmlData
374  {
375    private $xml = "";
376    private $nodes = Array();
377    private $isValid = false;
378    private $isLoaded = false;
379
380    /**
381     * the XmlData constructor needs ans Xml string
382     *
383     * @param String $xml : an xml structure in a string
384     */
385    function __construct($xml)
386    {
387      $this->isValid = $this->setXmlData($xml);
388      $this->isLoaded = $this->hasNodes();
389    }
390
391    function __destruct()
392    {
393      unset($this->xml);
394      unset($this->isValid);
395      unset($this->isLoaded);
396      unset($this->nodes);
397    }
398
399    /**
400     * returns true if the xml is valid
401     *
402     * @return Boolean
403     */
404    public function isValid()
405    {
406      return($this->isValid);
407    }
408
409    /**
410     * returns true if the xml has been successfully loaded
411     *
412     * @return Boolean
413     */
414    public function isLoaded()
415    {
416      return($this->isLoaded);
417    }
418
419    /**
420     * returns true if XmlData has nodes
421     *
422     * @return Boolean
423     */
424    public function hasNodes()
425    {
426      return(count($this->nodes)>0);
427    }
428
429    /**
430     * returns the first node of the XmlData
431     *
432     * @return XmlNode or null
433     */
434    public function getFirstNode()
435    {
436      if(count($this->nodes)>0)
437      {
438        return($this->nodes[0]);
439      }
440      else
441      {
442        return(null);
443      }
444    }
445
446    /**
447     * returns the last node of the XmlData
448     *
449     * @return XmlNode or null
450     */
451    public function getLastNode()
452    {
453      if(count($this->nodes)>0)
454      {
455        return($this->nodes[count($this->nodes)-1]);
456      }
457      else
458      {
459        return(null);
460      }
461    }
462
463    /**
464     * set the xml data
465     * return true if the xml is valid and the xml tree is built
466     *
467     * @param String $xml : an xml structure in a string
468     * @return Boolean
469     */
470    public function setXmlData($xml)
471    {
472      if(is_string($xml))
473      {
474        $this->xml=$xml;
475        return($this->buildTreeNode());
476      }
477      return(false);
478    }
479
480    /**
481     * the xml_parse_info_struct load an XML file into a one dimension array
482     * this function build a tree with XmlNode object
483     */
484    private function buildTreeNode()
485    {
486      $xmlParser = xml_parser_create();
487      xml_parser_set_option($xmlParser, XML_OPTION_CASE_FOLDING, 0);
488      xml_parser_set_option($xmlParser, XML_OPTION_SKIP_WHITE, 1);
489      $result=xml_parse_into_struct($xmlParser, $this->xml, $values);
490      xml_parser_free($xmlParser);
491      unset($xmlParser);
492
493      //an error has occured while parsing the xml structure
494      if($result===0) return(false);
495
496
497      $tree=Array();
498
499      for($i=0;$i<count($values);$i++)
500      {
501        $val=$values[$i];
502
503        switch($val['type'])
504        {
505          case "open":
506          case "complete":
507            $node=new XmlNode($val['tag'], $val['level']);
508
509            if(array_key_exists('value', $val))
510            {
511              $node->setValue($val['value']);
512            }
513
514            if(array_key_exists('attributes', $val))
515            {
516              foreach($val['attributes'] as $itemKey => $itemVal)
517              {
518                $node->addAttribute($itemKey, $itemVal);
519              }
520            }
521
522            if(count($tree)>0)
523            {
524              $parent=$tree[count($tree)-1];
525              if($parent->hasChilds())
526              {
527                $parent->getLastChild()->setNextNode($node);
528                $node->setPreviousNode($parent->getLastChild());
529              }
530              $parent->addChild($node);
531            }
532
533            if($val['type']=="open")
534            {
535              array_push($tree, $node);
536            }
537
538            $this->nodes[]=$node;
539            break;
540          case "close":
541            array_pop($tree);
542            break;
543        }
544      }
545      unset($values);
546      unset($tree);
547      return(true);
548    }
549
550  }
551
552?>
Note: See TracBrowser for help on using the repository browser.