From: Mark Huang Date: Wed, 25 Oct 2006 20:32:44 +0000 (+0000) Subject: generate PHP API X-Git-Tag: pycurl-7_13_1~446 X-Git-Url: http://git.onelab.eu/?p=plcapi.git;a=commitdiff_plain;h=53da9c96660f565972d27381c2a2aa0983bfc24a generate PHP API --- diff --git a/php/.cvsignore b/php/.cvsignore new file mode 100644 index 0000000..da15e22 --- /dev/null +++ b/php/.cvsignore @@ -0,0 +1,2 @@ +methods.php +plcapi.php diff --git a/php/Makefile b/php/Makefile new file mode 100644 index 0000000..14cf10d --- /dev/null +++ b/php/Makefile @@ -0,0 +1,23 @@ +# +# (Re)builds PHP API. PHP classes must be defined in a single file. +# +# Mark Huang +# Copyright (C) 2006 The Trustees of Princeton University +# +# $Id: Makefile,v 1.1 2006/09/06 15:34:41 mlhuang Exp $ +# + +all: plcapi.php + +methods.php: methods.py ../PLC/__init__.py ../PLC/Methods/__init__.py + PYTHONPATH=.. python $< | \ + sed -e "s/^/ /" > $@ + +plcapi.php: header.php methods.php footer.php + sed -e "s/@DATE@/$$(date)/" header.php | \ + cat - methods.php footer.php > $@ + +clean: + rm -f plcapi.php methods.php + +.PHONY: all clean diff --git a/php/footer.php b/php/footer.php new file mode 100644 index 0000000..466ea72 --- /dev/null +++ b/php/footer.php @@ -0,0 +1,3 @@ +} + +?> diff --git a/php/header.php b/php/header.php new file mode 100644 index 0000000..6b3dd2c --- /dev/null +++ b/php/header.php @@ -0,0 +1,190 @@ + +// Copyright (C) 2005-2006 The Trustees of Princeton University +// +// $Id: gen_php_api.py,v 1.13 2006/03/23 04:29:08 mlhuang Exp $ +// +// + +require_once 'plc_config.php'; + +class PLCAPI +{ + var $auth; + var $server; + var $port; + var $path; + var $errors; + var $trace; + var $calls; + var $multicall; + + function PLCAPI ($auth, + $server = PLC_API_HOST, + $port = 8000, # PLC_API_PORT, + $path = PLC_API_PATH, + $cainfo = NULL) + { + $this->auth = $auth; + $this->server = $server; + $this->port = $port; + $this->path = $path; + $this->cainfo = $cainfo; + $this->errors = array(); + $this->trace = array(); + $this->calls = array (); + $this->multicall = false; + } + + function error_log($error_msg, $backtrace_level = 1) + { + $backtrace = debug_backtrace(); + $file = $backtrace[$backtrace_level]['file']; + $line = $backtrace[$backtrace_level]['line']; + + $this->errors[] = 'PLCAPI error: ' . $error_msg . ' in ' . $file . ' on line ' . $line; + error_log(end($this->errors)); + } + + function error () + { + if (empty($this->trace)) { + return NULL; + } else { + $last_trace = end($this->trace); + return implode("\\n", $last_trace['errors']); + } + } + + function trace () + { + return $this->trace; + } + + function microtime_float() + { + list($usec, $sec) = explode(" ", microtime()); + return ((float) $usec + (float) $sec); + } + + function call($method, $args = NULL) + { + if ($this->multicall) { + $this->calls[] = array ('methodName' => $method, + 'params' => $args); + return NULL; + } else { + return $this->internal_call ($method, $args, 3); + } + } + + function internal_call ($method, $args = NULL, $backtrace_level = 2) + { + $curl = curl_init(); + + // Verify peer certificate if talking over SSL + if ($this->port == 443) { + curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, 2); + if (!empty($this->cainfo)) { + curl_setopt($curl, CURLOPT_CAINFO, $this->cainfo); + } elseif (defined('PLC_API_SSL_CRT')) { + curl_setopt($curl, CURLOPT_CAINFO, PLC_API_SSL_CRT); + } + $url = 'https://'; + } else { + $url = 'http://'; + } + + // Set the URL for the request + $url .= $this->server . ':' . $this->port . '/' . $this->path; + curl_setopt($curl, CURLOPT_URL, $url); + + // Marshal the XML-RPC request as a POST variable + $request = xmlrpc_encode_request($method, $args); + curl_setopt($curl, CURLOPT_POSTFIELDS, $request); + + // Construct the HTTP header + $header[] = 'Content-type: text/xml'; + $header[] = 'Content-length: ' . strlen($request); + curl_setopt($curl, CURLOPT_HTTPHEADER, $header); + + // Set some miscellaneous options + curl_setopt($curl, CURLOPT_TIMEOUT, 30); + + // Get the output of the request + curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1); + $t0 = $this->microtime_float(); + $output = curl_exec($curl); + $t1 = $this->microtime_float(); + + if (curl_errno($curl)) { + $this->error_log('curl: ' . curl_error($curl), true); + $ret = NULL; + } else { + $ret = xmlrpc_decode($output); + if (is_array($ret) && xmlrpc_is_fault($ret)) { + $this->error_log('Fault Code ' . $ret['faultCode'] . ': ' . + $ret['faultString'], $backtrace_level, true); + $ret = NULL; + } + } + + curl_close($curl); + + $this->trace[] = array('method' => $method, + 'args' => $args, + 'runtime' => $t1 - $t0, + 'return' => $ret, + 'errors' => $this->errors); + $this->errors = array(); + + return $ret; + } + + function begin() + { + if (!empty($this->calls)) { + $this->error_log ('Warning: multicall already in progress'); + } + + $this->multicall = true; + } + + function commit () + { + if (!empty ($this->calls)) { + $ret = array(); + $results = $this->internal_call ('system.multicall', array ($this->calls)); + foreach ($results as $result) { + if (is_array($result)) { + if (xmlrpc_is_fault($result)) { + $this->error_log('Fault Code ' . $result['faultCode'] . ': ' . + $result['faultString'], 1, true); + $ret[] = NULL; + } else { + $ret[] = $result[0]; + } + } else { + $ret[] = $result; + } + } + } else { + $ret = NULL; + } + + $this->calls = array (); + $this->multicall = false; + + return $ret; + } + + // + // PLCAPI Methods + // + diff --git a/php/methods.py b/php/methods.py new file mode 100755 index 0000000..0b54370 --- /dev/null +++ b/php/methods.py @@ -0,0 +1,83 @@ +#!/usr/bin/python +# +# Generates the PLCAPI interface for the website PHP code. +# +# Mark Huang +# Copyright (C) 2005 The Trustess of Princeton University +# +# $Id: gen_php_api.py,v 1.13 2006/03/23 04:29:08 mlhuang Exp $ +# + +import os, sys +import time + +from PLC.API import PLCAPI +from PLC.Method import * +from PLC.Auth import Auth + +# Class functions +api = PLCAPI(None) + +api.methods.sort() +for method in api.methods: + # Skip system. methods + if "system." in method: + continue + + function = api.callable(method) + + # Commented documentation + lines = ["// " + line.strip() for line in function.__doc__.strip().split("\n")] + print "\n".join(lines) + print + + # Function declaration + print "function " + function.name, + + # PHP function arguments + args = [] + (min_args, max_args, defaults) = function.args() + parameters = zip(max_args, function.accepts, defaults) + + for name, expected, default in parameters: + # Skip auth structures (added automatically) + if isinstance(expected, Auth) or \ + (isinstance(expected, Mixed) and \ + filter(lambda sub: isinstance(sub, Auth), expected)): + continue + + # Declare parameter + arg = "$" + name + + # Set optional parameters to special value NULL + if name not in min_args: + arg += " = NULL" + + args.append(arg) + + # Write function declaration + print "(" + ", ".join(args) + ")" + + # Begin function body + print "{" + + # API function arguments + for name, expected, default in parameters: + # Automatically added auth structures + if isinstance(expected, Auth) or \ + (isinstance(expected, Mixed) and \ + filter(lambda sub: isinstance(sub, Auth), expected)): + print " $args[] = $this->auth;" + continue + + if name in min_args: + print " $args[] = $%s;" % name + else: + print " if ($%s !== NULL) { $args[] = $%s; }" % (name, name) + + # Call API function + print " return $this->call('%s', $args);" % method + + # End function body + print "}" + print