Squiz Matrix  4.12.2
 All Data Structures Namespaces Functions Variables Pages
soap_common.inc
1 <?php
18 require_once SQ_FUDGE_PATH.'/general/text.inc';
19 require_once 'soap_form_based_common.inc';
20 
21 
22 // WSDL sometime defines a complex type in a loop, we need to get out of this loop if it repeats too many times while parsing
23 define('MAX_COMPLEX_TYPE_PASRSE_LOOP', 3);
24 
37 {
38 
39 
40  private static $recent_parsed_type = Array();
41 
42 
49  public static function _store_results($object, $prefix = 'soap_', &$soap_response_keywords=Array(), $file_keywords)
50  {
51  if (empty($object)) return;
52 
53  $vars = is_object($object) ? get_object_vars($object) : $object;
54  if (empty($vars)) return;
55 
56  foreach ($vars as $index => $value) {
57  if (is_object($value) || is_array($value)) {
58  self::_store_results ($value, $prefix.$index, $soap_response_keywords, $file_keywords);
59  } else {
60  // if the keyword we are trying to save is file
61  // response and is configured to be saved
62  // and to provide a link to the file
63  // then deal with it
64  if (in_array('%globals_session_'.$prefix.$index.'%', $file_keywords)) {
65  $link_value = self::_save_file($value);
66  $_SESSION[SQ_SESSION_SANDBOX_INDEX][$prefix.$index] = $link_value;
67  $soap_response_keywords[$prefix.$index] = $link_value;
68  } else {
69  $_SESSION[SQ_SESSION_SANDBOX_INDEX][$prefix.$index] = $value;
70  $soap_response_keywords[$prefix.$index] = $value;
71  }
72  }
73  }
74 
75  }//end _store_results()
76 
77 
84  public static function _parse_type($type, $types)
85  {
86  $type_name = preg_replace('/ .*/', '', $type);
87  //$param_name = preg_replace('/.* (.*);/', '$1', $param);
88  $sub_types = self::_is_complex_type($type_name, $types);
89 
90  // If simple type arguments
91  if (!$sub_types) {
92  return self::_is_array_type($type_name, $types);
93  }//end if
94 
95  // reset infinity loop check counter
96  self::$recent_parsed_type = Array();
97 
98  // It's a complext type, let's parse it recursively
99  $node = new SimpleXMLElement('<'.$type_name.'/>');
100  self::_parse_type_recursive($type, $types, $node);
101 
102  return $node;
103 
104  }//end _parse_type()
105 
112  private static function _is_array_type($param, $types)
113  {
114  // Get array types
115  $array_types = Array();
116  foreach($types as $type) {
117  if (substr($type, -2) == '[]') {
118  $array_type = explode(' ', $type);
119  if (count($array_type) > 1) {
120  $array_types[rtrim($array_type[1], '[]')] = $array_type[0];
121  }
122  }
123  }
124 
125  return isset($array_types[$param]);
126 
127  }//end _is_array_type()
128 
129 
136  public static function _parse_type_recursive($param, $types, &$node)
137  {
138  // Keep recently parsed type, to do an infinity check
139  foreach (self::$recent_parsed_type as $parsed) {
140  if ($parsed == $param) return;
141  }
142  array_push(self::$recent_parsed_type, $param);
143  if(count(self::$recent_parsed_type) > MAX_COMPLEX_TYPE_PASRSE_LOOP) {
144  array_shift(self::$recent_parsed_type);
145  }
146 
147  $param_type = preg_replace('/ .*/', '', $param);
148  $param_name = preg_replace('/.* (.*);/', '$1', $param);
149 
150  $is_param_array = FALSE;
151  $sub_types = self::_is_complex_type($param_type, $types);
152  if(!$sub_types) return;
153 
154  // It's a complext type, let's parse its children
155  foreach ($sub_types as $type) {
156  $is_type_array = FALSE;
157  $sub_type_type = preg_replace('/ .*/', '', $type);
158  $sub_type_name = preg_replace('/.* (.*);/', '$1', $type);
159  $sub_sub_types = self::_is_complex_type($sub_type_type, $types, $is_type_array);
160 
161  if (!$sub_sub_types || ($sub_type_type == $param_type)) {
162  // it's a simple type
163  $node->addChild($sub_type_name, '??');
164  } else {
165  // it's complex type, so step into its children
166  $new_node = $node->addChild($sub_type_name.($is_type_array ? '[ARRAY_ELEMENT]' : ''));
167  self::_parse_type_recursive($type, $types, $new_node);
168  }
169  }
170 
171  }//end _parse_type_recursive()
172 
173 
180  public static function _is_complex_type($param, $types, &$is_array=FALSE)
181  {
182  // Get array types
183  $array_types = Array();
184  foreach($types as $type) {
185  if (substr($type, -2) == '[]') {
186  $array_type = explode(' ', $type);
187  if (count($array_type) > 1) {
188  $array_types[rtrim($array_type[1], '[]')] = $array_type[0];
189  }
190  }
191  }
192  if (isset($array_types[$param])) {
193  $param = $array_types[$param];
194  $is_array = TRUE;
195  }
196 
197  foreach ($types as $type) {
198  if (preg_match ('/struct '.$param.'\s*{/', $type)) {
199  // find and return sub types
200  preg_match_all ('/\w+ \w+;/', $type, $matches);
201  return $matches[0];
202  }
203  }
204 
205  return FALSE;
206 
207  }//end is_complex_type()
208 
209 
216  public static function _formatXmlString($xml)
217  {
218  // add marker linefeeds to aid the pretty-tokeniser (adds a linefeed between all tag-end boundaries)
219  $xml = preg_replace('/(>)(<)(\/*)/', "$1\n$2$3", $xml);
220 
221  // now indent the tags
222  $token = strtok($xml, "\n");
223  $result = ''; // holds formatted version as it is built
224  $pad = 0; // initial indent
225  $matches = array(); // returns from preg_matches()
226 
227  // scan each line and adjust indent based on opening/closing tags
228  while ($token !== false) :
229 
230  // test for the various tag states
231 
232  // 1. open and closing tags on same line - no change
233  if (preg_match('/.+<\/\w[^>]*>$/', $token, $matches)) :
234  $indent=0;
235  // 2. closing tag - outdent now
236  elseif (preg_match('/^<\/\w/', $token, $matches)) :
237  $pad--;
238  // 3. opening tag - don't pad this one, only subsequent tags
239  elseif (preg_match('/^<\w[^>]*[^\/]>.*$/', $token, $matches)) :
240  $indent=1;
241  // 4. no indentation needed
242  else :
243  $indent = 0;
244  endif;
245 
246  // pad the line with the required number of leading spaces
247  $line = str_pad($token, strlen($token)+$pad, ' ', STR_PAD_LEFT);
248  $result .= $line . "\n"; // add to the cumulative result, with linefeed
249  $token = strtok("\n"); // get the next token
250  $pad += $indent; // update the pad size for subsequent lines
251  endwhile;
252 
253  return $result;
254 
255  }// end _formatXmlString()
256 
257 
264  public static function _parse_response_keywords (&$response_xml, $prefix = '')
265  {
266  if (!is_object($response_xml)) return '';
267 
268  $data = get_object_vars($response_xml);
269  $keywords_list = '';
270 
271  foreach ($data as $index => $sub_object) {
272  if(is_object($sub_object) && !empty($sub_object)) {
273  $keywords_list .= self::_parse_response_keywords($sub_object, $prefix.$index);
274  } else {
275  $keywords_list .= '%'.$prefix.$index.'%<br/>';
276  }
277  }
278 
279  return $keywords_list;
280 
281  }//end _parse_response_keywords
282 
283 
293  public static function _getSoapOptions($settings, $form=NULL)
294  {
295  // Work out HTTP auth
296  if (isset($settings['login']) && isset($settings['password'])) {
297  $options['login'] = $settings['login'];
298  $options['password'] = $settings['password'];
299  }
300 
301  // Work out HTTPS certificate and passphrase
302  if(!empty($settings['local_cert'])) {
303  $file = $GLOBALS['SQ_SYSTEM']->am->getAsset($settings['local_cert']);
304  if(empty($file) || !method_exists($file, 'getExistingFile')) {
305  if (!is_null($form)) $form->submission_errors = array_merge($form->submission_errors, Array(translate('no_cert')));
306  return FALSE;
307  }
308  $file_info = $file->getExistingFile();
309  $options['local_cert'] = $file_info['path'];
310  }
311 
312  if(isset($settings['passphrase'])) {
313  $options['passphrase'] = $settings['passphrase'];
314  }
315 
316  if ($settings['run_test']) {
317  $options['trace'] = 1;
318  }
319 
320  if ($settings['mute_exceptions']) {
321  $options['exceptions'] = 0;
322  }
323 
324  $options['cache_wsdl'] = WSDL_CACHE_NONE;
325 
326  return $options;
327 
328  }//end _getSoapOptions()
329 
330 
337  public static function testSoapRequest($client, $settings, $function, $form=NULL)
338  {
339  // Work out the parameters of that soap function
340  for($i = 0, $param = Array(); $i < count($settings['actions'][$settings['action']]); $i++) {
341  if(isset($settings[$settings['action'].'parameters'.$i])) {
342 
343  $soap_message = $settings[$settings['action'].'parameters'.$i];
344  $object = @simplexml_load_string($soap_message);
345  if (is_null($form)) {
346  // Convert XML to array, replace file content keywords, xml is not friendly for binary data
347  $object = self::toArray($object);
348  } else {
349  $object = SOAP_Form_Based_Common::toArray($object, $form);
350  }
351 
352  $param[] = $object;
353  }
354  }
355 
356  // Get an array of parameters
357  $eval_string = '';
358  foreach ($param as $index => $object) {
359  $eval_string .= $index == 0 ? '' : ', ';
360  $eval_string .= '$param['.$index.']';
361  }
362 
363  // Make SOAP call
364  try {
365  eval('$data = $client->$function('.$eval_string.');');
366  $soap_request = $client->__getLastRequest();
367  $soap_response = $client->__getLastResponse();
368 
369  }
370  catch (Exception $e) {
371  trigger_error($e->getMessage());
372  return FALSE;
373  }
374 
375  return Array('request' => $soap_request, 'response' => $soap_response);
376 
377  }//end testSoapRequest()
378 
379 
391  public static function _save_file($content)
392  {
393  // get a random file name
394  $file_name = random_password(10, TRUE, TRUE);
395  $sessionid = session_id();
396 
397  if (!is_dir(SQ_DATA_PATH.'/private/soap_action_file_responses/'.$sessionid)) mkdir(SQ_DATA_PATH.'/private/soap_action_file_responses/'.$sessionid, 0777, TRUE);
398 
399  file_put_contents(SQ_DATA_PATH.'/private/soap_action_file_responses/'.$sessionid.'/'.$file_name, $content);
400 
401  // generate url for file and throw it back to be used in the
402  // the keywords replacement array
403  $file_url = './?SQ_ACTION=get_soap_downloaded_file&soap_filename='.$file_name;
404 
405  return $file_url;
406 
407  }//end _save_file()
408 
409 
417  public static function toArray($data)
418  {
419  if (is_object($data)) $data = get_object_vars($data);
420 
421  // Don't play with empty object
422  if(empty($data)) return '';
423 
424  if(is_array($data)) {
425  $result = Array();
426  foreach ($data as $index => $element) {
427  $result[$index] = self::toArray($element);
428  }
429  return $result;
430  } else {
431  return $data;
432  }
433 
434  }//end toArray
435 
436 
437 
438 }//end class
439 
440 ?>