Blame view

php/classes/VOTableMgr.php 16.7 KB
16035364   Benjamin Renard   First commit
1
2
3
<?php
/**
 * @class VOTableMgr
10200969   Roipoussiere   Remove whitespace...
4
 * @version $Id: VOTableMgr.php 2916 2015-05-19 13:08:33Z elena $
16035364   Benjamin Renard   First commit
5
6
 */

8e8f453c   Nathanael Jourdane   VOTable parser: r...
7
8
//set DEBUG_MODE to TRUE to have some log information
define("DEBUG_MODE", FALSE);
16035364   Benjamin Renard   First commit
9
10

class VOTableMgr {
30cd92df   Roipoussiere   Fix merge conflicts
11
12
13
	public  $xml = null;
	private $log;
	private $xp;
5de62950   Nathanael Jourdane   Improve the VOTab...
14
15
	private $stream; // The stream in the VOTable
	private $c; // Current character position on the stream
e581690d   Nathanael Jourdane   Fix VOtable conve...
16
	private $is_little_endian;
b97c59e9   Nathanael Jourdane   Provide to the us...
17
	private $votable_error = false;
10200969   Roipoussiere   Remove whitespace...
18
19

  function __construct()
16035364   Benjamin Renard   First commit
20
21
22
23
  {
  	 if (DEBUG_MODE)
  	   $this->log = fopen(USERDATADIR."logVOTable","w");
  }
10200969   Roipoussiere   Remove whitespace...
24

16035364   Benjamin Renard   First commit
25
26
27
28
29
  function addLog($msg)
  {
  	 if (DEBUG_MODE)
  	   fprintf($this->log,$msg);
  }
10200969   Roipoussiere   Remove whitespace...
30

16035364   Benjamin Renard   First commit
31
32
  function load($fileName)
  {
30cd92df   Roipoussiere   Fix merge conflicts
33
34
35
36
37
38
39
40
41
42
43
44
	$this->is_little_endian = array_values(unpack('L1L', pack('V', 1)))[0] == 1;

	// see http://php.net/manual/en/domdocument.load.php#91384
	$options = array(
		'http' => array(
			'method' => 'GET',
			'timeout' => '5',
			'user_agent' => 'PHP libxml agent',
			// If the query is wrong, epn-tap service returns an HTTP error code 400, along with xml containing some usefull informations.
			'ignore_errors' => true
		)
	);
e57cb025   Benjamin Renard   Fix most of error...
45
46
47
48
49
50
51
52
53
54

	// BRE - Add proxy host if exists
	if (defined('HTTP_PROXY_HOST')) {
		$options['http']['proxy'] = 'tcp://'.HTTP_PROXY_HOST;
		$options['http']['request_fulluri'] = TRUE;
		if (defined('HTTP_PROXY_USER')) {
			$options['http']['header'] = "Proxy-Authorization: Basic ".base64_encode(HTTP_PROXY_USER);
		}
	}

30cd92df   Roipoussiere   Fix merge conflicts
55
56
57
58
	$context = stream_context_create($options);
	libxml_set_streams_context($context);
	$this->xml = new DomDocument();

e57cb025   Benjamin Renard   Fix most of error...
59
	if (!@$this->xml->load($fileName)) {
30cd92df   Roipoussiere   Fix merge conflicts
60
61
62
		$this->votable_error = 'Can not load xml file.';
		return false;
	}
10200969   Roipoussiere   Remove whitespace...
63

30cd92df   Roipoussiere   Fix merge conflicts
64
	$this->checkIDAttribute();
10200969   Roipoussiere   Remove whitespace...
65

30cd92df   Roipoussiere   Fix merge conflicts
66
67
68
	$rootNamespace = $this->xml->lookupNamespaceUri($this->xml->namespaceURI);
	$this->xp = new domxpath($this->xml);
	$this->xp->registerNameSpace('x', $rootNamespace);
10200969   Roipoussiere   Remove whitespace...
69

30cd92df   Roipoussiere   Fix merge conflicts
70
71
	return true;
  }
10200969   Roipoussiere   Remove whitespace...
72

30cd92df   Roipoussiere   Fix merge conflicts
73
74
  function getVotableError() {
	  return $this->votable_error;
16035364   Benjamin Renard   First commit
75
  }
10200969   Roipoussiere   Remove whitespace...
76

16035364   Benjamin Renard   First commit
77
78
  function isValidSchema()
  {
30cd92df   Roipoussiere   Fix merge conflicts
79
80
81
82
83
84
85
86
87
88
89
90
91
	if ($this->votable_error != false) {
		return false;
	}

	if (!$this->xml) {
		$this->votable_error = "The returned file is not XML.";
		return false;
	}

	$infos = $this->xp->query($this->queryResourceInfo());
	foreach($infos as $info) {
		if($info->getAttribute('value') == 'ERROR') {
			$this->votable_error = $info->textContent;
5de62950   Nathanael Jourdane   Improve the VOTab...
92
			return false;
f534c4a8   Nathanael Jourdane   Make the VOTable ...
93
		}
30cd92df   Roipoussiere   Fix merge conflicts
94
	}
10200969   Roipoussiere   Remove whitespace...
95
96


16035364   Benjamin Renard   First commit
97
98
  	 //ToDo - BRE - add validation!!
  	 return TRUE;
10200969   Roipoussiere   Remove whitespace...
99

16035364   Benjamin Renard   First commit
100
101
  	 if (DEBUG_MODE)
  	   libxml_use_internal_errors(true);
10200969   Roipoussiere   Remove whitespace...
102

16035364   Benjamin Renard   First commit
103
  	 $vers = $this->getVersion();
10200969   Roipoussiere   Remove whitespace...
104

16035364   Benjamin Renard   First commit
105
  	 $this->addLog("VOTable version : ".$vers."\n");
10200969   Roipoussiere   Remove whitespace...
106

16035364   Benjamin Renard   First commit
107
  	 $result = FALSE;
10200969   Roipoussiere   Remove whitespace...
108

16035364   Benjamin Renard   First commit
109
110
111
112
113
114
115
116
117
  	 switch ($vers)
  	 {
  	 	 case '1.2' :
  	 	 	 $result = $this->xml->schemaValidate(XMLPATH.'VOTable-1.2.xsd');
  	 	 case '1.0' :
  	 	 	 $result = $this->xml->schemaValidate(XMLPATH.'VOTable-1.0.xsd');
  	 	 default :
  	 	   $result = $this->xml->schemaValidate(XMLPATH.'VOTable-1.1.xsd');
  	 }
10200969   Roipoussiere   Remove whitespace...
118

16035364   Benjamin Renard   First commit
119
120
121
  	 if (DEBUG_MODE)
  	 {
  	   $errors = libxml_get_errors();
10200969   Roipoussiere   Remove whitespace...
122
123

  	   foreach ($errors as $error)
16035364   Benjamin Renard   First commit
124
  	   {
10200969   Roipoussiere   Remove whitespace...
125
126
  	   	 $msg = '';

16035364   Benjamin Renard   First commit
127
128
129
130
131
132
133
134
135
136
137
138
139
        switch ($error->level)
        {
          case LIBXML_ERR_WARNING:
            $msg .= ("WARNING ".$error->code.": ");
            break;
          case LIBXML_ERR_ERROR:
            $msg .= ("ERROR ".$error->code.": ");
            break;
          case LIBXML_ERR_FATAL:
            $msg .= ("FATAL ".$error->code.": ");
            break;
        }
        $msg .= ($error->message." - In line : ".$error->line." - Of file : ".$error->file."\n");
10200969   Roipoussiere   Remove whitespace...
140

16035364   Benjamin Renard   First commit
141
142
        $this->addLog($msg);
  	   }
10200969   Roipoussiere   Remove whitespace...
143

16035364   Benjamin Renard   First commit
144
145
  	   libxml_use_internal_errors(false);
  	 }
10200969   Roipoussiere   Remove whitespace...
146

16035364   Benjamin Renard   First commit
147
148
    return $result;
  }
10200969   Roipoussiere   Remove whitespace...
149

16035364   Benjamin Renard   First commit
150
151
152
153
  protected function queryResource()
  {
  	 return "//x:RESOURCE";
  }
10200969   Roipoussiere   Remove whitespace...
154

30cd92df   Roipoussiere   Fix merge conflicts
155
	protected function queryResourceInfo() {
5de62950   Nathanael Jourdane   Improve the VOTab...
156
157
158
		return $this->queryResource()."/x:INFO";
	}

16035364   Benjamin Renard   First commit
159
160
161
162
  protected function queryTable()
  {
  	 return $this->queryResource()."/x:TABLE";
  }
10200969   Roipoussiere   Remove whitespace...
163

16035364   Benjamin Renard   First commit
164
165
166
167
  protected function queryDescription()
  {
  	 return $this->queryTable()."/x:DESCRIPTION";
  }
10200969   Roipoussiere   Remove whitespace...
168

16035364   Benjamin Renard   First commit
169
170
171
172
  protected function queryFields()
  {
  	 return $this->queryTable()."/x:FIELD";
  }
10200969   Roipoussiere   Remove whitespace...
173

16035364   Benjamin Renard   First commit
174
175
176
177
178
179
180
181
182
183
184
185
186
  protected function queryField($field_id)
  {
  	 return $this->queryFields()."[@ID='".$field_id."']";
  }

