wCMF  3.6
 All Classes Namespaces Files Functions Variables Groups Pages
class.XMLOutputStrategy.php
Go to the documentation of this file.
1 <?php
2 /**
3  * wCMF - wemove Content Management Framework
4  * Copyright (C) 2005-2014 wemove digital solutions GmbH
5  *
6  * Licensed under the terms of any of the following licenses
7  * at your choice:
8  *
9  * - GNU Lesser General Public License (LGPL)
10  * http://www.gnu.org/licenses/lgpl.html
11  * - Eclipse Public License (EPL)
12  * http://www.eclipse.org/org/documents/epl-v10.php
13  *
14  * See the license.txt file distributed with this work for
15  * additional information.
16  *
17  * $Id: class.XMLOutputStrategy.php 1462 2014-02-04 23:52:27Z iherwig $
18  */
19 require_once(BASE."wcmf/lib/output/class.OutputStrategy.php");
20 require_once(BASE."wcmf/lib/util/class.FileUtil.php");
21 require_once(BASE."wcmf/lib/util/class.Log.php");
22 
23 /**
24  * @class XMLOutputStrategy
25  * @ingroup Output
26  * @brief This OutputStrategy outputs an object's content in a xml file
27  * using the default format.
28  * @note file locking works not on NFS!
29  *
30  * @author ingo herwig <ingo@wemove.com>
31  */
33 {
34  var $_id = 0;
35  var $_file = '';
36  var $_docType = '';
37  var $_dtd = '';
38  var $_encoding = '';
39  var $_fp = 0;
40  var $_indent = '';
41  var $_linebreak = "\n";
42  var $_tagsToClose = null;
43  var $_lastIndent = -1;
44  var $_fileOk = false; // indicates if we can write to the file
45  /**
46  * Constructor.
47  * @param file The output file name.
48  * @param docType The document type.
49  * @param dtd The document type definition name.
50  * @param encoding The used encoding (default: UTF-8).
51  * @param indent The number of spaces to indent (default: 2).
52  * @param linebreak The linebreak char to use (default: \n).
53  */
54  function XMLOutputStrategy($file, $docType, $dtd, $encoding='UTF-8', $indent=2, $linebreak="\n")
55  {
56  $this->_file = $file;
57  $this->_docType = $docType;
58  $this->_dtd = $dtd;
59  $this->_encoding = $encoding;
60  $this->_indent = str_repeat(' ', $indent);
61  $this->_linebreak = $linebreak;
62  $this->_tagsToClose = array();
63  $this->_fileOk = false;
64  }
65  /**
66  * Write the xml header.
67  */
68  function writeHeader()
69  {
70  // check if file exists and is locked
71  if (file_exists($this->_file))
72  {
73  $this->_fp = fopen($this->_file, "r");
74  if (!$this->_fp)
75  {
76  Log::warn("Can't write to file ".$this->_file.". Another user holds the lock. Try again later.", __CLASS__);
77  return;
78  }
79  else
80  fclose($this->_fp);
81  }
82  // check if file exists and is locked
83  $this->_fp = fopen($this->_file, "w");
84  if ($this->_fp)
85  {
86  if(!flock ($this->_fp, LOCK_EX))
87  Log::warn("Can't lock file ".$this->_file.". Proceeding without.", __CLASS__);
88 
89  $this->_fileOk = true;
90  $this->writeToFile('<?xml version="1.0" encoding="'.$this->_encoding.'"?>'.$this->_linebreak.'<!DOCTYPE '.$this->_docType.' SYSTEM "'.$this->_dtd.'">'.$this->_linebreak);
91  return true;
92  }
93  }
94  /**
95  * Write the xml footer.
96  */
97  function writeFooter()
98  {
99  if ($this->_fileOk)
100  {
101  // print remaining open tags
102  for ($i=0;$i<sizeOf($this->_tagsToClose);$i++)
103  {
104  $closeTag = $this->_tagsToClose[$i];
105  $this->writeToFile(str_repeat($this->_indent, $closeTag["indent"]).'</'.$closeTag["name"].'>'.$this->_linebreak);
106  }
107  flock ($this->_fp, LOCK_UN);
108  fclose($this->_fp);
109  }
110  }
111  /**
112  * Write the object.
113  * @param obj The object to write.
114  */
115  function writeObject(&$obj)
116  {
117  if ($this->_fileOk)
118  {
119  $curIndent = $obj->getDepth();
120  if ($curIndent < $this->_lastIndent)
121  {
122  // write last opened and not closed tags
123  for ($i=$this->_lastIndent-$curIndent;$i>0;$i--)
124  {
125  $closeTag = array_shift($this->_tagsToClose);
126  $this->writeToFile(str_repeat($this->_indent, $closeTag["indent"]).'</'.$closeTag["name"].'>'.$this->_linebreak);
127  }
128  }
129  $tagName = $this->writeObjectContent($obj, $curIndent);
130  if ($tagName != "")
131  {
132  // remember open tag if not closed
133  if ($obj->getNumChildren() > 0)
134  {
135  $closeTag = array("name" => $tagName, "indent" => $curIndent);
136  array_unshift($this->_tagsToClose, $closeTag);
137  }
138  else
139  {
140  //$this->writeToFile($this->_linebreak.str_repeat($this->_indent, $curIndent).'</'.$tagName.'>'.$this->_linebreak);
141  $this->writeToFile('</'.$tagName.'>'.$this->_linebreak);
142  }
143  // remember current indent
144  $this->_lastIndent = $curIndent;
145  }
146  }
147  }
148  /**
149  * Actually write text to the file.
150  * @note subclasses will override this to implement any final conversion.
151  * @param text The text to write
152  */
153  function writeToFile($text)
154  {
155  fputs($this->_fp, $text);
156  }
157  /**
158  * Write the object's content including opening tag, excluding closing tag.
159  * @param obj The object to write.
160  * @param curIndent The current indent.
161  * @return The name of the opening tag
162  */
163  function writeObjectContent(&$obj, $curIndent)
164  {
165  // write object's content
166  $elementName = $this->getElementName($obj);
167 
168  // open tag
169  $this->writeToFile(str_repeat($this->_indent, $curIndent).'<'.$elementName);
170 
171  // write object id
172  if ($this->isWritingOIDs())
173  $this->writeToFile(' id="'.$obj->getOID().'"');
174 
175  // write object attributes
176  $attributeNames = $obj->getValueNames(DATATYPE_ATTRIBUTE);
177  foreach ($attributeNames as $curAttribute)
178  $this->writeAttribute(&$obj, $curAttribute);
179 
180  // close tag
181  $this->writeToFile('>');
182  if ($obj->getNumChildren() > 0)
183  $this->writeToFile($this->_linebreak);
184 
185  // write object element
186  $elementNames = $obj->getValueNames(DATATYPE_ELEMENT);
187  foreach ($elementNames as $curElement)
188  $this->writeElement(&$obj, $curElement);
189 
190  return $elementName;
191  }
192  /**
193  * Determine wether the oid should be written to the file. The default implementation returns true.
194  * @note subclasses will override this to implement special application requirements.
195  * @return True/False wether the oid should be written
196  */
197  function isWritingOIDs()
198  {
199  return true;
200  }
201  /**
202  * Write an object value of type DATATYPE_ELEMENT.
203  * @note subclasses will override this to implement special application requirements.
204  * @param obj The object to write
205  * @param name The name of the value
206  */
207  function writeElement(&$obj, $name)
208  {
209  $value = $obj->getValue($name, DATATYPE_ELEMENT);
210  if ($value != '')
211  {
212  $value = $this->getElementValue($obj, $name, $value);
213  $this->writeToFile($value);
214  }
215  }
216  /**
217  * Get the xml element name for an object. The default implementation returns the result of the getType() method.
218  * @note subclasses will override this to implement special application requirements.
219  * @param obj The object to write
220  * @return The xml name of the element
221  */
222  function getElementName(&$obj)
223  {
224  return $obj->getType();
225  }
226  /**
227  * Get the xml element value for an object. The default implementation replaces newlines by <br>
228  * and applies htmlspecialchars to the result.
229  * @note subclasses will override this to implement special application requirements.
230  * @param obj The object to write
231  * @param name The name of the element
232  * @param value The value to write
233  * @return The xml value
234  */
235  function getElementValue(&$obj, $name, $value)
236  {
237  return htmlspecialchars(preg_replace("/\r\n|\n\r|\n|\r/", "<br />", $value));
238  }
239  /**
240  * Write an object value of type DATATYPE_ATTRIBUTE.
241  * @note subclasses will override this to implement special application requirements.
242  * @param obj The object to write
243  * @param name The name of the value
244  */
245  function writeAttribute(&$obj, $name)
246  {
247  $value = $obj->getValue($name, DATATYPE_ATTRIBUTE);
248  if ($value != '')
249  {
250  $value = $this->getAttributeValue($obj, $name, $value);
251  $this->writeToFile(' '.$this->getAttributeName($obj, $name).'="'.$value.'"');
252  }
253  }
254  /**
255  * Get the xml attribute name for an object value. The default implementation returns the name of the attribute.
256  * @note subclasses will override this to implement special application requirements.
257  * @param obj The object to write
258  * @param name The name of the attribute
259  * @return The xml name of the attribute
260  */
261  function getAttributeName(&$obj, $name)
262  {
263  return $name;
264  }
265  /**
266  * Get the xml attribute value for an object value. The default implementation replaces newlines by <br>
267  * and applies htmlspecialchars to the result.
268  * @note subclasses will override this to implement special application requirements.
269  * @param obj The object to write
270  * @param name The name of the attribute
271  * @param value The value to write
272  * @return The xml value
273  */
274  function getAttributeValue(&$obj, $name, $value)
275  {
276  return htmlspecialchars(preg_replace("/\r\n|\n\r|\n|\r/", "<br />", $value));
277  }
278 }
279 ?>
writeObjectContent(&$obj, $curIndent)
warn($message, $category)
Definition: class.Log.php:59
OutputStrategy is used to write an object's content to a destination (called 'document') using a spec...
const DATATYPE_ATTRIBUTE
XMLOutputStrategy($file, $docType, $dtd, $encoding='UTF-8', $indent=2, $linebreak="\n")
const DATATYPE_ELEMENT
This OutputStrategy outputs an object's content in a xml file using the default format.
getAttributeValue(&$obj, $name, $value)
getElementValue(&$obj, $name, $value)