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

Last change on this file since 7569 was 4904, checked in by grum, 15 years ago

Optimize some memory leak and some bugged lines of code

  • Property svn:executable set to *
File size: 12.4 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
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     * returns true if the node have childs
260
261     * @return Boolean
262     */
263    public function hasChilds()
264    {
265      return(count($this->childs)>0);
266    }
267
268    /**
269     * returns an array of childs
270
271     * @return Array of XmlNode
272     */
273    public function getChilds()
274    {
275      return($this->childs);
276    }
277
278    /**
279     * add a new child (added as the last child)
280     *
281     * @param XmlNode $node : the child must be an instanciated XmlNode
282     */
283    public function addChild(XmlNode $node)
284    {
285      $this->childs[]=$node;
286    }
287
288    /**
289     * returns the first child
290     *
291     * @return XmlNode or null
292     */
293    public function getFirstChild()
294    {
295      if($this->hasChilds())
296        return($this->childs[0]);
297      else
298        return(null);
299    }
300
301    /**
302     * returns the last child
303     *
304     * @return XmlNode or null
305     */
306    public function getLastChild()
307    {
308      if($this->hasChilds())
309        return($this->childs[count($this->childs)-1]);
310      else
311        return(null);
312    }
313
314    /**
315     * set the previous node
316     *
317     * @param XmlNode $node : must be an instanciated XmlNode
318     * @return XmlNode : the previous node
319     */
320    public function setPreviousNode(XmlNode $node)
321    {
322      $this->previousNode = $node;
323      return($this->previousNode);
324    }
325
326    /**
327     * returns the previous node
328     *
329     * @return XmlNode or null
330     */
331    public function getPreviousNode()
332    {
333      return($this->previousNode);
334    }
335
336    /**
337     * set the next node
338     *
339     * @param XmlNode $node : must be an instanciated XmlNode
340     * @return XmlNode : the next node
341     */
342    public function setNextNode(XmlNode $node)
343    {
344      $this->nextNode = $node;
345      return($this->nextNode);
346    }
347
348    /**
349     * returns the next node
350     *
351     * @return XmlNode or null
352     */
353    public function getNextNode()
354    {
355      return($this->nextNode);
356    }
357
358
359  }
360
361  class XmlData
362  {
363    private $xml = "";
364    private $nodes = Array();
365    private $isValid = false;
366    private $isLoaded = false;
367
368    /**
369     * the XmlData constructor needs ans Xml string
370     *
371     * @param String $xml : an xml structure in a string
372     */
373    function __construct($xml)
374    {
375      $this->isValid = $this->setXmlData($xml);
376      $this->isLoaded = $this->hasNodes();
377    }
378
379    function __destruct()
380    {
381      unset($this->xml);
382      unset($this->isValid);
383      unset($this->isLoaded);
384      unset($this->nodes);
385    }
386
387    /**
388     * returns true if the xml is valid
389     *
390     * @return Boolean
391     */
392    public function isValid()
393    {
394      return($this->isValid);
395    }
396
397    /**
398     * returns true if the xml has been successfully loaded
399     *
400     * @return Boolean
401     */
402    public function isLoaded()
403    {
404      return($this->isLoaded);
405    }
406
407    /**
408     * returns true if XmlData has nodes
409     *
410     * @return Boolean
411     */
412    public function hasNodes()
413    {
414      return(count($this->nodes)>0);
415    }
416
417    /**
418     * returns the first node of the XmlData
419     *
420     * @return XmlNode or null
421     */
422    public function getFirstNode()
423    {
424      if(count($this->nodes)>0)
425      {
426        return($this->nodes[0]);
427      }
428      else
429      {
430        return(null);
431      }
432    }
433
434    /**
435     * returns the last node of the XmlData
436     *
437     * @return XmlNode or null
438     */
439    public function getLastNode()
440    {
441      if(count($this->nodes)>0)
442      {
443        return($this->nodes[count($this->nodes)-1]);
444      }
445      else
446      {
447        return(null);
448      }
449    }
450
451    /**
452     * set the xml data
453     * return true if the xml is valid and the xml tree is built
454     *
455     * @param String $xml : an xml structure in a string
456     * @return Boolean
457     */
458    public function setXmlData($xml)
459    {
460      if(is_string($xml))
461      {
462        $this->xml=$xml;
463        return($this->buildTreeNode());
464      }
465      return(false);
466    }
467
468    /**
469     * the xml_parse_info_struct load an XML file into a one dimension array
470     * this function build a tree with XmlNode object
471     */
472    private function buildTreeNode()
473    {
474      $xmlParser = xml_parser_create();
475      xml_parser_set_option($xmlParser, XML_OPTION_CASE_FOLDING, 0);
476      xml_parser_set_option($xmlParser, XML_OPTION_SKIP_WHITE, 1);
477      $result=xml_parse_into_struct($xmlParser, $this->xml, $values);
478      xml_parser_free($xmlParser);
479      unset($xmlParser);
480
481      //an error has occured while parsing the xml structure
482      if($result===0) return(false);
483
484
485      $tree=Array();
486
487      for($i=0;$i<count($values);$i++)
488      {
489        $val=$values[$i];
490
491        switch($val['type'])
492        {
493          case "open":
494          case "complete":
495            $node=new XmlNode($val['tag'], $val['level']);
496
497            if(array_key_exists('value', $val))
498            {
499              $node->setValue($val['value']);
500            }
501
502            if(array_key_exists('attributes', $val))
503            {
504              foreach($val['attributes'] as $itemKey => $itemVal)
505              {
506                $node->addAttribute($itemKey, $itemVal);
507              }
508            }
509
510            if(count($tree)>0)
511            {
512              $parent=$tree[count($tree)-1];
513              if($parent->hasChilds())
514              {
515                $parent->getLastChild()->setNextNode($node);
516                $node->setPreviousNode($parent->getLastChild());
517              }
518              $parent->addChild($node);
519            }
520
521            if($val['type']=="open")
522            {
523              array_push($tree, $node);
524            }
525
526            $this->nodes[]=$node;
527            break;
528          case "close":
529            array_pop($tree);
530            break;
531        }
532      }
533      unset($values);
534      unset($tree);
535      return(true);
536    }
537
538  }
539
540?>
Note: See TracBrowser for help on using the repository browser.