  protected function queryFieldByName($field_id)
  {
  	 return $this->queryFields()."[@name='".$field_id."']";
  }
  protected function queryFieldDescription($field_id)
  {
  	 return $this->queryField($field_id)."/x:DESCRIPTION";
  }
10200969   Roipoussiere   Remove whitespace...
187

16035364   Benjamin Renard   First commit
188
189
190
191
  protected function queryData()
  {
  	 return $this->queryTable()."/x:DATA";
  }
10200969   Roipoussiere   Remove whitespace...
192

16035364   Benjamin Renard   First commit
193
194
195
196
  protected function queryTableData()
  {
  	 return $this->queryData()."/x:TABLEDATA";
  }
10200969   Roipoussiere   Remove whitespace...
197

16035364   Benjamin Renard   First commit
198
199
200
201
  protected function queryTR()
  {
  	 return $this->queryTableData()."/x:TR";
  }
10200969   Roipoussiere   Remove whitespace...
202

30cd92df   Roipoussiere   Fix merge conflicts
203
204
	protected function queryBinaryData() {
		return $this->queryData()."/x:BINARY";
5de62950   Nathanael Jourdane   Improve the VOTab...
205
206
	}

30cd92df   Roipoussiere   Fix merge conflicts
207
208
	protected function queryStream() {
		return $this->queryBinaryData()."/x:STREAM";
5de62950   Nathanael Jourdane   Improve the VOTab...
209
	}
16035364   Benjamin Renard   First commit
210
  //
10200969   Roipoussiere   Remove whitespace...
211

16035364   Benjamin Renard   First commit
212
213
214
215
216
  public function getVersion()
  {
  	 if (!$this->xml)
  	 		return '';
  	 $root = $this->xml->documentElement;
10200969   Roipoussiere   Remove whitespace...
217

16035364   Benjamin Renard   First commit
218
219
  	 return $root->getAttribute('version');
  }
10200969   Roipoussiere   Remove whitespace...
220

16035364   Benjamin Renard   First commit
221
222
223
224
  public function getDescription()
  {
  	 if (!$this->xp)
  	   return '';
10200969   Roipoussiere   Remove whitespace...
225

16035364   Benjamin Renard   First commit
226
  	 $desc = $this->xp->query($this->queryDescription());
10200969   Roipoussiere   Remove whitespace...
227

16035364   Benjamin Renard   First commit
228
229
  	 if ($desc->length < 1)
  	   return '';
10200969   Roipoussiere   Remove whitespace...
230

16035364   Benjamin Renard   First commit
231
232
  	 return $desc->item(0)->nodeValue;
  }
10200969   Roipoussiere   Remove whitespace...
233

bf74fc2d   Elena.Budnik   IMPEX
234
235
236
237
  public function isData()
  {
    $trs =  $this->xml->getElementsByTagName('TR');
    if ($trs->length > 0) return true;
10200969   Roipoussiere   Remove whitespace...
238

bf74fc2d   Elena.Budnik   IMPEX
239
240
    return false;
  }
10200969   Roipoussiere   Remove whitespace...
241

16035364   Benjamin Renard   First commit
242
243
  public function getFirstTR()
  {
f60f0bd9   Benjamin Renard   Fix upload from s...
244
  	 if (!isset($this->xp))
16035364   Benjamin Renard   First commit
245
  	   return NULL;
10200969   Roipoussiere   Remove whitespace...
246

16035364   Benjamin Renard   First commit
247
  	 $tabledatas = $this->xp->query($this->queryTableData());
10200969   Roipoussiere   Remove whitespace...
248

16035364   Benjamin Renard   First commit
249
250
  	 if ($tabledatas->length < 1)
  	   return NULL;
10200969   Roipoussiere   Remove whitespace...
251

16035364   Benjamin Renard   First commit
252
  	 $tabledata = $tabledatas->item(0);
10200969   Roipoussiere   Remove whitespace...
253

16035364   Benjamin Renard   First commit
254
  	 $node = $tabledata->firstChild;
f60f0bd9   Benjamin Renard   Fix upload from s...
255
256
	 if (!isset($node))
		return NULL;
10200969   Roipoussiere   Remove whitespace...
257

f60f0bd9   Benjamin Renard   Fix upload from s...
258
259
	 if (($node->nodeType != XML_ELEMENT_NODE) || ($node->nodeName != "TR"))
		return $this->getNextTR($node);
10200969   Roipoussiere   Remove whitespace...
260

f60f0bd9   Benjamin Renard   Fix upload from s...
261
    	return $node;
16035364   Benjamin Renard   First commit
262
  }
10200969   Roipoussiere   Remove whitespace...
263

16035364   Benjamin Renard   First commit
264
265
  public function getNextTR($tr)
  {
f60f0bd9   Benjamin Renard   Fix upload from s...
266
  	 if (!isset($this->xp) || !isset($tr) || !isset($tr->nextSibling))
16035364   Benjamin Renard   First commit
267
  	   return NULL;
10200969   Roipoussiere   Remove whitespace...
268

f60f0bd9   Benjamin Renard   Fix upload from s...
269
270
271
	if (($tr->nextSibling->nodeType != XML_ELEMENT_NODE) || ($tr->nextSibling->nodeName != "TR"))
		return $this->getNextTR($tr->nextSibling);
	return $tr->nextSibling;
16035364   Benjamin Renard   First commit
272
  }
10200969   Roipoussiere   Remove whitespace...
273

16035364   Benjamin Renard   First commit
274
275
276
277
  public function getTDValueByFieldIndex($tr,$field_index)
  {
  	 if (!$this->xp)
  	   return NULL;
10200969   Roipoussiere   Remove whitespace...
278

16035364   Benjamin Renard   First commit
279
  	 $tds = $tr->getElementsByTagName("TD");
10200969   Roipoussiere   Remove whitespace...
280

16035364   Benjamin Renard   First commit
281
282
  	 if (($tds->length < 1) || ($field_index >= $tds->length))
  	   return NULL;
10200969   Roipoussiere   Remove whitespace...
283

16035364   Benjamin Renard   First commit
284
285
  	 return $tds->item($field_index)->nodeValue;
  }
10200969   Roipoussiere   Remove whitespace...
286

16035364   Benjamin Renard   First commit
287
288
289
290
  protected function isTimeField($field)
  {
    if (!$this->xp)
  	   return FALSE;
10200969   Roipoussiere   Remove whitespace...
291

6de48c3d   Benjamin Renard   Implement data up...
292
293
  	 return (($field->getAttribute("ucd") == "time.epoch") && ($field->getAttribute("xtype") == "dateTime") ||
		 ($field->getAttribute("ucd") == "TIME") && ($field->getAttribute("unit") == "iso-8601"));
16035364   Benjamin Renard   First commit
294
  }
10200969   Roipoussiere   Remove whitespace...
295

16035364   Benjamin Renard   First commit
296
297
298
299
  public function getTimeFieldIndex()
  {
  	 if (!$this->xp)
  	   return -1;
10200969   Roipoussiere   Remove whitespace...
300

16035364   Benjamin Renard   First commit
301
  	 $fields = $this->xp->query($this->queryFields());
10200969   Roipoussiere   Remove whitespace...
302

16035364   Benjamin Renard   First commit
303
304
  	 if ($fields->length < 1)
  	   return -1;
10200969   Roipoussiere   Remove whitespace...
305

16035364   Benjamin Renard   First commit
306
307
308
  	 for ($i = 0; $i < $fields->length; $i++)
  	   if ($this->isTimeField($fields->item($i)))
  	     return $i;
10200969   Roipoussiere   Remove whitespace...
309

16035364   Benjamin Renard   First commit
310
311
  	 return -1;
  }
10200969   Roipoussiere   Remove whitespace...
312

bf74fc2d   Elena.Budnik   IMPEX
313
314
315
316
	protected function getFieldByID($field_id)
	{
		if (!$this->xp)
			return NULL;
16035364   Benjamin Renard   First commit
317

bf74fc2d   Elena.Budnik   IMPEX
318
		$fields = $this->xp->query($this->queryFields());
10200969   Roipoussiere   Remove whitespace...
319

bf74fc2d   Elena.Budnik   IMPEX
320
321
		if ($fields->length < 1)
			return NULL;
10200969   Roipoussiere   Remove whitespace...
322

bf74fc2d   Elena.Budnik   IMPEX
323
324
325
		foreach ($fields as $field)
			if ($field->getAttribute("ID") == $field_id)
				return $field;
10200969   Roipoussiere   Remove whitespace...
326

bf74fc2d   Elena.Budnik   IMPEX
327
328
		return NULL;
	}
16035364   Benjamin Renard   First commit
329

bf74fc2d   Elena.Budnik   IMPEX
330
331
332
333
	protected function getFieldByName($field_id)
	{
		if (!$this->xp)
			return NULL;
10200969   Roipoussiere   Remove whitespace...
334

bf74fc2d   Elena.Budnik   IMPEX
335
		$fields = $this->xp->query($this->queryFieldByName($field_id));
10200969   Roipoussiere   Remove whitespace...
336

bf74fc2d   Elena.Budnik   IMPEX
337
338
		if ($fields->length < 1)
			return NULL;
10200969   Roipoussiere   Remove whitespace...
339

bf74fc2d   Elena.Budnik   IMPEX
340
341
342
		foreach ($fields as $field)
			if ($field->getAttribute("name") == $field_id)
			return $field;
10200969   Roipoussiere   Remove whitespace...
343

bf74fc2d   Elena.Budnik   IMPEX
344
		return NULL;
16035364   Benjamin Renard   First commit
345
	}
16035364   Benjamin Renard   First commit
346

bf74fc2d   Elena.Budnik   IMPEX
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
	protected function checkIDAttribute()
	{

		$fields = $this->xml->getElementsByTagName('FIELD');
		$i = 0;
		foreach ($fields as $field)
		{
			$i++;
			if (!$field->hasAttribute("ID"))
			{
				$field->setAttribute("ID", "col".$i);
			}
		}
		$this->xml->saveXML();
	}
16035364   Benjamin Renard   First commit
362
363
364
365
366

