<?php
// Implementation of hook_help()
function xmlrpc_helper_help($section) {
  switch ($section) {
    case 'admin/modules#description':
      $output = t('xmlrpc helper that displays methods and method signatures.');
      break;
  }
  return $output;
}

// Implemention of hook_menu()
function xmlrpc_helper_menu($may_cache) {
  if ($may_cache) {
    $items[] = array(
      'path' => 'xmlrpc_helper',
      'title' => t('XML-RPC Helper'),
      'callback' => 'xmlrpc_helper_page',
      'access' => user_access('administer site configuration'),
      'type' => MENU_NORMAL_ITEM
    );
  }else{
    $items[] = array(
      'path' => 'xmlrpc_helper/'.arg(1),
      'title' => arg(1),
      'callback' => 'xmlrpc_helper_method',
      'access' => user_access('administer site configuration'),
      'type' => MENU_CALLBACK
    );
  }    
  return $items;
}

function xmlrpc_helper_page(){
  $url = 'http://'.$_SERVER['HTTP_HOST'].'/xmlrpc.php';  
  foreach(xmlrpc_helper_get_methods() as $method){
    $list[] = theme('xmlrpc_helper_method',$method);
  }
  $specs = xmlrpc($url,'system.getCapabilities');
  return theme('xmlrpc_helper_capabilities',$specs).theme('item_list',$list,'Methods');
}

function xmlrpc_helper_method(){
  $form = xmlrpc_helper_method_form();
  return drupal_get_form('xmlrpc_helper_method_form', $form);
}  
function xmlrpc_helper_method_form(){
  $methods = xmlrpc_helper_get_methods();
  $method = $methods[arg(1)];
  
  $form['method'] = array(
    '#type' => 'value',
    '#value' => $method,
  );
  $form['description'] = array(
    '#value'=> '<p>'.$method['description'].'</p>',
    '#weight'=>-10,
  );
  $form['params'] = array(
    '#tree' => true,
    '#weight' => 0,
  );
  foreach($method['params'] as $type){
    $form['params'][] = array(
      '#title' => $type,
      '#type' => 'textfield',
    );
  }
  $form['submit'] = array(
    '#type' => 'button', 
    '#value' => t('Submit'),
    '#weight' => 20,
  );
  $form['result'] = array(
    '#type' => 'markup',
    '#value' => '',
    '#weight' => 21,
  );
  $form['flashcode'] = array(
    '#type' => 'markup',
    '#value'=>'',
    '#weight'=>22,
  );
  
  $form['#after_build'] = array(
    'xmlrpc_helper_method_call',
  );
  return $form;
}

function xmlrpc_helper_method_call($form,$form_values){
  $op = $_POST['op'];
  if ($op == t('Submit')) {
    $url = 'http://'.$_SERVER['HTTP_HOST'].'/xmlrpc.php';  
    $method = $form_values['method'];
    $params = $form_values['params'];
    if(empty($params)){
      $data = xmlrpc($url,$method['name']);
    }else{
      array_unshift($params,$url,$method['name']);
      $data = call_user_func_array('xmlrpc',$params);
    }  
    $form['result']['#type'] = 'textarea';
    $form['result']['#type'] = 'fieldset';
    $form['result']['#collapsible'] = true;
    $form['result']['#collapsed'] = true;
    $form['result']['#title'] = 'Result ('.$method['return'].')';
    $form['result']['#value'] = '<pre>'.htmlspecialchars(print_r($data,true)).'</pre>';
    
    $form['flashcode']['#type'] = 'textarea';
    $form['flashcode']['#type'] = 'fieldset';
    $form['flashcode']['#collapsible'] = true;
    $form['flashcode']['#collapsed'] = true;
    $form['flashcode']['#title'] = 'xmlrpcflash code sample';
    $form['flashcode']['#value'] = '<pre>'.htmlspecialchars(xmlrpc_helper_flash_code($method,$url,$data)).'</pre>';

  }
  return $form;
}

function xmlrpc_helper_get_methods(){
  static $methods = false;
  if($methods){
    return $methods;
  }
  $methods = array();
  $url = 'http://'.$_SERVER['HTTP_HOST'].'/xmlrpc.php';  
  $methodnames = xmlrpc($url,'system.listMethods');
  if(!$methodnames){
    return array();
  }
  foreach($methodnames as $method){
    $sig = xmlrpc($url,'system.methodSignature',$method);
    $methods[$method]['name'] = $method;
    $methods[$method]['description'] = xmlrpc($url,'system.methodHelp',$method);
    if(is_array($sig)){
      $methods[$method]['return'] = array_shift($sig);
      $methods[$method]['params'] = $sig;
    }else{
      $methods[$method]['return'] = '';
      $methods[$method]['params'] = array();
    }
  }
  return $methods;
}
  
function theme_xmlrpc_helper_method($method){
  $output = '<em>'.$method['return'].'</em> '
          . '<strong>'.l($method['name'],'xmlrpc_helper/'.$method['name']).'</strong>'
          . '(<em>' . join($method['params'],', ') . '</em>)<br />'
          . $method['description'];
  return $output;
}

function theme_xmlrpc_helper_capabilities($specs){
  foreach($specs as $name=>$spec){
    $list[] = l($name,$spec['specUrl']).' (Version: '.$spec['specVersion'].')';
  }
  return theme('item_list',$list,'Server Capabilities ('.$_SERVER['HTTP_HOST'].')');
}

function xmlrpc_helper_flash_code($method,$url,$data=null){
  $output = "import com.mattism.http.xmlrpc.Connection;\n"
          . "import com.mattism.http.xmlrpc.ConnectionImpl;\n\n";
  switch(strtolower($method['return'])){
    case 'array':
      $output .= "onLoadFunction = function (r:Array) {\n"
              .  "  for (var i = 0; i<r.length; i++) {\n"
              .  "    trace(r[i]);\n"
              .  "  }\n"
              .  "}\n";
      break;
    case 'struct':
      $output .= "onLoadFunction = function (r:Object) {\n"
              .  "  for (var i = 0; i<r.length; i++) {\n"
              .  "    trace(r.property);\n"
              .  "  }\n"
              .  "}\n";
      break;
    case 'string':
      $output .= "onLoadFunction = function (r:String) {\n"
              .  "  trace(r);\n"
              .  "}\n";
      break;
    case 'i4':
    case 'int':
    case 'double':
      $output .= "onLoadFunction = function (r:Number) {\n"
              .  "  trace(r);\n"
              .  "}\n";
      break;
          
  }
  $output .= "var url:String = \"{$url}\";\n"
          .  "var c:Connection = new ConnectionImpl();\n"
          .  "c.setUrl(url);\n"
          .  "c.onLoad = onLoadFunction;\n";
  foreach($method['params'] as $param){
    $output .= "c.addParam(x); // replace x with a {$param} variable\n";
  }
  $output .= "c.call(\"{$method['name']}\");\n";
  return $output;
}