DotOutputStrategy.php
1 <?php
2 /**
3  * wCMF - wemove Content Management Framework
4  * Copyright (C) 2005-2020 wemove digital solutions GmbH
5  *
6  * Licensed under the terms of the MIT License.
7  *
8  * See the LICENSE file distributed with this work for
9  * additional information.
10  */
11 namespace wcmf\lib\model\output;
12 
16 
17 /**
18  * DotOutputStrategy outputs an object's content in a dot file.
19  * @note file locking works not on NFS!
20  *
21  * @author ingo herwig <ingo@wemove.com>
22  */
24 
25  const DEFAULT_NODE_STYLE = 'height=0.1,width=1,shape=box,style=filled,color="#49B4CF",fillcolor="#49B4CF",fontcolor=white,fontsize=14,fontname="Helvetica-Bold"';
26  const DEFAULT_EDGE_STYLE = 'color="#49B4CF"';
27 
28  private $file = '';
29  private $fp = 0;
30  private $fileOk = false; // indicates if we can write to the file
31  private $nodeIndex = 0;
32  private $nodeIndexMap = [];
33  private $writtenNodes = [];
34 
35  private $nodeStyle = '';
36  private $edgeStyle = '';
37 
38  private static $logger = null;
39 
40  /**
41  * Constructor.
42  * @param $file The output file name.
43  * @param $nodeStyle Style definition to use for nodes (see dot documentation).
44  * @param $edgeStyle Style definition to use for edges (see dot documentation).
45  */
46  public function __construct($file, $nodeStyle='', $edgeStyle='') {
47  $this->file = $file;
48  $this->fileOk = false;
49 
50  if ($nodeStyle != '') {
51  $this->nodeStyle = $nodeStyle;
52  }
53  else {
54  $this->nodeStyle = self::DEFAULT_NODE_STYLE;
55  }
56  if ($edgeStyle != '') {
57  $this->edgeStyle = $edgeStyle;
58  }
59  else {
60  $this->edgeStyle = self::DEFAULT_EDGE_STYLE;
61  }
62  if (self::$logger == null) {
63  self::$logger = LogManager::getLogger(__CLASS__);
64  }
65  }
66 
67  /**
68  * @see OutputStrategy::writeHeader
69  */
70  public function writeHeader() {
71  // check if file exists and is locked
72  if (file_exists($this->file)) {
73  $this->fp = fopen($this->file, "r");
74  if (!$this->fp) {
75  self::$logger->warn("Can't write to file ".$this->file.". Another user holds the lock. Try again later.");
76  return;
77  }
78  else {
79  fclose($this->fp);
80  }
81  }
82  // check if file exists and is locked
83  $this->fp = fopen($this->file, "w");
84  if ($this->fp) {
85  if (flock ($this->fp, LOCK_EX)) {
86  $this->fileOk = true;
87  fputs($this->fp, "digraph G {\n\n");
88  fputs($this->fp, " node [".$this->nodeStyle."]\n");
89  fputs($this->fp, " edge [".$this->edgeStyle."]\n\n");
90  return true;
91  }
92  }
93  }
94 
95  /**
96  * @see OutputStrategy::writeFooter
97  */
98  public function writeFooter() {
99  if ($this->fileOk) {
100  fputs($this->fp, "\n}\n");
101  flock ($this->fp, LOCK_UN);
102  fclose($this->fp);
103  }
104  }
105 
106  /**
107  * @see OutputStrategy::writeObject
108  */
109  public function writeObject(PersistentObject $obj) {
110  if ($this->isWritten($obj)) {
111  return;
112  }
113  if ($this->fileOk) {
114  fputs($this->fp, ' n'.$this->getIndex($obj).' [label="'.$obj->getDisplayValue().'"]'."\n");
115  $children = $obj->getChildren(false);
116  for($i=0; $i<sizeOf($children); $i++) {
117  fputs($this->fp, ' n'.$this->getIndex($obj).' -> n'.$this->getIndex($children[$i])."\n");
118  }
119  fputs($this->fp, "\n");
120  }
121  $oidStr = $obj->getOID()->__toString();
122  $this->writtenNodes[$oidStr] = true;
123  }
124 
125  /**
126  * Check if a node is written.
127  * @param $node The node to check
128  * @return Boolean
129  */
130  private function isWritten($node) {
131  $oidStr = $node->getOID()->__toString();
132  return (isset($this->writtenNodes[$oidStr]));
133  }
134 
135  /**
136  * Get the node index.
137  * @param $node The node to get the index of
138  * @return Number
139  */
140  private function getIndex($node) {
141  $oidStr = $node->getOID()->__toString();
142  if (!isset($this->nodeIndexMap[$oidStr])) {
143  $this->nodeIndexMap[$oidStr] = $this->getNextIndex();
144  }
145  return $this->nodeIndexMap[$oidStr];
146  }
147 
148  /**
149  * Get the next node index.
150  * @return Number
151  */
152  private function getNextIndex() {
153  return $this->nodeIndex++;
154  }
155 }
156 ?>
OutputStrategy defines the interface for classes that write an object's content to a destination (cal...
getDisplayValue()
Get the value of the object used for display.
getOID()
Get the object id of the PersistentObject.
__construct($file, $nodeStyle='', $edgeStyle='')
Constructor.
static getLogger($name)
Get the logger with the given name.
Definition: LogManager.php:37
PersistentObject defines the interface of all persistent objects.
LogManager is used to retrieve Logger instances.
Definition: LogManager.php:20
DotOutputStrategy outputs an object's content in a dot file.