  public function getFieldIndexByID($field_id)
  {
  	 if (!$this->xp)
  	   return -1;
10200969   Roipoussiere   Remove whitespace...
367

16035364   Benjamin Renard   First commit
368
  	 $fields = $this->xp->query($this->queryFields());
10200969   Roipoussiere   Remove whitespace...
369

16035364   Benjamin Renard   First commit
370
371
  	 if ($fields->length < 1)
  	   return -1;
10200969   Roipoussiere   Remove whitespace...
372

16035364   Benjamin Renard   First commit
373
374
375
  	 for ($i = 0; $i < $fields->length; $i++)
  	   if ($fields->item($i)->getAttribute("ID") == $field_id)
  	     return $i;
10200969   Roipoussiere   Remove whitespace...
376

16035364   Benjamin Renard   First commit
377
378
  	 return -1;
  }
10200969   Roipoussiere   Remove whitespace...
379
380

  public function getStartStop()
16035364   Benjamin Renard   First commit
381
382
383
  {
  	 if (!$this->xp)
  	   return '0 0';
10200969   Roipoussiere   Remove whitespace...
384

16035364   Benjamin Renard   First commit
385
386
387
    $timeIndex = $this->getTimeFieldIndex();
    if ($timeIndex < 0)
      return '0 0';
10200969   Roipoussiere   Remove whitespace...
388

16035364   Benjamin Renard   First commit
389
    $tr = $this->getFirstTR();
10200969   Roipoussiere   Remove whitespace...
390

f60f0bd9   Benjamin Renard   Fix upload from s...
391
    if (!isset($tr))
16035364   Benjamin Renard   First commit
392
      return '0 0';
10200969   Roipoussiere   Remove whitespace...
393

16035364   Benjamin Renard   First commit
394
    $start = $this->getTDValueByFieldIndex($tr,$timeIndex);
10200969   Roipoussiere   Remove whitespace...
395

16035364   Benjamin Renard   First commit
396
    $stop = $start;
f60f0bd9   Benjamin Renard   Fix upload from s...
397
    while (isset($tr))
16035364   Benjamin Renard   First commit
398
399
400
401
    {
      $stop = $this->getTDValueByFieldIndex($tr,$timeIndex);
      $tr = $this->getNextTR($tr);
    }
10200969   Roipoussiere   Remove whitespace...
402

f60f0bd9   Benjamin Renard   Fix upload from s...
403
    if (!isset($start))
16035364   Benjamin Renard   First commit
404
405
406
      $start = 0;
    else
      $start = strtotime($start);
10200969   Roipoussiere   Remove whitespace...
407

f60f0bd9   Benjamin Renard   Fix upload from s...
408
    if (!isset($stop))
16035364   Benjamin Renard   First commit
409
410
411
      $stop = 0;
    else
      $stop = strtotime($stop);
10200969   Roipoussiere   Remove whitespace...
412
413

    return $start." ".$stop;
16035364   Benjamin Renard   First commit
414
  }
10200969   Roipoussiere   Remove whitespace...
415

bf74fc2d   Elena.Budnik   IMPEX
416
417
418
419
	public function getFieldInfoByID($field_id)
	{
		if (!$this->xp)
			return array("id"    => $field_id, "error" => "No file loaded");
10200969   Roipoussiere   Remove whitespace...
420

bf74fc2d   Elena.Budnik   IMPEX
421
		$field = $this->getFieldByID($field_id);
10200969   Roipoussiere   Remove whitespace...
422

bf74fc2d   Elena.Budnik   IMPEX
423
424
		if (!$field)
			$field = $this->getFieldByName($field_id);
16035364   Benjamin Renard   First commit
425

bf74fc2d   Elena.Budnik   IMPEX
426
427
		if (!$field)
			return array("id" => $field_id, "error" => "This field doesn't exist");
10200969   Roipoussiere   Remove whitespace...
428

bf74fc2d   Elena.Budnik   IMPEX
429
430
		return $this->getFieldInfo($field);
	}
10200969   Roipoussiere   Remove whitespace...
431

30cd92df   Roipoussiere   Fix merge conflicts
432
	/** Get the size of a row according to datatype array length. */
e581690d   Nathanael Jourdane   Fix VOtable conve...
433
434
435
436
437
438
439
440
	private function get_row_size($field_node) {
		$datatype = $field_node->getAttribute("datatype");

		if($datatype == 'boolean') {
			return 1;
		}

		switch($datatype) {
5de62950   Nathanael Jourdane   Improve the VOTab...
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
			case 'unsignedByte':
			case 'char':
				$block_size = 1;
				break;
			case 'unicodeChar':
			case 'short':
				$block_size = 2;
				break;
			case 'int':
			case 'float':
				$block_size = 4;
				break;
			case 'long':
			case 'double':
			case 'float_complex':
				$block_size = 8;
				break;
			case 'double_complex':
e581690d   Nathanael Jourdane   Fix VOtable conve...
459
				$block_size = 16;
5de62950   Nathanael Jourdane   Improve the VOTab...
460
461
462
463
			default:
				$block_size = 0;
				break;
		}
5de62950   Nathanael Jourdane   Improve the VOTab...
464

5de62950   Nathanael Jourdane   Improve the VOTab...
465
466
467
		if($field_node->getAttribute("arraysize") == NULL) {
			$array_size = $block_size;
		} else if("*" == $field_node->getAttribute("arraysize")) {
5de62950   Nathanael Jourdane   Improve the VOTab...
468
			$array_size = unpack("Ns", substr($this->stream, $this->c, 4))["s"] * $block_size;
5de62950   Nathanael Jourdane   Improve the VOTab...
469
470
471
472
473
474
			$this->c+=4;
		} else {
			$array_size = (int)($field_node->getAttribute("arraysize")) * $block_size;
		}
		return $array_size;
	}
f534c4a8   Nathanael Jourdane   Make the VOTable ...
475
476

