Blame view

php/classes/TimeTableMgr.php 19.9 KB
16035364   Benjamin Renard   First commit
1
2
3
4
5
6
7
8
9
<?php

/**
 * @class TimeTableMgr
 * @version $Id: TimeTableMgr.php 2809 2015-03-05 09:50:52Z natacha $
 * @todo MANAGE TT created by Search and Plot interactive - HERE?
 *
 */

4a438b99   elena   catalog draft
10
class TimeTableMgr extends AmdaObjectMgr
139a8045   Nathanaël Jourdane   autocleanup
11
{
d8ec1623   Nathanaël Jourdane   fix phpcs warnings
12
13
14
15
16
17
	/**
	 * TimeTableMgr constructor.
	 * @param null $user The user
	 * @param bool $sharedObject Shared object
	 */
	public function __construct($user = null, $sharedObject = false)
4a438b99   elena   catalog draft
18
	{
16035364   Benjamin Renard   First commit
19
20
21
		parent::__construct('Tt.xml');
		$this->contentRootId = 'timeTable-treeRootNode';
		$this->contentRootTag = 'timetabList';
d8ec1623   Nathanaël Jourdane   fix phpcs warnings
22
23
		$this->attributes = ['name' => '', 'intervals' => ''];
		$this->optionalAttributes = [];
16035364   Benjamin Renard   First commit
24
25
26
		$this->objTagName = 'timetab';
		$this->id_prefix = 'tt_';

169f14d2   Benjamin Renard   Add shared object...
27
		if (!$sharedObject && !file_exists($this->xmlName)) {
139a8045   Nathanaël Jourdane   autocleanup
28
29
			$this->createDom();
			$this->xp = new domxpath($this->contentDom);
16035364   Benjamin Renard   First commit
30
31
		}
	}
139a8045   Nathanaël Jourdane   autocleanup
32
33

	protected function createDom()
3ed056c4   Elena.Budnik   redmine #5278
34
	{
d8ec1623   Nathanaël Jourdane   fix phpcs warnings
35
		$types = ['timetab' => 'timeTable', 'catalog' => 'catalog'];
16035364   Benjamin Renard   First commit
36
37

		$rootElement = $this->contentDom->createElement('ws');
139a8045   Nathanaël Jourdane   autocleanup
38

3ed056c4   Elena.Budnik   redmine #5278
39
		foreach ($types as $key => $value) {
139a8045   Nathanaël Jourdane   autocleanup
40
41
			$contentId = $value . '-treeRootNode';
			$contentTag = $key . 'List';
3ed056c4   Elena.Budnik   redmine #5278
42
43
44
			$typeElement = $this->contentDom->createElement($contentTag);
			$typeElement->setAttribute('xml:id', $contentId);
			$rootElement->appendChild($typeElement);
16035364   Benjamin Renard   First commit
45
		}
4a438b99   elena   catalog draft
46
		$this->contentDom->appendChild($rootElement);
16035364   Benjamin Renard   First commit
47
		$this->contentDom->save($this->xmlName);
3ed056c4   Elena.Budnik   redmine #5278
48
	}
16035364   Benjamin Renard   First commit
49

d8ec1623   Nathanaël Jourdane   fix phpcs warnings
50
51
52
53
54
55
56
	/**
	 * Get object
	 * @param $id
	 * @param $nodeType
	 * @return array
	 */
	public function getObject($id, $nodeType = null)
4a438b99   elena   catalog draft
57
	{
139a8045   Nathanaël Jourdane   autocleanup
58
59
60
61
62
63
64
		if (substr($nodeType, 0, 6) == 'shared') {
			//Shared object
			$sharedObjMgr = new SharedObjectsMgr();
			$path = $sharedObjMgr->getDataFilePath(str_replace('shared', '', $nodeType), $id);
		} else {
			$path = USERTTDIR . $id . '.xml';
		}
16035364   Benjamin Renard   First commit
65

139a8045   Nathanaël Jourdane   autocleanup
66
		if (!file_exists($path)) {
d8ec1623   Nathanaël Jourdane   fix phpcs warnings
67
			return ['error' => NO_OBJECT_FILE];
139a8045   Nathanaël Jourdane   autocleanup
68
69
70
		}
		$this->objectDom->load($path);
		if (!($objToGet = $this->objectDom->getElementById($id))) {
d8ec1623   Nathanaël Jourdane   fix phpcs warnings
71
			return ['error' => NO_SUCH_ID];
139a8045   Nathanaël Jourdane   autocleanup
72
73
74
75
76
77
78
79
80
81
82
83
84
85
		}
		$attributesToReturn['id'] = $objToGet->getAttribute('xml:id');
		$attributes = $objToGet->childNodes;

		$nbInt = 0;
		foreach ($attributes as $attribute) {
			if ($attribute->nodeType == XML_ELEMENT_NODE) {
				/*if ($attribute->tagName == 'intervals') {
					$start = $attribute -> getElementsByTagName('start')->item(0) -> nodeValue;
					$stop = $attribute -> getElementsByTagName('stop')->item(0) -> nodeValue;
					$attributesToReturn['intervals'][] = array('start' => $start, 'stop' => $stop);
				}
				else
				$attributesToReturn[$attribute->tagName] =  $attribute->nodeValue;*/
0fea5567   Benjamin Renard   First step for re...
86
				//BRE - load all except intervals - Intervals will be loaded later with 'loadIntervalsFromObject' function
139a8045   Nathanaël Jourdane   autocleanup
87
88
89
90
91
92
93
				if ($attribute->tagName != 'intervals') {
					$attributesToReturn[$attribute->tagName] = $attribute->nodeValue;
				} else {
					$nbInt++;
				}
			}
		}
139a8045   Nathanaël Jourdane   autocleanup
94
95
96
		$attributesToReturn['nbIntervals'] = $nbInt;

		return $attributesToReturn;
16035364   Benjamin Renard   First commit
97
98
	}

d8ec1623   Nathanaël Jourdane   fix phpcs warnings
99
100
101
102
103
	/**
	 * Modify an object
	 * @param $p
	 * @return array
	 */
139a8045   Nathanaël Jourdane   autocleanup
104
	public function modifyObject($p)
4a438b99   elena   catalog draft
105
	{
139a8045   Nathanaël Jourdane   autocleanup
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
		$folder = $this->getObjectFolder($p->id);

		//Copy TT in a tempory file
		$ttFilePath = USERTTDIR . $p->id . '.xml';
		$tmpFileExist = false;
		if (file_exists($ttFilePath)) {
			$tmpFileExist = copy($ttFilePath, $ttFilePath . ".tmp");
		}

		//Delete TT
		$this->deleteObject($p);

		//Save modifications
		try {
			$result = $this->createObject($p, $folder);
			if ($result['error']) {
				throw new Exception($result['error']);
			}
			if ($tmpFileExist) {
				unlink($ttFilePath . ".tmp");
			}
d8ec1623   Nathanaël Jourdane   fix phpcs warnings
127
128
			return ['id' => $p->id, 'info' => $result['info']];
		} catch (Exception $exception) {
139a8045   Nathanaël Jourdane   autocleanup
129
130
131
132
133
			//Restore TT file
			if ($tmpFileExist) {
				copy($ttFilePath . ".tmp", $ttFilePath);
				unlink($ttFilePath . ".tmp");
			}
d8ec1623   Nathanaël Jourdane   fix phpcs warnings
134
			return ['error' => $exception->getMessage()];
139a8045   Nathanaël Jourdane   autocleanup
135
		}
16035364   Benjamin Renard   First commit
136
137
	}

d8ec1623   Nathanaël Jourdane   fix phpcs warnings
138
139
140
141
142
143
	/**
	 * Create an object
	 * @param $p
	 * @param $folder
	 * @return array
	 */
139a8045   Nathanaël Jourdane   autocleanup
144
145
146
147
148
149
150
151
152
	public function createObject($p, $folder)
	{
		if ($p->leaf) {
			$result = $this->createParameter($p, $folder);
			if ($result['error']) {
				return $result;
			}
			$cacheMgr = new TimeTableCacheMgr();
			if (isset($p->cacheToken) && ($p->cacheToken != '')) {
0fea5567   Benjamin Renard   First step for re...
153
				$resultSaveInt = $cacheMgr->saveInObject($result['id'], "update", $p->cacheToken);
139a8045   Nathanaël Jourdane   autocleanup
154
155
				if (!$resultSaveInt['success']) {
					if ($resultSaveInt['message']) {
d8ec1623   Nathanaël Jourdane   fix phpcs warnings
156
						return ['error' => $resultSaveInt['message']];
139a8045   Nathanaël Jourdane   autocleanup
157
					} else {
d8ec1623   Nathanaël Jourdane   fix phpcs warnings
158
						return ['error' => 'Unknown error during intervals save'];
139a8045   Nathanaël Jourdane   autocleanup
159
160
161
162
					}
				}
			}
			return $result;
d8ec1623   Nathanaël Jourdane   fix phpcs warnings
163
164
165
166
		} else {
			return ['error' => 'createFolder should be called from RENAME'];
			// return $this->createFolder($p);
			// TODO check if this is possible?
139a8045   Nathanaël Jourdane   autocleanup
167
		}
16035364   Benjamin Renard   First commit
168
	}
16035364   Benjamin Renard   First commit
169

d8ec1623   Nathanaël Jourdane   fix phpcs warnings
170
171
172
173
174
175
	/**
	 * Create parameter (in case of catalogs)
	 * @param $p
	 * @param $folder
	 * @return array
	 */
4a438b99   elena   catalog draft
176
177
	protected function createParameter($p, $folder)
	{
139a8045   Nathanaël Jourdane   autocleanup
178
179
180
		if ($this->objectExistsByName($p->name)) {
			$p->id = $this->getObjectIdByName($p->name);
			$this->deleteObject($p);
16035364   Benjamin Renard   First commit
181
		}
139a8045   Nathanaël Jourdane   autocleanup
182

16035364   Benjamin Renard   First commit
183
184
		$this->id = $this->setId();
		$this->created = date('Y-m-d\TH:i:s');
139a8045   Nathanaël Jourdane   autocleanup
185
		if (!$this->id) {
d8ec1623   Nathanaël Jourdane   fix phpcs warnings
186
			return ['error' => ID_CREATION_ERROR];
139a8045   Nathanaël Jourdane   autocleanup
187
188
189
		}

		$this->resFileName = USERTTDIR . $this->id . '.xml';
d8ec1623   Nathanaël Jourdane   fix phpcs warnings
190
		// TODO catalog root element = 'timetable'
16035364   Benjamin Renard   First commit
191
		$rootElement = $this->objectDom->createElement('timetable');
139a8045   Nathanaël Jourdane   autocleanup
192
193
194
		$rootElement->setAttribute('xml:id', $this->id);

		foreach ($p as $key => $value) {
3ed056c4   Elena.Budnik   redmine #5278
195
196
			if ($key != 'id' && $key != 'leaf' && $key != 'nodeType' &&
				$key != 'objName' && $key != 'objFormat' && $key != 'folderId' && $key != 'cacheToken') {
139a8045   Nathanaël Jourdane   autocleanup
197
198
199
200
201
202
203
204
205
				if ($key == 'created') {
					$rootElement->appendChild($this->objectDom->createElement($key, $this->created));
				} // it is catalog
				else {
					if ($key == 'parameters') {
						$paramsElement = $this->setParamDescription($value);
						if ($paramsElement) {
							$rootElement->appendChild($paramsElement);
						}
139a8045   Nathanaël Jourdane   autocleanup
206
207
208
209
					} else {
						if ($key != 'intervals') {
							$rootElement->appendChild($this->objectDom->createElement($key, htmlspecialchars($value)));
						}
3ed056c4   Elena.Budnik   redmine #5278
210
					}
139a8045   Nathanaël Jourdane   autocleanup
211
				}
d18b535d   elena   catalog draft + c...
212
			}
139a8045   Nathanaël Jourdane   autocleanup
213
		}
16035364   Benjamin Renard   First commit
214
215
216
217
218
219

		$this->objectDom->appendChild($rootElement);
		$this->objectDom->save($this->resFileName);
		$obj = new stdClass();
		$obj->name = $p->name;
		$obj->intervals = $p->nbIntervals;
139a8045   Nathanaël Jourdane   autocleanup
220
		$this->addToContent($obj, $folder);
d8ec1623   Nathanaël Jourdane   fix phpcs warnings
221
222
		// FIXME field created is undefined
		return ['id' => $this->id, 'created' => $this->created, 'info' => $obj->intervals . ' intervals'];
16035364   Benjamin Renard   First commit
223
224
	}

d8ec1623   Nathanaël Jourdane   fix phpcs warnings
225
226
227
228
229
	/**
	 * Set parameter description
	 * TODO
	 * @param $param string The parameter
	 * @return DOMNode
139a8045   Nathanaël Jourdane   autocleanup
230
	 */
139a8045   Nathanaël Jourdane   autocleanup
231
	protected function setParamDescription($param)
4a438b99   elena   catalog draft
232
	{
d8ec1623   Nathanaël Jourdane   fix phpcs warnings
233
		return new DOMNode();
4a438b99   elena   catalog draft
234
	}
139a8045   Nathanaël Jourdane   autocleanup
235

d8ec1623   Nathanaël Jourdane   fix phpcs warnings
236
	/**
53048303   Benjamin Renard   Cleanup TimeTable...
237
	 * Load TT content from dom documentElement
d8ec1623   Nathanaël Jourdane   fix phpcs warnings
238
	 */
53048303   Benjamin Renard   Cleanup TimeTable...
239
240
	 protected function loadObjectFile($dom, $onlyDescription, $start = null, $limit = null) {
		$attributesToReturn = array();
16035364   Benjamin Renard   First commit
241

139a8045   Nathanaël Jourdane   autocleanup
242
243
244
245
		$descNodes = $dom->getElementsByTagName('description');
		if ($descNodes->length > 0) {
			$attributesToReturn['description'] = $descNodes->item(0)->nodeValue;
		}
16035364   Benjamin Renard   First commit
246

139a8045   Nathanaël Jourdane   autocleanup
247
248
249
250
251
252
253
254
255
256
		$creatNodes = $dom->getElementsByTagName('created');
		if ($creatNodes->length > 0) {
			$attributesToReturn['created'] = $creatNodes->item(0)->nodeValue;
		}

		$histNodes = $dom->getElementsByTagName('history');
		if ($histNodes->length > 0) {
			$attributesToReturn['history'] = $histNodes->item(0)->nodeValue;
		}

53048303   Benjamin Renard   Cleanup TimeTable...
257
258
259
260
		$nameNodes = $dom->getElementsByTagName('name');
		if ($nameNodes->length > 0) {
			$attributesToReturn['name'] = $nameNodes->item(0)->nodeValue;
		}
139a8045   Nathanaël Jourdane   autocleanup
261
262

		if (!$onlyDescription) {
53048303   Benjamin Renard   Cleanup TimeTable...
263
264
			$attributesToReturn['intervals'] = array();

e01ca7c5   Benjamin Renard   Improve performan...
265
			$xpath = new DOMXPath($dom);
d8ec1623   Nathanaël Jourdane   fix phpcs warnings
266

e01ca7c5   Benjamin Renard   Improve performan...
267
268
			$intervals = $xpath->query('//intervals');

53048303   Benjamin Renard   Cleanup TimeTable...
269
270
271
			if (!isset($start) || !isset($limit)) {
				foreach ($intervals as $interval) {
					$attributesToReturn['intervals'][] = $this->loadIntervalElement($interval);
139a8045   Nathanaël Jourdane   autocleanup
272
				}
53048303   Benjamin Renard   Cleanup TimeTable...
273
274
275
276
277
278
			} else {
				for ($iInt = 0; $iInt < $limit; ++$iInt) {
					if ($start + $iInt >= $intervals->length) {
						break;
					}
					$attributesToReturn['intervals'][] = $this->loadIntervalElement($intervals->item($start + $iInt));
16035364   Benjamin Renard   First commit
279
				}
16035364   Benjamin Renard   First commit
280
			}
16035364   Benjamin Renard   First commit
281
		}
139a8045   Nathanaël Jourdane   autocleanup
282
283

		return $attributesToReturn;
16035364   Benjamin Renard   First commit
284
	}
139a8045   Nathanaël Jourdane   autocleanup
285

d8ec1623   Nathanaël Jourdane   fix phpcs warnings
286
	/**
53048303   Benjamin Renard   Cleanup TimeTable...
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
	 * Get uploaded object
	 * @param $name
	 * @param $format
	 * @param bool $onlyDescription
	 * @return mixed
	 */
  public function getUploadedObject($name, $format, $onlyDescription = false)
 {
	 if (strpos($name, '.xml') !== false) {
		 $temp = explode('.xml', $name);
		 $name = $temp[0];
	 }

	 if (!file_exists(USERTEMPDIR . $name . '.xml')) {
		 return ['error' => 'no such name'];
	 }

	 $this->objectDom->load(USERTEMPDIR . $name . '.xml');
	 if (!($objToGet = $this->objectDom->getElementsByTagName('timetable')->item(0)) &&
		 !($objToGet = $this->objectDom->getElementsByTagName('TimeTable')->item(0))) {
		 return ['error' => 'no time table'];
	 }

	 return array(
		 'name'      => $name,
		 'objName'   => $name,
		 'objFormat' => $format,
		 'success'   => TRUE,
	 ) + $this->loadObjectFile($this->objectDom, $onlyDescription);
 }


	/*****************************************************************
	 *                           PUBLIC FUNCTIONS
	 *****************************************************************/

	/*
	 *   Get Object into Edit
	 */
	public function getTmpObject($folderId, $name, $onlyDescription = false)
 	{
 		$filePath = USERWORKINGDIR . $folderId . '/' . $name . '.xml';
 		if (!file_exists($filePath)) {
 			return ['error' => 'Cannot find result file'];
 		}

 		$dom = new DomDocument('1.0');
 		$dom->formatOutput = true;

 		if (!$dom->load($filePath)) {
 			return ['error' => 'Cannot load result file'];
 		}

 		return array(
 			'objName' => $name,
 			'folderId' => $folderId,
			'success' => TRUE,
 		) + $this->loadObjectFile($dom, $onlyDescription);
 	}

	/**
d8ec1623   Nathanaël Jourdane   fix phpcs warnings
348
349
350
351
	 * Merge time tables
	 * @param $obj
	 * @return array
	 */
139a8045   Nathanaël Jourdane   autocleanup
352
353
354
355
356
357
358
359
360
	public function merge($obj)
	{
		/**
		 * Array of intervals, used like :
		 * [{start:'2010-01-01T23:00:00',stop:'2011-01-01T20:00:00'},{start:'2009-01-01T23:00:00',stop:'2010-01-01T20:00:00'}]
		 * $attributesToReturn['intervals'][] = array('start' => $start, 'stop' => $stop);
		 */

		$intervals = 0;
d8ec1623   Nathanaël Jourdane   fix phpcs warnings
361
		for ($iId = 0; $iId < count($obj->ids); $iId++) {
0fea5567   Benjamin Renard   First step for re...
362
			$table[$iId] = $this->loadIntervalsFromObject($obj->ids[$iId]);
d8ec1623   Nathanaël Jourdane   fix phpcs warnings
363
364
365
			for ($jId = 0; $jId < count($table[$iId]['intervals']); $jId++) {
				$interval[$iId][$jId][0] = $table[$iId]['intervals'][$jId]['start'];
				$interval[$iId][$jId][1] = $table[$iId]['intervals'][$jId]['stop'];
139a8045   Nathanaël Jourdane   autocleanup
366
			}
d8ec1623   Nathanaël Jourdane   fix phpcs warnings
367
			$intervals += count($interval[$iId]);
16035364   Benjamin Renard   First commit
368
		}
139a8045   Nathanaël Jourdane   autocleanup
369
370
371
372
		if ($intervals > 10000) {
			set_time_limit(1800);
		}

d8ec1623   Nathanaël Jourdane   fix phpcs warnings
373
374
375
		$final = [];
		for ($iId = 0; $iId < count($obj->ids); $iId++) {
			$final = array_merge($final, $interval[$iId]);
139a8045   Nathanaël Jourdane   autocleanup
376
377
378
379
380
		}
		sort($final);

		// Algorithm of union
		$line = 0;
d8ec1623   Nathanaël Jourdane   fix phpcs warnings
381
382
383
384
385
		$iId = 0;
		$val = $final[$iId][0];
		while ($iId < count($final) - 1) {
			if ($final[$iId + 1][1] <= $final[$iId][1]) {
				array_splice($final, $iId + 1, 1);
139a8045   Nathanaël Jourdane   autocleanup
386
			} else {
d8ec1623   Nathanaël Jourdane   fix phpcs warnings
387
388
				if (($final[$iId + 1][0] <= $final[$iId][1]) && ($final[$iId + 1][1] >= $final[$iId][1])) {
					$iId++;
139a8045   Nathanaël Jourdane   autocleanup
389
				} else {
d8ec1623   Nathanaël Jourdane   fix phpcs warnings
390
391
392
					$start[$line] = $val;
					$stop[$line] = $final[$iId][1];
					$iId++;
139a8045   Nathanaël Jourdane   autocleanup
393
					$line++;
d8ec1623   Nathanaël Jourdane   fix phpcs warnings
394
					$val = $final[$iId][0];
139a8045   Nathanaël Jourdane   autocleanup
395
				}
16035364   Benjamin Renard   First commit
396
			}
16035364   Benjamin Renard   First commit
397
		}
d8ec1623   Nathanaël Jourdane   fix phpcs warnings
398
399
		$start[$line] = $val;
		$stop[$line] = $final[$iId][1];
139a8045   Nathanaël Jourdane   autocleanup
400
401
402
403
404
405
406

		$objTT = new stdClass();
		$objTT->name = $obj->name;
		$objTT->nodeType = 'timeTable';
		$objTT->leaf = true;
		$objTT->created = null;
		$objTT->history = $obj->history;
d8ec1623   Nathanaël Jourdane   fix phpcs warnings
407
		for ($iId = 0; $iId < count($start); $iId++) {
a9285c23   Benjamin Renard   Fix TT merge & in...
408
409
410
411
			$inter = array(
				'start' => $start[$iId],
				'stop' => $stop[$iId],
			);
139a8045   Nathanaël Jourdane   autocleanup
412
413
414
415
416
417
			$objTT->intervals[] = $inter;
		}
		$objTT->nbIntervals = count($start);
		$this->objectDom = new DomDocument('1.0');
		$this->objectDom->formatOutput = true;

d8ec1623   Nathanaël Jourdane   fix phpcs warnings
418
		$res = $this->createParameter($objTT, $folder); // FIXME $folder is undefined
139a8045   Nathanaël Jourdane   autocleanup
419
420
421
422
423
		if ($res['error']) {
			return $res;
		}

		$this->saveIntervals($res['id'], $objTT->intervals, 'merge');
139a8045   Nathanaël Jourdane   autocleanup
424
		return $res;
16035364   Benjamin Renard   First commit
425
	}
139a8045   Nathanaël Jourdane   autocleanup
426

d8ec1623   Nathanaël Jourdane   fix phpcs warnings
427
428
429
430
431
432
433
434
	/**
	 * Load intervals from time table
	 * @param $id
	 * @param $typeTT
	 * @param null $start
	 * @param null $limit
	 * @return array
	 */
53048303   Benjamin Renard   Cleanup TimeTable...
435
436
	 public function loadIntervalsFromObject($id, $typeTT = '', $start = null, $limit = null)
 	{
d54a1a7b   Benjamin Renard   Fix load from sha...
437
 		if ($typeTT == 'sharedtimeTable' || $typeTT == 'sharedcatalog') {
53048303   Benjamin Renard   Cleanup TimeTable...
438
439
 			//Shared object
 			$sharedObjMgr = new SharedObjectsMgr();
d54a1a7b   Benjamin Renard   Fix load from sha...
440
441
			$sharedType = ($typeTT == 'sharedcatalog') ? 'catalog' : 'timeTable';
 			$path = $sharedObjMgr->getDataFilePath($sharedType, $id);
53048303   Benjamin Renard   Cleanup TimeTable...
442
443
444
445
446
447
 		} else {
 			$path = USERTTDIR . $id . '.xml';
 		}

 		//load intervals from TT id
 		if (!file_exists($path)) {
d54a1a7b   Benjamin Renard   Fix load from sha...
448
 			return ['success' => false, 'message' => "Cannot find TT file " . $id ];
53048303   Benjamin Renard   Cleanup TimeTable...
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
 		}

 		$this->objectDom->load($path);
 		if (!($objToGet = $this->objectDom->getElementById($id))) {
 			return ['success' => false, 'message' => NO_SUCH_ID . " " . $id];
 		}

 		$result = $this->loadObjectFile($this->objectDom, FALSE, $start, $limit);

 		return array(
 			'totalCount' => $result['totalCount'],
 			'intervals' => $result['intervals'],
 			'start' => isset($start) ? $start : 0,
 			'limit' => isset($limit) ? $limit : 0,
 			'success' => true,
 		);
 	}
139a8045   Nathanaël Jourdane   autocleanup
466

d8ec1623   Nathanaël Jourdane   fix phpcs warnings
467
468
469
470
471
472
473
	/**
	 * Save intervals
	 * @param $id
	 * @param $intervals
	 * @param $action
	 * @return array
	 */
42e2e019   Benjamin Renard   Next step for cac...
474
	public function saveIntervals($id, $intervals, $action, $options = array())
3ed056c4   Elena.Budnik   redmine #5278
475
	{
139a8045   Nathanaël Jourdane   autocleanup
476
		if (substr($id, 0, 6) == 'shared') {
d8ec1623   Nathanaël Jourdane   fix phpcs warnings
477
			return ['success' => false, 'message' => "Cannot save shared TimeTable"];
139a8045   Nathanaël Jourdane   autocleanup
478
479
480
481
		} else {
			$path = USERTTDIR . $id . '.xml';
		}
		if (!file_exists($path)) {
d8ec1623   Nathanaël Jourdane   fix phpcs warnings
482
			return ['success' => false, 'message' => "Cannot find TT file " . $id];
139a8045   Nathanaël Jourdane   autocleanup
483
484
485
486
		}
		$this->objectDom->load($path);

		if (!($objToGet = $this->objectDom->getElementById($id))) {
d8ec1623   Nathanaël Jourdane   fix phpcs warnings
487
			return ['success' => false, 'message' => NO_SUCH_ID . " " . $id];
3ed056c4   Elena.Budnik   redmine #5278
488
		}
16035364   Benjamin Renard   First commit
489

3ed056c4   Elena.Budnik   redmine #5278
490
491
		//remove old intervals
		$crtNode = $objToGet->firstChild;
139a8045   Nathanaël Jourdane   autocleanup
492

3ed056c4   Elena.Budnik   redmine #5278
493
		while ($crtNode) {
139a8045   Nathanaël Jourdane   autocleanup
494
			if (($crtNode->nodeType != XML_ELEMENT_NODE) || ($crtNode->tagName != 'intervals')) {
3ed056c4   Elena.Budnik   redmine #5278
495
496
497
498
499
500
501
502
				$crtNode = $crtNode->nextSibling;
				continue;
			}
			$toRemove = $crtNode;
			$crtNode = $crtNode->nextSibling;
			$objToGet->removeChild($toRemove);
			unset($toRemove);
		}
139a8045   Nathanaël Jourdane   autocleanup
503

3ed056c4   Elena.Budnik   redmine #5278
504
		//add new intervals
139a8045   Nathanaël Jourdane   autocleanup
505
		foreach ($intervals as $interval) {
42e2e019   Benjamin Renard   Next step for cac...
506
			$newInterval = $this->createIntervalElement($interval, $options);
3ed056c4   Elena.Budnik   redmine #5278
507
508
			$this->objectDom->documentElement->appendChild($newInterval);
		}
16035364   Benjamin Renard   First commit
509

3ed056c4   Elena.Budnik   redmine #5278
510
511
		//save modifications
		$this->id = $id;
139a8045   Nathanaël Jourdane   autocleanup
512
		$this->resFileName = USERTTDIR . $this->id . '.xml';
3ed056c4   Elena.Budnik   redmine #5278
513
		$this->objectDom->save($this->resFileName);
139a8045   Nathanaël Jourdane   autocleanup
514

3ed056c4   Elena.Budnik   redmine #5278
515
		unset($this->objectDom);
139a8045   Nathanaël Jourdane   autocleanup
516

d8ec1623   Nathanaël Jourdane   fix phpcs warnings
517
		return ['success' => true, 'action' => $action, 'nbIntervals' => count($intervals)];
3ed056c4   Elena.Budnik   redmine #5278
518
	}
139a8045   Nathanaël Jourdane   autocleanup
519

d8ec1623   Nathanaël Jourdane   fix phpcs warnings
520
	/**
53048303   Benjamin Renard   Cleanup TimeTable...
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
	 * Load interval from DOMElement
	 * @param DOMElement
	 * @return interval
	 */
	protected function loadIntervalElement($intervalNode)
	{
		$startTimes = $intervalNode->getElementsByTagName('start');
		$stopTimes = $intervalNode->getElementsByTagName('stop');

		if (($startTimes->length != 1) || ($stopTimes->length != 1)) {
			return FALSE;
		}

		return array(
			'start' => $startTimes->item(0)->nodeValue,
			'stop' => $stopTimes->item(0)->nodeValue,
		);
	}

	/**
d8ec1623   Nathanaël Jourdane   fix phpcs warnings
541
542
543
544
	 * Create interval element
	 * @param $interval
	 * @return DOMElement
	 */
42e2e019   Benjamin Renard   Next step for cac...
545
	protected function createIntervalElement($interval, $options = array())
3ed056c4   Elena.Budnik   redmine #5278
546
	{
139a8045   Nathanaël Jourdane   autocleanup
547
		$newInterval = $this->objectDom->createElement('intervals');
42e2e019   Benjamin Renard   Next step for cac...
548
549
		$newInterval->appendChild($this->objectDom->createElement('start', $interval['start']));
		$newInterval->appendChild($this->objectDom->createElement('stop', $interval['stop']));
139a8045   Nathanaël Jourdane   autocleanup
550
551
552
		return $newInterval;
	}

d8ec1623   Nathanaël Jourdane   fix phpcs warnings
553
554
555
556
557
	/**
	 * Intersect time tables
	 * @param $obj
	 * @return array|string
	 */
139a8045   Nathanaël Jourdane   autocleanup
558
559
	public function intersect($obj)
	{
d8ec1623   Nathanaël Jourdane   fix phpcs warnings
560
561
		$intervals = 0;
		for ($iId = 0; $iId < count($obj->ids); $iId++) {
0fea5567   Benjamin Renard   First step for re...
562
			$table[$iId] = $this->loadIntervalsFromObject($obj->ids[$iId]);
d8ec1623   Nathanaël Jourdane   fix phpcs warnings
563
564
565
			for ($jId = 0; $jId < count($table[$iId]['intervals']); $jId++) {
				$interval[$iId][$jId][0] = $table[$iId]['intervals'][$jId]['start'];
				$interval[$iId][$jId][1] = $table[$iId]['intervals'][$jId]['stop'];
139a8045   Nathanaël Jourdane   autocleanup
566
			}
d8ec1623   Nathanaël Jourdane   fix phpcs warnings
567
			$intervals += count($interval[$iId]);
16035364   Benjamin Renard   First commit
568
		}
139a8045   Nathanaël Jourdane   autocleanup
569
570
		if ($intervals > 10000) {
			set_time_limit(1800);
16035364   Benjamin Renard   First commit
571
		}
16035364   Benjamin Renard   First commit
572

139a8045   Nathanaël Jourdane   autocleanup
573
574
575
		// Sort intervals in time tables
		sort($interval[0]);
		sort($interval[1]);
16035364   Benjamin Renard   First commit
576

d8ec1623   Nathanaël Jourdane   fix phpcs warnings
577
578
		$iId = 0;
		$jId = 0;
139a8045   Nathanaël Jourdane   autocleanup
579
580
		$line = 0;

d8ec1623   Nathanaël Jourdane   fix phpcs warnings
581
582
		while (($iId < count($interval[0])) && ($jId < count($interval[1]))) {
			$inter = $this->callIntersection($interval[0][$iId], $interval[1][$jId]);
139a8045   Nathanaël Jourdane   autocleanup
583
584
585
586
587
588
589

			if ($inter[0][0] != 0 && $inter[0][1] != 0) {
				$start[$line] = $inter[0][0];
				$stop[$line] = $inter[0][1];
				$line++;
			}

d8ec1623   Nathanaël Jourdane   fix phpcs warnings
590
591
			if ($interval[0][$iId][1] < $interval[1][$jId][1]) {
				$iId++;
139a8045   Nathanaël Jourdane   autocleanup
592
			} else {
d8ec1623   Nathanaël Jourdane   fix phpcs warnings
593
				$jId++;
139a8045   Nathanaël Jourdane   autocleanup
594
595
596
597
598
599
600
			}
		}

		// Intersection is empty
		if ($line == 0) {
			$result = "empty";
		} else {
d8ec1623   Nathanaël Jourdane   fix phpcs warnings
601
			$objTT->name = $obj->name;  // FIXME $objTT is undefined
139a8045   Nathanaël Jourdane   autocleanup
602
603
604
605
			$objTT->nodeType = 'timeTable';
			$objTT->leaf = true;
			$objTT->created = null;
			$objTT->history = $obj->history;
d8ec1623   Nathanaël Jourdane   fix phpcs warnings
606
			for ($iId = 0; $iId < count($start); $iId++) {
a9285c23   Benjamin Renard   Fix TT merge & in...
607
608
609
610
				$inter = array(
					'start' => $start[$iId],
					'stop' => $stop[$iId],
				);
139a8045   Nathanaël Jourdane   autocleanup
611
612
613
614
615
616
617
618
619
				$objTT->intervals[] = $inter;
			}
			$objTT->nbIntervals = count($start);

			if (count($objTT->intervals) == 0) {
				$result = "empty";
			} else {
				$this->objectDom = new DomDocument('1.0');
				$this->objectDom->formatOutput = true;
d8ec1623   Nathanaël Jourdane   fix phpcs warnings
620
				$result = $this->createObject($objTT, $folder); // FIXME $folder is undefined
139a8045   Nathanaël Jourdane   autocleanup
621
622
623

				if (!isset($result['error'])) {
					$this->saveIntervals($result['id'], $objTT->intervals, 'intersect');
3ed056c4   Elena.Budnik   redmine #5278
624
				}
16035364   Benjamin Renard   First commit
625
			}
3ed056c4   Elena.Budnik   redmine #5278
626
		}
139a8045   Nathanaël Jourdane   autocleanup
627
628
629
		return $result;
	}

d8ec1623   Nathanaël Jourdane   fix phpcs warnings
630
631
632
633
634
635
636
	/**
	 * Call intersection
	 * @param $fst
	 * @param $snd
	 * @return array
	 */
	protected function callIntersection($fst, $snd)
139a8045   Nathanaël Jourdane   autocleanup
637
638
639
	{
		$inf = ($fst[0] > $snd[0]) ? $fst[0] : $snd[0];
		$sup = ($fst[1] < $snd[1]) ? $fst[1] : $snd[1];
d8ec1623   Nathanaël Jourdane   fix phpcs warnings
640
		$inter[] = ($inf >= $sup) ? [0, 0] : [$inf, $sup];
139a8045   Nathanaël Jourdane   autocleanup
641
		return $inter;
16035364   Benjamin Renard   First commit
642
643
	}

d8ec1623   Nathanaël Jourdane   fix phpcs warnings
644
645
646
647
648
649
650
	/**
	 * Valid name object
	 * TODO getObject only!!!! => change DD_Search output
	 * @param $p
	 * @return array
	 */
	public function validNameObject($p)
139a8045   Nathanaël Jourdane   autocleanup
651
652
653
654
655
656
657
658
659
660
	{
		// overwritten
		$res = parent::validNameObject($p);

		if (!$res['valid']) {
			return $res;
		}

		//no space
		if (strpos($p->name, ' ') === false) {
d8ec1623   Nathanaël Jourdane   fix phpcs warnings
661
			return ['valid' => true];
16035364   Benjamin Renard   First commit
662
		}
139a8045   Nathanaël Jourdane   autocleanup
663

d8ec1623   Nathanaël Jourdane   fix phpcs warnings
664
		return ['valid' => false, 'error' => 'Space character is not allowed'];
16035364   Benjamin Renard   First commit
665
666
	}

d8ec1623   Nathanaël Jourdane   fix phpcs warnings
667
668
669
670
671
672
673
674
675
	/**
	 * Copy time table
	 * @param $src_path
	 * @param $dst_path
	 * @param $newId
	 * @param $newName
	 * @param null $newDescription
	 * @return bool
	 */
139a8045   Nathanaël Jourdane   autocleanup
676
	public function copyTT($src_path, $dst_path, $newId, $newName, $newDescription = null)
3ed056c4   Elena.Budnik   redmine #5278
677
	{
139a8045   Nathanaël Jourdane   autocleanup
678
679
680
681
682
683
684
685
		if (!file_exists($src_path)) {
			return false;
		}

		if (!is_dir($dst_path)) {
			return false;
		}

169f14d2   Benjamin Renard   Add shared object...
686
687
		$dom = new DomDocument('1.0');
		$dom->formatOutput = true;
139a8045   Nathanaël Jourdane   autocleanup
688
689
690
691
692

		if (!$dom->load($src_path)) {
			return false;
		}

169f14d2   Benjamin Renard   Add shared object...
693
		$timeTableNodes = $dom->getElementsByTagName('timetable');
139a8045   Nathanaël Jourdane   autocleanup
694
695
696
697
		if ($timeTableNodes->length <= 0) {
			return false;
		}

169f14d2   Benjamin Renard   Add shared object...
698
		$timeTableNode = $timeTableNodes->item(0);
139a8045   Nathanaël Jourdane   autocleanup
699

169f14d2   Benjamin Renard   Add shared object...
700
		$timeTableNode->setAttribute('xml:id', $newId);
139a8045   Nathanaël Jourdane   autocleanup
701

169f14d2   Benjamin Renard   Add shared object...
702
		$nameNodes = $timeTableNode->getElementsByTagName('name');
139a8045   Nathanaël Jourdane   autocleanup
703

247b38e9   Benjamin Renard   Fix function used...
704
		if ($nameNodes->length <= 0) {
169f14d2   Benjamin Renard   Add shared object...
705
706
707
			//create name node (normally never append)
			$nameNode = $dom->createElement('name');
			$timeTableNode->appendChild($nameNode);
139a8045   Nathanaël Jourdane   autocleanup
708
		} else {
169f14d2   Benjamin Renard   Add shared object...
709
			$nameNode = $nameNodes->item(0);
139a8045   Nathanaël Jourdane   autocleanup
710
711
		}

169f14d2   Benjamin Renard   Add shared object...
712
		$nameNode->nodeValue = $newName;
139a8045   Nathanaël Jourdane   autocleanup
713

09eefb2d   Benjamin Renard   Shared TT and Cat...
714
715
		if (isset($newDescription) && !empty($newDescription)) {
			$descriptionNodes = $timeTableNode->getElementsByTagName('description');
247b38e9   Benjamin Renard   Fix function used...
716
			if ($descriptionNodes->length <= 0) {
09eefb2d   Benjamin Renard   Shared TT and Cat...
717
718
719
				//create description node (normally never append)
				$descriptionNode = $dom->createElement('description');
				$timeTableNode->appendChild($descriptionNode);
139a8045   Nathanaël Jourdane   autocleanup
720
			} else {
09eefb2d   Benjamin Renard   Shared TT and Cat...
721
				$descriptionNode = $descriptionNodes->item(0);
139a8045   Nathanaël Jourdane   autocleanup
722
723
			}

09eefb2d   Benjamin Renard   Shared TT and Cat...
724
725
			$descriptionNode->nodeValue = $newDescription;
		}
139a8045   Nathanaël Jourdane   autocleanup
726

d8ec1623   Nathanaël Jourdane   fix phpcs warnings
727
728
		$dstFilePath = $dst_path . "/" . $newId . ".xml";
		if ($dom->save($dstFilePath) === false) {
139a8045   Nathanaël Jourdane   autocleanup
729
730
731
			return false;
		}

d8ec1623   Nathanaël Jourdane   fix phpcs warnings
732
733
		chgrp($dstFilePath, APACHE_USER);
		chmod($dstFilePath, 0775);
139a8045   Nathanaël Jourdane   autocleanup
734
735
736
737

		return true;
	}

d8ec1623   Nathanaël Jourdane   fix phpcs warnings
738
739
740
741
742
	/**
	 * Rename in resource
	 * @param $name
	 * @param $id
	 * @return bool
139a8045   Nathanaël Jourdane   autocleanup
743
	 */
139a8045   Nathanaël Jourdane   autocleanup
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
	protected function renameInResource($name, $id)
	{
		if (!file_exists(USERTTDIR . $id . '.xml')) {
			return false;
		}

		$this->objectDom->load(USERTTDIR . $id . '.xml');
		if (!($objToRename = $this->objectDom->getElementById($id))) {
			return false;
		}
		$objToRename->getElementsByTagName('name')->item(0)->nodeValue = $name;
		$this->objectDom->save(USERTTDIR . $id . '.xml');

		return true;
	}

d8ec1623   Nathanaël Jourdane   fix phpcs warnings
760
761
762
763
	/**
	 * Delete parameter
	 * @param $id
	 */
139a8045   Nathanaël Jourdane   autocleanup
764
765
766
767
768
769
770
	protected function deleteParameter($id)
	{
		if (file_exists(USERTTDIR . $id . '.xml')) {
			unlink(USERTTDIR . $id . '.xml');
		}
	}

d8ec1623   Nathanaël Jourdane   fix phpcs warnings
771
772
773
774
775
	/**
	 * Rename only
	 * @param $p
	 * @return bool
	 */
139a8045   Nathanaël Jourdane   autocleanup
776
777
778
779
	protected function renameOnly($p)
	{
		//if (!($p->intervals)) return true;
		return false;
3ed056c4   Elena.Budnik   redmine #5278
780
	}
16035364   Benjamin Renard   First commit
781
}