Parser   A
last analyzed

Complexity

Total Complexity 14

Size/Duplication

Total Lines 122
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 4

Importance

Changes 0
Metric Value
wmc 14
lcom 1
cbo 4
dl 0
loc 122
rs 10
c 0
b 0
f 0

3 Methods

Rating   Name   Duplication   Size   Complexity  
A buildDocumentTreeFromFilePath() 0 13 2
C fillNode() 0 30 8
A fillNodeAttributes() 0 12 4
1
<?php
2
3
namespace OpenMindParser;
4
5
use OpenMindParser\Models\Document;
6
use OpenMindParser\Models\Node;
7
use OpenMindParser\Models\Icon;
8
use OpenMindParser\Models\NodeList;
9
use \InvalidArgumentException;
10
use \DOMDocument;
11
use \DOMElement;
12
use \DOMNamedNodeMap;
13
14
/*The class responsible to build the objects tree representing the openMind document.*/
15
class Parser
16
{
17
	/**
18
	 * @const String NODE_NODENAME : a constant with the name of the XML node with data to store.
19
	 */
20
	const NODE_NODENAME = 'node';
21
	/**
22
	 * @var Array $nodeAvailableAttributes : list of available attributes in XML tag NODE_NODENAME.
23
	 */
24
	private static $nodeAvailableAttributes = [
25
		'ID'       => 'id',
26
		'COLOR'    => 'color',
27
		'CREATED'  => 'created',
28
		'MODIFIED' => 'modified',
29
		'POSITION' => 'position',
30
		'VSHIFT'   => 'vshift',
31
		'FOLDED'   => 'folded',
32
		'TEXT'     => 'text',
33
	];
34
	/**
35
	 * @const String FONT_NODENAME : a constant with the name of the XML node with data to store for font matter.
36
	 */
37
	const FONT_NODENAME = 'font';
38
	/**
39
	 * @var Array $fontAvailableAttributes : list of available attributes in XML tag FONT_NODENAME.
40
	 */
41
	private static $fontAvailableAttributes = [
42
		'NAME'   => 'fontName',
43
		'SIZE'   => 'fontSize',
44
		'BOLD'   => 'bold',
45
		'ITALIC' => 'italic',
46
	];
47
	/**
48
	 * @const String ICON_NODENAME : a constant with the name of the XML node with data to store for icon matter.
49
	 */
50
	const ICON_NODENAME = 'icon';
51
	/**
52
	 * @var Array $iconAvailableAttributes : list of available attributes in XML tag ICON_NODENAME.
53
	 */
54
	private static $iconAvailableAttributes = [
55
		'BUILTIN' => 'icon',
56
	];
57
	
58
	/**
59
	 * Build the document tree (all objects) out of the file given in parameter.
60
	 * 
61
	 * @param String $filePath : The path to the openMind file.
62
	 * 
63
	 * @return Document : The document instance with all its nodes instances.
64
	 */
65
	public function buildDocumentTreeFromFilePath($filePath) {
66
		if(!file_exists($filePath)) {
67
			throw new InvalidArgumentException('The given path : "'.$filePath.'" is invalid.');
68
		}
69
		
70
		$domDocument = new DOMDocument();
71
		$domDocument->load($filePath);
72
		
73
		//Get the first node named 'self::NODE_NODENAME' and make a Node object out of it.
74
		$rootNode = $this->fillNode($domDocument->getElementsByTagName(self::NODE_NODENAME)->item(0));
75
		
76
		return new Document($domDocument, $rootNode, $filePath, basename($filePath), filesize($filePath));
77
	}
78
	
79
	/**
80
	 * Create and fill the node instance with all the data stored in the XML file
81
	 * 
82
	 * @param DOMElement $domNode : The current XML 'node' element to build the Node object.
83
	 * 
84
	 * @return Node : The created Node (and all its children).
85
	 */
86
	private function fillNode(DOMElement $domNode) {
87
		//The given node name must be self::NODE_NODENAME
88
		if($domNode->nodeName !== self::NODE_NODENAME) {
89
			throw new InvalidNodeNameException('The node name must be "node". "'.$domNode->nodeName.'" given.');
90
		}
91
		
92
		$node = new Node($domNode);
93
		
94
		$this->fillNodeAttributes($domNode->attributes, self::$nodeAvailableAttributes, $node);
95
		
96
		//Build the list of children nodes and fill font information.
97
		$children = new NodeList();
98
		foreach($domNode->childNodes as $childNode) {
99
			if($childNode->nodeName === self::NODE_NODENAME) {
100
				$children->add($this->fillNode($childNode));
101
			} elseif($childNode->nodeName === self::FONT_NODENAME) {
102
				$this->fillNodeAttributes($childNode->attributes, self::$fontAvailableAttributes, $node);
103
			} elseif($childNode->nodeName === self::ICON_NODENAME) {
104
				foreach($childNode->attributes as $attribute) {
105
					if(array_key_exists($attribute->nodeName, self::$iconAvailableAttributes)) {
106
						$node->setIcon(new Icon($attribute->nodeValue));
107
					}
108
				}
109
			}
110
		}
111
		
112
		$node->setChildren($children);
113
		
114
		return $node;
115
	}
116
	
117
	/**
118
	 * For each attribute whom the name is the keys of $availableAttributes, its value will be put in the matching attribute.
119
	 * 
120
	 * @param DOMNamedNodeMap $nodeAtributes : The list of attributes of the current node to fill the Node object.
121
	 * @param array $availableAttributes : One of the static array of this class to describe the list of known attributes.
122
	 * @param Node $node : The Node object to fill in.
123
	 */
124
	private function fillNodeAttributes (DOMNamedNodeMap $nodeAtributes, array $availableAttributes, Node $node) {
125
		foreach($nodeAtributes as $attribute) {
126
			if(array_key_exists($attribute->nodeName, $availableAttributes)) {
127
				call_user_func([
128
						$node, 
129
						sprintf('openMindParser\Models\Node::set%s', ucfirst($availableAttributes[$attribute->nodeName]))
130
					], 
131
					json_decode($attribute->nodeValue) ?: $attribute->nodeValue
132
				);
133
			}
134
		}
135
	}
136
}