Blame view

php/classes/TimeTableMgr.php 19.8 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++) {
139a8045   Nathanaël Jourdane   autocleanup
408
			$inter = new stdClass();
d8ec1623   Nathanaël Jourdane   fix phpcs warnings
409
410
			$inter->start = $start[$iId];
			$inter->stop = $stop[$iId];
139a8045   Nathanaël Jourdane   autocleanup
411
412
413
414
415
416
			$objTT->intervals[] = $inter;
		}
		$objTT->nbIntervals = count($start);
		$this->objectDom = new DomDocument('1.0');
		$this->objectDom->formatOutput = true;

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

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

d8ec1623   Nathanaël Jourdane   fix phpcs warnings
426
427
428
429
430
431
432
433
	/**
	 * Load intervals from time table
	 * @param $id
	 * @param $typeTT
	 * @param null $start
	 * @param null $limit
	 * @return array
	 */
53048303   Benjamin Renard   Cleanup TimeTable...
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
	 public function loadIntervalsFromObject($id, $typeTT = '', $start = null, $limit = null)
 	{
 		if ($typeTT == 'sharedtimeTable') {
 			//Shared object
 			$sharedObjMgr = new SharedObjectsMgr();
 			$path = $sharedObjMgr->getDataFilePath('timeTable', $id);
 		} else {
 			$path = USERTTDIR . $id . '.xml';
 		}

 		//load intervals from TT id
 		if (!file_exists($path)) {
 			return ['success' => false, 'message' => "Cannot find TT file " . $id];
 		}

 		$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
464

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

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

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

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

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

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

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

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

d8ec1623   Nathanaël Jourdane   fix phpcs warnings
518
	/**
53048303   Benjamin Renard   Cleanup TimeTable...
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
	 * 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
539
540
541
542
	 * Create interval element
	 * @param $interval
	 * @return DOMElement
	 */
42e2e019   Benjamin Renard   Next step for cac...
543
	protected function createIntervalElement($interval, $options = array())
3ed056c4   Elena.Budnik   redmine #5278
544
	{
139a8045   Nathanaël Jourdane   autocleanup
545
		$newInterval = $this->objectDom->createElement('intervals');
42e2e019   Benjamin Renard   Next step for cac...
546
547
		$newInterval->appendChild($this->objectDom->createElement('start', $interval['start']));
		$newInterval->appendChild($this->objectDom->createElement('stop', $interval['stop']));
139a8045   Nathanaël Jourdane   autocleanup
548
549
550
		return $newInterval;
	}

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

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

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

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

			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
588
589
			if ($interval[0][$iId][1] < $interval[1][$jId][1]) {
				$iId++;
139a8045   Nathanaël Jourdane   autocleanup
590
			} else {
d8ec1623   Nathanaël Jourdane   fix phpcs warnings
591
				$jId++;
139a8045   Nathanaël Jourdane   autocleanup
592
593
594
595
596
597
598
			}
		}

		// Intersection is empty
		if ($line == 0) {
			$result = "empty";
		} else {
d8ec1623   Nathanaël Jourdane   fix phpcs warnings
599
			$objTT->name = $obj->name;  // FIXME $objTT is undefined
139a8045   Nathanaël Jourdane   autocleanup
600
601
602
603
			$objTT->nodeType = 'timeTable';
			$objTT->leaf = true;
			$objTT->created = null;
			$objTT->history = $obj->history;
d8ec1623   Nathanaël Jourdane   fix phpcs warnings
604
			for ($iId = 0; $iId < count($start); $iId++) {
139a8045   Nathanaël Jourdane   autocleanup
605
				$inter = new stdClass();
d8ec1623   Nathanaël Jourdane   fix phpcs warnings
606
607
				$inter->start = $start[$iId];
				$inter->stop = $stop[$iId];
139a8045   Nathanaël Jourdane   autocleanup
608
609
610
611
612
613
614
615
616
				$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
617
				$result = $this->createObject($objTT, $folder); // FIXME $folder is undefined
139a8045   Nathanaël Jourdane   autocleanup
618
619
620

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

		return true;
	}

d8ec1623   Nathanaël Jourdane   fix phpcs warnings
735
736
737
738
739
	/**
	 * Rename in resource
	 * @param $name
	 * @param $id
	 * @return bool
139a8045   Nathanaël Jourdane   autocleanup
740
	 */
139a8045   Nathanaël Jourdane   autocleanup
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
	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
757
758
759
760
	/**
	 * Delete parameter
	 * @param $id
	 */
139a8045   Nathanaël Jourdane   autocleanup
761
762
763
764
765
766
767
	protected function deleteParameter($id)
	{
		if (file_exists(USERTTDIR . $id . '.xml')) {
			unlink(USERTTDIR . $id . '.xml');
		}
	}

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