Skip to content

Commit

Permalink
initial solution
Browse files Browse the repository at this point in the history
  • Loading branch information
Michael committed Sep 17, 2011
1 parent d3914bb commit bc1f964
Show file tree
Hide file tree
Showing 5 changed files with 318 additions and 0 deletions.
Empty file removed docs/api/test.xml
Empty file.
23 changes: 23 additions & 0 deletions library/App/Webservice/Calls.php
@@ -0,0 +1,23 @@
<?php
/**
* Created by JetBrains PhpStorm.
* User: Michael
* Date: 15.09.11
* Time: 06:44
* To change this template use File | Settings | File Templates.
*/
namespace App\Webservice;

class Calls {
/**
* Returns the input string reversed
* @param string $input
* @return string
*/
public function reverseString($input = "") {
$sc = \Zend_Registry::get('sc');
$srv = $sc->getService('stringReverser');
return $srv->reverse($input);
}

}
147 changes: 147 additions & 0 deletions library/Boilerplate/Webservice/Soap/Autodiscover.php
@@ -0,0 +1,147 @@
<?php

namespace Boilerplate\Webservice\Soap;

class AutoDiscover extends \Zend_Soap_AutoDiscover {

private $_extra_params = array('apikey' => 'string');

public function __construct($strategy = true, $uri=null) {
parent::__construct($strategy,$uri);
}

/**
* overload the ZF method
*
* @param $function Zend_Server_Reflection_Function_Abstract function to add
* @param $wsdl Zend_Soap_Wsdl WSDL document
* @param $port object wsdl:portType
* @param $binding object wsdl:binding
* @return void
*/
protected function _addFunctionToWsdl($function, $wsdl, $port, $binding)
{
$uri = $this->getUri();

$prototype = null;
$maxNumArgumentsOfPrototype = -1;
foreach ($function->getPrototypes() as $tmpPrototype) {
$numParams = count($tmpPrototype->getParameters());
if ($numParams > $maxNumArgumentsOfPrototype) {
$maxNumArgumentsOfPrototype = $numParams;
$prototype = $tmpPrototype;
}
}
if ($prototype === null) {
require_once "Zend/Soap/AutoDiscover/Exception.php";
throw new \Zend_Soap_AutoDiscover_Exception("No prototypes could be found for the '" . $function->getName() . "' function");
}

// Add the input message (parameters)
$args = array();
if ($this->_bindingStyle['style'] == 'document') {
// Document style: wrap all parameters in a sequence element
$sequence = array();
foreach ($this->_extra_params as $param_name => $param_type) {
$sequenceElement = array(
'name' => $param_name,
'type' => $wsdl->getType($param_type)
);
if (in_array($param_name,$this->_extra_optional)) {
$sequenceElement['nillable'] = 'true';
}
$sequence[] = $sequenceElement;
}
foreach ($prototype->getParameters() as $param) {
$sequenceElement = array(
'name' => $param->getName(),
'type' => $wsdl->getType($param->getType())
);
if ($param->isOptional()) {
$sequenceElement['nillable'] = 'true';
}
$sequence[] = $sequenceElement;
}
$element = array(
'name' => $function->getName(),
'sequence' => $sequence
);
// Add the wrapper element part, which must be named 'parameters'
$args['parameters'] = array('element' => $wsdl->addElement($element));
} else {
// RPC style: add each parameter as a typed part
foreach ($this->_extra_params as $param_name => $param_type) {
$args[$param_name] = array('type' => $wsdl->getType($param_type));
}
foreach ($prototype->getParameters() as $param) {
$args[$param->getName()] = array('type' => $wsdl->getType($param->getType()));
}
}
$wsdl->addMessage($function->getName() . 'In', $args);

$isOneWayMessage = false;
if($prototype->getReturnType() == "void") {
$isOneWayMessage = true;
}

if($isOneWayMessage == false) {
// Add the output message (return value)
$args = array();
if ($this->_bindingStyle['style'] == 'document') {
// Document style: wrap the return value in a sequence element
$sequence = array();
if ($prototype->getReturnType() != "void") {
$sequence[] = array(
'name' => $function->getName() . 'Result',
'type' => $wsdl->getType($prototype->getReturnType())
);
}
if (isset($this->_extra_out)) {
foreach ($this->_extra_out as $out_name => $out_type) {
$sequence[] = array(
'name' => $out_name . 'Result',
'type' => $wsdl->getType($out_type)
);
}
}

$element = array(
'name' => $function->getName() . 'Response',
'sequence' => $sequence
);
// Add the wrapper element part, which must be named 'parameters'
$args['parameters'] = array('element' => $wsdl->addElement($element));
} else if ($prototype->getReturnType() != "void") {
// RPC style: add the return value as a typed part
$args['return'] = array('type' => $wsdl->getType($prototype->getReturnType()));
}
$wsdl->addMessage($function->getName() . 'Out', $args);
}

// Add the portType operation
if($isOneWayMessage == false) {
$portOperation = $wsdl->addPortOperation($port, $function->getName(), 'tns:' . $function->getName() . 'In', 'tns:' . $function->getName() . 'Out');
} else {
$portOperation = $wsdl->addPortOperation($port, $function->getName(), 'tns:' . $function->getName() . 'In', false);
}
$desc = $function->getDescription();
if (strlen($desc) > 0) {
//$wsdl->addDocumentation($portOperation, $desc);
}

// When using the RPC style, make sure the operation style includes a 'namespace' attribute (WS-I Basic Profile 1.1 R2717)
if ($this->_bindingStyle['style'] == 'rpc' && !isset($this->_operationBodyStyle['namespace'])) {
$this->_operationBodyStyle['namespace'] = ''.$uri;
}

// Add the binding operation
$operation = $wsdl->addBindingOperation($binding, $function->getName(), $this->_operationBodyStyle, $this->_operationBodyStyle);
$wsdl->addSoapOperation($operation, $uri . '#' .$function->getName());

// Add the function name to the list
$this->_functions[] = $function->getName();
}



}
99 changes: 99 additions & 0 deletions library/Boilerplate/Webservice/Soap/Server.php
@@ -0,0 +1,99 @@
<?php
/**
* Created by JetBrains PhpStorm.
* User: Michael
* Date: 16.09.11
* Time: 03:59
* To change this template use File | Settings | File Templates.
*/