	/** Get the VOTable stream content.*/
5de62950   Nathanael Jourdane   Improve the VOTab...
477
	public function parseStream() {
b97c59e9   Nathanael Jourdane   Provide to the us...
478
		if (! $this->isValidSchema()) {
8d5016bc   Nathanael Jourdane   bugFix: do not us...
479
			error_log('There is an error on the VOTable: ' . $this->votable_error);
b97c59e9   Nathanael Jourdane   Provide to the us...
480
			return null;
b97c59e9   Nathanael Jourdane   Provide to the us...
481
		}
5de62950   Nathanael Jourdane   Improve the VOTab...
482
483
		$data = Array();
		$fields = $this->xp->query($this->queryFields());
8d5016bc   Nathanael Jourdane   bugFix: do not us...
484
		$resource = $this->xp->query($this->queryResource());
5de62950   Nathanael Jourdane   Improve the VOTab...
485
486
487
488
489
		$nb_columns = $fields->length;
		$row = Array();
		$n_value = 0; // index of current value
		$this->c = 0; // initialize cursor position.
		$query_stream = $this->xp->query($this->queryStream())->item(0);
b97c59e9   Nathanael Jourdane   Provide to the us...
490
491
		if($query_stream == NULL) {
			$this->votable_error = "There is no STREAM node in the VOTable file.";
8d5016bc   Nathanael Jourdane   bugFix: do not us...
492
			return null;
b97c59e9   Nathanael Jourdane   Provide to the us...
493
		}
5de62950   Nathanael Jourdane   Improve the VOTab...
494
		$this->stream = base64_decode($query_stream->textContent);
5de62950   Nathanael Jourdane   Improve the VOTab...
495
		$stream_len = strlen($this->stream);
b97c59e9   Nathanael Jourdane   Provide to the us...
496
		if($stream_len == 0) {
58423118   Nathanael Jourdane   Prompt an error m...
497
			$this->votable_error = "no result";
8d5016bc   Nathanael Jourdane   bugFix: do not us...
498
			return null;
b97c59e9   Nathanael Jourdane   Provide to the us...
499
		}
5de62950   Nathanael Jourdane   Improve the VOTab...
500
501
		while($this->c < strlen($this->stream)) {
			$col_id = $n_value % $nb_columns;
57d96667   Nathanael Jourdane   Compatibility wit...
502
			$field_node = $fields->item($col_id);
5de62950   Nathanael Jourdane   Improve the VOTab...
503

5de62950   Nathanael Jourdane   Improve the VOTab...
504
505
506
507
508
509
			if($col_id == 0) {
				$row = Array();
			}
			$row[$field_node->getAttribute("ID")] = $this->process_datablock($field_node);
			if($col_id == $nb_columns-1) {
				array_push($data, $row);
f534c4a8   Nathanael Jourdane   Make the VOTable ...
510
			}
5de62950   Nathanael Jourdane   Improve the VOTab...
511
			$n_value+=1;
f534c4a8   Nathanael Jourdane   Make the VOTable ...
512
		}
5de62950   Nathanael Jourdane   Improve the VOTab...
513
514
		return $data;
	}
f534c4a8   Nathanael Jourdane   Make the VOTable ...
515

e581690d   Nathanael Jourdane   Fix VOtable conve...
516
517
518
519
520
	private function JDTodate($jd) {
		list($month, $day, $year) = split('/', JDToGregorian($jd));
		return "$day/$month/$year";
	}

5de62950   Nathanael Jourdane   Improve the VOTab...
521
522
523
	private function process_datablock($field_node) {
		$data_type = $field_node->getAttribute("datatype");
		$row_size = $this->get_row_size($field_node);
e581690d   Nathanael Jourdane   Fix VOtable conve...
524
525
		$substr = substr($this->stream, $this->c, $row_size);

5de62950   Nathanael Jourdane   Improve the VOTab...
526
527
528
		switch ($data_type) {
			case 'boolean':
			case 'unsignedByte':
e581690d   Nathanael Jourdane   Fix VOtable conve...
529
				$b = $substr;
cdf35aa6   Nathanael Jourdane   Votable parser: c...
530
				$res = $b == 'T' || $b == 't' || $b == '1';
5de62950   Nathanael Jourdane   Improve the VOTab...
531
532
				break;
			case 'char':
cdf35aa6   Nathanael Jourdane   Votable parser: c...
533
				$res = $row_size !=0 ? utf8_encode($substr) : NULL;
5de62950   Nathanael Jourdane   Improve the VOTab...
534
			case 'unicodeChar':
cdf35aa6   Nathanael Jourdane   Votable parser: c...
535
				$res = $row_size !=0 ? utf8_encode(str_replace("\0", '', $substr)) : NULL;
5de62950   Nathanael Jourdane   Improve the VOTab...
536
537
				break;
			case 'short':
cdf35aa6   Nathanael Jourdane   Votable parser: c...
538
539
				$res = unpack('ss', $substr)['s'];
				$res = is_nan($res) ? NULL : $res;
5de62950   Nathanael Jourdane   Improve the VOTab...
540
541
				break;
			case 'int':
cdf35aa6   Nathanael Jourdane   Votable parser: c...
542
543
				$res = unpack('Ns', $substr)['s'];
				$res = is_nan($res) ? NULL : $res;
5de62950   Nathanael Jourdane   Improve the VOTab...
544
545
				break;
			case 'long':
cdf35aa6   Nathanael Jourdane   Votable parser: c...
546
547
				$res = unpack('Js', $substr)['s'];  // /!\ J -> PHP 5.6 only
				$res = is_nan($res) ? NULL : $res;
5de62950   Nathanael Jourdane   Improve the VOTab...
548
549
				break;
			case 'float':
cdf35aa6   Nathanael Jourdane   Votable parser: c...
550
				$res = unpack('fs', $substr)['s'];
e581690d   Nathanael Jourdane   Fix VOtable conve...
551
552
				// If machine is little endian:
				if($this->is_little_endian) {
cdf35aa6   Nathanael Jourdane   Votable parser: c...
553
					$res = unpack('f1f', strrev(pack('f', $res)))['f'];
e581690d   Nathanael Jourdane   Fix VOtable conve...
554
				}
cdf35aa6   Nathanael Jourdane   Votable parser: c...
555
				$res = is_nan($res) ? NULL : $res;
5de62950   Nathanael Jourdane   Improve the VOTab...
556
557
				break;
			case 'double':
cdf35aa6   Nathanael Jourdane   Votable parser: c...
558
				$res = unpack('ds', $substr)['s'];
e581690d   Nathanael Jourdane   Fix VOtable conve...
559
560
				// If machine is little endian:
				if($this->is_little_endian) {
cdf35aa6   Nathanael Jourdane   Votable parser: c...
561
					$res = unpack('d1d', strrev(pack('d', $res)))['d'];
e581690d   Nathanael Jourdane   Fix VOtable conve...
562
				}
cdf35aa6   Nathanael Jourdane   Votable parser: c...
563
				$res = is_nan($res) ? NULL : $res;
5de62950   Nathanael Jourdane   Improve the VOTab...
564
565
566
				break;
			default:
				$res = NULL;
cdf35aa6   Nathanael Jourdane   Votable parser: c...
567
				error_log("Unknown datatype: $data_type");
5de62950   Nathanael Jourdane   Improve the VOTab...
568
569
570
				break;
		}
		$this->c+=$row_size;
cdf35aa6   Nathanael Jourdane   Votable parser: c...
571
		return $res;
5de62950   Nathanael Jourdane   Improve the VOTab...
572
	}
10200969   Roipoussiere   Remove whitespace...
573

bf74fc2d   Elena.Budnik   IMPEX
574
575
576
577
	public function getFieldInfo($field)
	{
		if (!$this->xp)
			return array("id"    => $field_id, "error" => "No file loaded");
10200969   Roipoussiere   Remove whitespace...
578

bf74fc2d   Elena.Budnik   IMPEX
579
580
581
582
		$description = '';
		$desc = $field->getElementsByTagName("DESCRIPTION");
		if ($desc->length >= 1)
			$description = $desc->item(0)->nodeValue;
16035364   Benjamin Renard   First commit
583

bf74fc2d   Elena.Budnik   IMPEX
584
585
586
587
588
		$size = $field->getAttribute("arraysize");
		if ($size == '')
			$size = 1;
		else
			$size = intval($size);
16035364   Benjamin Renard   First commit
589

bf74fc2d   Elena.Budnik   IMPEX
590
591
592
593
594
595
596
597
598
599
600
601
602
		switch ($field->getAttribute("datatype"))
		{
			case "short" :
				$type = "SHORT";
				break;
			case "int" :
				$type = "INTEGER";
				break;
			case "long"   :
			case "double" :
				$type = "DOUBLE";
				break;
			default :
10200969   Roipoussiere   Remove whitespace...
603
				$type = "FLOAT";
bf74fc2d   Elena.Budnik   IMPEX
604
		}
10200969   Roipoussiere   Remove whitespace...
605

bf74fc2d   Elena.Budnik   IMPEX
606
607
		if (!$field->getAttribute("ID"))
			$id = "col".$n;
10200969   Roipoussiere   Remove whitespace...
608
		else
bf74fc2d   Elena.Budnik   IMPEX
609
			$id = $field->getAttribute("ID");
10200969   Roipoussiere   Remove whitespace...
610

bf74fc2d   Elena.Budnik   IMPEX
611
612
613
614
615
616
617
618
619
		return array("id"     => $field->getAttribute("ID"),
						"type"        => $type,
						"name"        => $field->getAttribute("name"),
						"ucd"         => $field->getAttribute("ucd"),
						"unit"        => $field->getAttribute("unit"),
						"size"        => $size,
						"description" => $description
						);
	}
10200969   Roipoussiere   Remove whitespace...
620

16035364   Benjamin Renard   First commit
621
622
623
624
  public function getFieldsInfo()
  {
   	 if (!$this->xp)
  	   return array("error" => "No file loaded");
10200969   Roipoussiere   Remove whitespace...
625

16035364   Benjamin Renard   First commit
626
    $fields_info = array();
10200969   Roipoussiere   Remove whitespace...
627

16035364   Benjamin Renard   First commit
628
  	 $fields = $this->xp->query($this->queryFields());
10200969   Roipoussiere   Remove whitespace...
629

16035364   Benjamin Renard   First commit
630
631
  	 if ($fields->length < 1)
  	   return $fields_info;
10200969   Roipoussiere   Remove whitespace...
632

16035364   Benjamin Renard   First commit
633
634
635
636
    foreach ($fields as $field)
    {
     	if ($this->isTimeField($field))
        continue;
10200969   Roipoussiere   Remove whitespace...
637

16035364   Benjamin Renard   First commit
638
639
      array_push($fields_info,$this->getFieldInfo($field));
    }
10200969   Roipoussiere   Remove whitespace...
640

16035364   Benjamin Renard   First commit
641
642
    return $fields_info;
  }
10200969   Roipoussiere   Remove whitespace...
643
644

