/
Session.php
303 lines (254 loc) · 9.16 KB
/
Session.php
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
<?php
/**
*
* The Session object provides read and write access to the content of a particular workspace in the repository.
* The Session object is returned by Repository->login(Credentials, string).
* It encapsulates both the authorization settings of a particular user (as specified by the passed Credentials) and a binding to the workspace specified by the workspace name passed on login.
* Each Session object is associated one-to-one with a Workspace object.
* The Workspace object represents a "view" of an actual repository workspace entity as seen through the authorization settings of its associated Session.
* Session class represents the entry point into the content repository.
* @author
* @version 1.0
*
*/
class Session {
private $credentials;
private $pm;
private $workspace;
/**
*
* Creates a new Session object, given a particular user (as specified by the passed Credentials) and named workspace.
* @param Credentials $credentials the credentials of the user.
* @param string $workspace the name of the workspace.
*
*/
public function __construct(&$pm) {
$this->pm =& $pm;
$this->credentials = $pm->getCredentials();
$this->workspace = $pm->getWorkspace();
}
public function __destruct() {
}
private function buildXML(Node $node, $xml) {
$xml .= '<node name="' . htmlentities($node->getName(), ENT_QUOTES, 'UTF-8') . '">';
if ($node->hasProperties()) {
$xml = $this->buildXMLProperties($node, $xml);
}
if ($node->hasNodes()) {
$ni = $node->getNodes();
while ($ni->hasNext()) {
$temporaryNode = $ni->nextNode();
if ($temporaryNode->hasNodes()) {
$xml = $this->buildXML($temporaryNode, $xml);
} else {
$xml .= '<node name="' . htmlentities($temporaryNode->getName(), ENT_QUOTES, 'UTF-8') . '">';
if ($temporaryNode->hasProperties()) {
$xml = $this->buildXMLProperties($temporaryNode, $xml);
}
$xml .= '</node>';
}
}
}
return $xml .= '</node>';
}
private function buildXMLProperties(Node $node, $xml) {
$pi = $node->getProperties();
while ($pi->hasNext()) {
$property = $pi->nextProperty();
$xml .= '<property name="' . htmlentities($property->getName(), ENT_QUOTES, 'UTF-8') . '">';
if ($property->getType() == 'array') {
foreach ($property->getValues() as $value) {
$xml .= '<value>' . htmlentities($value, ENT_QUOTES, 'UTF-8') . '</value>';
}
} else {
$xml .= '<value>' . htmlentities($property->getValue(), ENT_QUOTES, 'UTF-8') . '</value>';
}
$xml .= '</property>';
}
return $xml;
}
private function checkLocks(Node $node) {
if ($node->isLocked()) {
throw new LockException("cannot move locked node: $this->workspace=>" . $node->getPath());
} else if ($node->hasNodes()) {
$ni = $node->getNodes();
while ($ni->hasNext()) {
$temporaryNode = $ni->nextNode();
if ($temporaryNode->hasNodes()) {
$this->checkLocks($temporaryNode);
} else if ($temporaryNode->isLocked()) {
throw new LockException("cannot move locked node: $this->workspace=>" . $temporaryNode->getPath());
}
}
}
}
/**
*
* Serializes the node at $path into a series of SAX events by calling the methods of the supplied SimpleXML class.
* The resulting XML is in the system view form.
* Note that $path must be the path of a node, not a property.
* A PathNotFoundException is thrown if no node exists at $path.
* @param string $path the path of the node and it's descendants to export.
* @return string containing the XML of the nodes and properites found during the export.
*
*/
public function exportXML($path) {
if ($path != 'pcr:root') {
if ($this->pm->getNode($path) === null) {
throw new PathNotFoundException("$this->workspace=>$path");
}
}
$xml = $this->buildXML(new Node($this->pm, $path), '<?xml version="1.0" encoding="UTF-8"?>');
Log4PCR::info("Requested XML export of item: $this->workspace=>$path");
return $xml;
}
/**
*
* Returns the value of the named attribute as a string, or null if no attribute of the given name exists.
* @param string $name specifying the name of the attribute.
* @return string|null containing the value of the attribute, or null if the attribute does not exist.
*
*/
public function getAttribute($name) {
return $this->credentials->getAttribute($name);
}
/**
*
* Returns the names of the attributes available to this credentials instance.
* This method returns an empty array if the credentials instance has no attributes available to it.
* @return array containing the names of the stored attributes.
*
*/
public function getAttributeNames() {
return $this->credentials->getAttributeNames();
}
/**
*
* Returns the item at the specified absolute path in the workspace.
* @param string $path an absolute path.
* @return Item an item.
*
*/
public function getItem($path) {
if ($this->pm->getNode($path) !== null) {
$item = new Item($this->pm, $path);
$type = 'Node';
} else {
$lastSlash = strrpos($path, '/');
$parent = substr($path, 0, $lastSlash);
$property = substr($path, $lastSlash + 1);
$result = $this->pm->getProperty($parent, $property);
if ($result !== null) {
$item = new Item($this->pm, $parent, $property, $result);
$type = 'Property';
} else {
throw new PathNotFoundException("$this->workspace=>$path");
}
}
Log4PCR::info("Requested item ($type): $this->workspace=>$path");
return $item;
}
/**
*
* Returns the root node of the workspace.
* The root node, "pcr:root", is the main access point to the content of the workspace.
* @return Node the root node of the workspace: a Node object.
*
*/
public function getRootNode() {
Log4PCR::info("Requested node: $this->workspace=>pcr:root");
return new Node($this->pm, 'pcr:root');
}
/**
*
* Returns the user ID.
* @return string the user ID.
*
*/
public function getUserID() {
return $this->credentials->getUserID();
}
/**
*
* Returns the Workspace attached to this Session.
* @return Workspace a Workspace object.
*
*/
public function getWorkspace() {
return new Workspace($this->pm);
}
/**
*
* Returns true if this Session object is usable by the client.
* Otherwise, returns false.
* A usable Session is one that is neither logged-out, timed-out nor in any other way disconnected from the repository.
* @return boolean true if this Session is usable, false otherwise.
*
*/
public function isLive() {
return $this->pm->isLive();
}
/**
*
* Returns true if an item exists at $path; otherwise returns false.
* Also returns false if the specified $path is malformed.
* @param string $path an absolute path.
* @return boolean true if an item exists at $path; otherwise returns false.
*
*/
public function itemExists($path) {
if ($this->pm->getNode($path) !== null) {
$itemExists = true;
} else {
$lastSlash = strrpos($path, '/');
$parent = substr($path, 0, $lastSlash);
$property = substr($path, $lastSlash + 1);
if ($this->pm->getProperty($parent, $property) !== null) {
$itemExists = true;
} else {
$itemExists = false;
}
}
return $itemExists;
}
/**
*
* Releases all resources associated with this Session.
* This method should be called when a Session is no longer needed.
*
*/
public function logout() {
$this->__destruct();
}
/**
*
* Moves the node at $sourcePath (and its entire subtree) to the new location at $destinationPath.
* Strictly speaking, the $destinationPath parameter is actually an absolute path to the parent node of the new location, appended with the new name desired for the moved node.
* If no node exists at $sourcePath or no node exists one level above $destinationPath (in other words, there is no node that will serve as the parent of the moved item) then a PathNotFoundException is thrown immediately.
* An ItemExistsException is thrown immediately if a node already exists at $destinationPath.
* A LockException is thrown immediately if a node lock prevents the move.
* A RepositoryException is thrown if the "pcr:root" node is tried to be moved or moved to.
* @param string $sourcePath the root of the subtree to be moved.
* @param string $destinationPath the location to which the subtree is to be moved.
*
*/
public function move($sourcePath, $destinationPath) {
if ($sourcePath == 'pcr:root') {
throw new RepositoryException("cannot move node: $this->workspace=>pcr:root");
} else if ($this->pm->getNode($sourcePath) === null) {
throw new PathNotFoundException("$this->workspace=>$sourcePath");
} else if ($this->pm->getNode($destinationPath) !== null) {
throw new ItemExistsException("$this->workspace=>$destinationPath");
}
$parent = substr($destinationPath, 0, strrpos($destinationPath, '/'));
if ($parent != 'pcr:root') {
if ($this->pm->getNode($parent) === null) {
throw new PathNotFoundException("$this->workspace=>$parent");
}
}
$this->checkLocks(new Node($this->pm, $sourcePath));
Log4PCR::info("Moved node (and its descendants, if any): $this->workspace=>$sourcePath to $this->workspace=>$destinationPath");
$this->pm->move($sourcePath, $destinationPath);
}
}
?>