namespace Boilerplate\Webservice\Soap;

class Server extends \Zend_Soap_Server {

private $allowedKeys = array('123456');

public function __construct($wsdl = null, array $options = null) {

parent::__construct($wsdl,$options);

}

/**
* Handle a request
* overload the default ZF method
*
* @param string $request Optional request
* @return void|string
*/
public function handle($request = null) {

if (null === $request) {
$request = file_get_contents('php://input');
}
if (strlen($request) == 0) {
$soap = $this->_getSoap();
$soap->fault(401 , 'Message contains no XML');
}

$dom = new \DOMDocument();
if(!$dom->loadXML($request)) {
$soap = $this->_getSoap();
$soap->fault(401 , 'Message contains invalid XML');
} else {
//strip out api_key stuff
$xml = simplexml_load_string($request);
$url = 'http://'.$_SERVER['HTTP_HOST'].$_SERVER['REQUEST_URI'];

$children = (array) $xml->children('http://schemas.xmlsoap.org/soap/envelope/')
->Body
->children($url);

$methods = array_keys($children);
$method = $methods[0];

$soap = $this->_getSoap();

$apikey = (string) $xml->children('http://schemas.xmlsoap.org/soap/envelope/')
->Body
->children($url)
->{$method}
->children()
->apikey;

if ($this->_hasAccess($apikey, $method)) {
//strip api info
unset($xml->children('http://schemas.xmlsoap.org/soap/envelope/')
->Body
->children($url)
->{$method}
->children()
->apikey);

$request = $xml->asXml();

//remove whitespace & empty lines
$request = trim($request);
$request = preg_replace("/(^[\r\n]*|[\r\n]+)[\s\t]*[\r\n]+/", "\n", $request);
return parent::handle($request);
} else {
$soap = $this->_getSoap();
$soap->fault(403 , 'Access forbidden');
}
}
}

/**
* check if apikey has access to method
*
* @param string $apikey
* @param string $method
* @return bool
*/
protected function _hasAccess($apikey, $method) {
return in_array($apikey, $this->allowedKeys);
}

}


49 changes: 49 additions & 0 deletions public/ws/soap.php
@@ -0,0 +1,49 @@
<?php
// Define path to application directory
defined('APPLICATION_PATH')
|| define('APPLICATION_PATH', realpath(dirname(__FILE__) . '/../../application'));

// Define application environment
defined('APPLICATION_ENV')
|| define('APPLICATION_ENV', (getenv('APPLICATION_ENV') ? getenv('APPLICATION_ENV') : 'development'));

// Ensure library/ is on include_path
set_include_path(implode(PATH_SEPARATOR, array(
realpath(APPLICATION_PATH . '/../library'),
get_include_path(),
)));

include "Zend/Loader/Autoloader.php";
$l = Zend_Loader_Autoloader::getInstance();
$l->registerNamespace('Boilerplate_');
$l->registerNamespace('Elastica_');
include "App/Webservice/Calls.php"; //?
// Create application, bootstrap, and run
$application = new Zend_Application(
APPLICATION_ENV,
APPLICATION_PATH . '/configs/application.ini'
);

$application->bootstrap();

ini_set("soap.wsdl_cache_enabled", 0);//for development
if (isset($_GET['WSDL'])) {
// Auto generate WSDL
$autodiscover = new \Boilerplate\Webservice\Soap\AutoDiscover();
//$autodiscover = new Zend_Soap_AutoDiscover();
// Set endpoint URL
$autodiscover->setUri('http://localhost:8080/ws/soap.php');
$autodiscover->setClass("\\App\\Webservice\\Calls");
$autodiscover->handle();
} elseif (isset($_GET['INTERNALWSDL'])) {
$autodiscover = new Zend_Soap_AutoDiscover();
$autodiscover->setClass('\\App\\Webservice\\Calls');
$autodiscover->setUri('http://localhost:8080/ws/soap.php');
$autodiscover->handle();
} else {
$options = array('soap_version' => SOAP_1_2);
$server = new \Boilerplate\Webservice\Soap\Server('http://localhost/ws/soap.php?INTERNALWSDL=1', $options);
$server->setObject(new \App\Webservice\Calls());
$server->handle();
}

0 comments on commit bc1f964

Please sign in to comment.