  public function getSamplings()
16035364   Benjamin Renard   First commit
645
646
647
648
  {
  	 if (!$this->xp)
  	   return array("minSampling" => 0,
                   "maxSampling" => 0);
10200969   Roipoussiere   Remove whitespace...
649

16035364   Benjamin Renard   First commit
650
651
652
653
  	 $timeIndex = $this->getTimeFieldIndex();
    if ($timeIndex < 0)
      return array("minSampling" => 0,
                   "maxSampling" => 0);
10200969   Roipoussiere   Remove whitespace...
654

16035364   Benjamin Renard   First commit
655
656
657
658
659
660
661
    $tr = $this->getFirstTR();

    if (!$tr)
      return array("minSampling" => 0,
                   "maxSampling" => 0);

    $prevTime = 0;
f60f0bd9   Benjamin Renard   Fix upload from s...
662
    while (isset($tr))
16035364   Benjamin Renard   First commit
663
664
    {
      $time = $this->getTDValueByFieldIndex($tr,$timeIndex);
10200969   Roipoussiere   Remove whitespace...
665

f60f0bd9   Benjamin Renard   Fix upload from s...
666
      if (isset($time))
16035364   Benjamin Renard   First commit
667
668
669
670
671
672
      {
        $time = strtotime($time);
        if (($prevTime > 0) && ($time-$prevTime > 0))
          $deltaT[$time-$prevTime]++;
        $prevTime = $time;
      }
10200969   Roipoussiere   Remove whitespace...
673

16035364   Benjamin Renard   First commit
674
675
      $tr = $this->getNextTR($tr);
    }
10200969   Roipoussiere   Remove whitespace...
676

16035364   Benjamin Renard   First commit
677
678
    $minSampling = +1.e31;
    $maxSampling = 0.0;
10200969   Roipoussiere   Remove whitespace...
679
680

    foreach ($deltaT as $key => $value)
16035364   Benjamin Renard   First commit
681
    {
10200969   Roipoussiere   Remove whitespace...
682

16035364   Benjamin Renard   First commit
683
684
     if ($value/count($deltaT) < 0.10)
        continue;
10200969   Roipoussiere   Remove whitespace...
685

16035364   Benjamin Renard   First commit
686
687
688
      if ($key < $minSampling) $minSampling = $key;
      if ($key > $maxSampling) $maxSampling = $key;
    }
10200969   Roipoussiere   Remove whitespace...
689

16035364   Benjamin Renard   First commit
690
691
692
    return array("minSampling" => $minSampling,
                 "maxSampling" => $maxSampling);
  }
10200969   Roipoussiere   Remove whitespace...
693

bf74fc2d   Elena.Budnik   IMPEX
694
695
696
697
698
699
  /*
	* Add vector data made from components to IMPEX VOT
	*/
	public function addVectorToVot($paramID, $fileName)
	{
		$argsArr = explode(',', $paramID);
10200969   Roipoussiere   Remove whitespace...
700

bf74fc2d   Elena.Budnik   IMPEX
701
702
703
		$fields = $this->xml->getElementsByTagName('FIELD');
		$table = $this->xml->getElementsByTagName('TABLE')->item(0);
		$data = $this->xml->getElementsByTagName('DATA')->item(0);
10200969   Roipoussiere   Remove whitespace...
704

bf74fc2d   Elena.Budnik   IMPEX
705
		$i=0;
10200969   Roipoussiere   Remove whitespace...
706
		$find = false;
bf74fc2d   Elena.Budnik   IMPEX
707
		foreach ($fields as $field)
10200969   Roipoussiere   Remove whitespace...
708
		{
bf74fc2d   Elena.Budnik   IMPEX
709
			if ($field->getAttribute('name') == $argsArr[0])
10200969   Roipoussiere   Remove whitespace...
710
			{
bf74fc2d   Elena.Budnik   IMPEX
711
712
713
714
715
716
717
				$unit = $field->getAttribute('unit');
				$ucd  = $field->getAttribute('ucd');
				$datatype  = $field->getAttribute('datatype');
				$firstTD = $i;
				$find = true;
				break;
			}
10200969   Roipoussiere   Remove whitespace...
718
			$i++;
bf74fc2d   Elena.Budnik   IMPEX
719
		}
16035364   Benjamin Renard   First commit
720

bf74fc2d   Elena.Budnik   IMPEX
721
		if ($find)
10200969   Roipoussiere   Remove whitespace...
722
		{
bf74fc2d   Elena.Budnik   IMPEX
723
724
725
726
727
728
			$new_field = $this->xml->createElement('FIELD');
			$new_field->setAttribute('ID', $paramID);
			$new_field->setAttribute('name', $paramID);
			$new_field->setAttribute('datatype', $datatype);
			$new_field->setAttribute('arraysize', '3');
			$new_field->setAttribute('unit', $unit);
10200969   Roipoussiere   Remove whitespace...
729
730
			$new_field->setAttribute('ucd', $ucd);
			$colN = $fields->length + 1;
bf74fc2d   Elena.Budnik   IMPEX
731
			$new_field->setAttribute('ID', 'col'.$colN);
10200969   Roipoussiere   Remove whitespace...
732

bf74fc2d   Elena.Budnik   IMPEX
733
			$table->insertBefore($new_field,$data);
10200969   Roipoussiere   Remove whitespace...
734

bf74fc2d   Elena.Budnik   IMPEX
735
736
737
738
739
740
741
742
			$trs = $this->xml->getElementsByTagName('TR');
			foreach($trs as $tr)
			{
				$tds = $tr->getElementsByTagName('TD');
				$value = trim($tds->item($firstTD)->nodeValue).' '.trim($tds->item($firstTD + 1)->nodeValue).' '.trim($tds->item($firstTD + 2)->nodeValue);
				$td = $this->xml->createElement('TD', $value);
				$tr->appendChild($td);
			}
10200969   Roipoussiere   Remove whitespace...
743
744

			$this->xml->save($fileName);
bf74fc2d   Elena.Budnik   IMPEX
745
		}
16035364   Benjamin Renard   First commit
746
	}
16035364   Benjamin Renard   First commit
747
}
10200969   Roipoussiere   Remove whitespace...
748
?>