XSD schema based XML validation in PHP unit test - php

I am developing a PHP-powered application component which exports some data to an XML file which must follow a scheme defined by XSD file. I know how to validate the file manually, but it would be very handy if this could be done within unit tests.
Is there any library or framework available which can me help doing that?

One possibility would be to use DOMDocument::schemaValidate or DOMDocument::schemaValidateSource. Since either of those two methods returns a boolean value, you could then assert that the returned value is true.

This PHPUnit XSD validation lib defines a custom PHPUnit_Framework_Constraint uses DOMDocument::schemaValidate.
The advantage is that it gives a useful error when the validation fails, rather than just saying that 'false is not true'.
Usage
$constraint = new Jasny\PHPUnit\Constraint\XSDValidation("myschema.xsd");
$xml = $this->object->doSomething();
$this->assertThat($xml, $constraint);
Note: This is a shameless plug of my own open source library.

Related

Couchbase - creating design documents through API

I've been using Couchbase for a large project where we only consume data, but have no requrirement to actually write to the Couchbase cluster. I want to write some management tools and be able to create Design Documents and Views through the API and not the web console.
Creating Documents is not an issue at all, but whenever I use setDesignDoc() I get the following error message:
Fatal error: Uncaught exception 'CouchbaseLibcouchbaseException' with message 'Failed to store design doc: Invalid input/arguments' in ....
I can get the actual view data from the source with getDesignDoc() and use it for the creating that design document on the destination server like so:
$connandleDestination->setDesignDoc( "myDesignDoc", $connSource->getDesignDoc("myDesignDoc") );
And that's where I get the above error message.
I'm using the PHP SDK by the way with the latest version against Couchbase 2.5.1
Can you confirm if what you've given as your example is the exact code you're using?
$connandleDestination->setDesignDoc( "myDesignDoc", $connSource->getDesignDoc("myDesignDoc") );
What you've given would not work as, from the API docs, the syntax is as follows:
setDesignDoc(string $name, string $document) : bool
Hence, it would appear you are trying to set a new doc, myDesignDoc to be equal to the design doc myDesignDoc, which would either not exist, or have no effect (as setting something to equal itself causes no change - and creating a new design doc with the name of an existing one will simply overwrite it).
Did you instead mean to just use get()? get() would return a document (which would be valid in the setDesignDoc input, and that document could have the same name as the new design doc to be created.

Zend Soap Server / WSDL

I've been working on a project (which I'll keep specific details out of this post with randomized data) that involves integrating our system (PHP 5.3.x+) with an API (they provided a SDK) of a major company. They provided a WSDL and claimed ours needed to match their methods and they provided examples of how output (XML generated by the Soap Server) should look.
Right now, everything has been working as expected. When I send a XML request from SoapUI (an app I'm using to test) it all processes properly and such, but the XML output isn't matching closely with their examples and we believe they said we must be close to their examples.
Basically, we created an agnostic class we initialize with a service name and it initializes into a non-agnostic class which is used via the following:
/**
* The following is used to process Soap Server based on config and any optional settings.
*
* #param string $className
* #param array $options
* #param object $config
* #return Zend_Soap_Server
*/
public static function init($className, Array $options = null, $config = null)
{
// Used to define the class and return object.
$soap_server = new Zend_Soap_Server(null, $options);
$soap_server->setClass($className, null, (isset($config) ? $config : null));
$soap_server->handle();
exit;
}
The problem itself lies within the outputted response. How would you guys suggest we build the XML output if they're very specific about everything?
1.) One of our methods is moneyTransferRequest. When I send the XML over for this, it does find the method and processes it. However, they want it to show the method name, in the response, as moneyTransferResponse but it outputs moneyTransferRequestResponse.
2.) Our output (for variables and such sent back as an object) has multiple variables, we'll say $money for example. The field for this would return as:
<money xsi:type="xsd:string">10.0</money>
They would like it to be:
<ns1:money xsi:type="xsd:string">10.0</money>
in the return.
I appreciate any help and input on the subject.
The key feature of SOAP is that it uses XML, and XML can come in a bunch of different styles but still mean the same.
I think (but I can only guess because you didn't provide details) that your two issues might be non-existing.
1.) The name of the response XML structure should align with the name mentioned in the WSDL. YOU are publishing the WSDL, so you should check if these two match. Note that the important entry point is the SOAP method - everything thereafter is defined in the WSDL itself, any consuming client should be able to figure it out as long as the names mentioned are correctly used.
2.) This is basically the same, but even easier: XML allows to use namespaces, and these can be defined in several locations, with the result being not literally the same, but every XML parser will understand that they are the same. So you should check whether the namespace that is required as "ns1" is mentioned in the XML header of your response. Every XML document has a base namespace, which does not need to be repeated on every element that belongs to it.
This is the case with the <money> element. Your style of writing uses that base namespace, their style of writing uses a namespace shortcut ns1 also introduced in the XML header, but not declared as the base namespace. So as long as there are traces of the correct XML namespace in both responses, I'd assume they are equivalent.
And the bad news would be that you cannot change how the PHP SoapServer generates the XML. You'd need to create your own implementation of a SOAP server, which I'd say is a complete waste of resources.

php SoapClient, __soapCall and __getLastRequest / __getLastResponse

I used a downloaded tool to auto-create a wrapper for a web service (fedex rate service) as it creates a really handy code base for accessing the service that auto-generates a class map and builds an auto-loading data structure by asking the web service itself for it's requirements and capabilities. It creates this wrapper as an 'extend' of SoapClient itself.
The only problem is, that it makes the separate service calls using an abstract wrapper that utilizes the __soapCall method. The problem that I've noticed with this is that it apparently doesn't populate anything where you can retrieve the XML from the calls themselves. Whenever I call __getLastRequest or __getLastResponse, they just return null even though __soapCall('getRates', $args) returns a php object response from the service.
Short of my re-writing the auto-generated code to call $this->getRates($args) or something similar, is there any trick to seeing the XML used in the request and returned in the response when using __soapCall ?
Nevermind - I thought I had trace defaulted to true, and the reason i was getting back 'null' was that it was defaulting to false.
As long as I create the interface instance with the second argument array('trace'=>1) I'm getting the XML now.

JS Lexer to detect function calls

In order to localize strings used within my javascript, I want scan all my js files for such strings.
I am using a t() function to request string translations as follows:
t("Hello world");
or with dynamic portions:
t("Hello #user", {"#user": "d_inevitable"});
I want to detect all calls to the t() function and thus gather the strings contained in the first argument in a php "build" script, but skipping the following:
function foo(t) {
t("This is not the real t, do not localize this!");
}
function bar() {
var t = function(){}; //not the real t either...
}
function zoo() {
function t() {
//This also isn't the real t() function.
}
}
t("Translate this string, because this is the real t() in its global scope");
So the simple rule here is that the t function being invokes must be in global scope in order for the first argument to qualify as a translation string.
As a rule, dynamic runtime data as first argument is not allowed. The first argument to t() must always be a "constant" literal string.
I think php codesniffer will help me do it, however all the documentation I could find on it is about enforcing code standard (or detecting violations of it). I need lower level access to its js lexer.
My question is:
Would the php codesniffer's js lexer be able to help me solve my problem?
If so how do I access that lexer?
Are there any other php libs that could help me find the calls to t()?
Please do not suggest stand-alone regular expressions as they cannot possibly solve my problem in full.
Thank you in advance.
What you are describing is basically a coding standard. Certainly, ensuring strings are localised correctly is part of many project standards. So I think PHPCS is the right tool for you, but you will need to write a custom sniff for it because nothing exists to do exactly what you are after.
The best thing to do is probably clone the PHPCS Git repo from Github and then create a new directory under CodeSniffer/Standards to contain your custom sniff. Let's say you call it MyStandard. Make sure you create a Sniffs directory under it and then a subdirectory to house your new sniff. Take a look at the other standards in there to see how they work. You'll also find it easier to copy an existing ruleset.xml file from another standard and just change the cotent to suit you. if you don't want to include any other sniffs from anywhere (you just want to run this one check over your code) then you can just specify a name and description and leave the rest blank.
There is a basic tutorial that covers that.
Inside your sniff, you'll obviously want it to check JS files only, so make sure you specify that in the supportedTokenizers member var (also in the docs). This will ensure PHP and CSS files are always ignored.
When you get down to the actual checking, you'll have full low-level access to the parsed and tokenised content of your file. There are a lot of helper functions to check things like if the code inside other scopes, or to help you move backwards and forwards through the stack looking for bits of code you need.
TIP: run PHPCS using the -v option to see the token output on your file. It should help you see the structure more easily.
If you want to really do things properly, you can even create a nice unit test for your sniff to make sure it keeps running over time.
After all this, you'd check your code like this:
phpcs --standard=MyStandard /path/to/code
And you can use a lot of integrations that exist for PHPCS inside code editors.
You might decide to add a new more sniffs to the standard to check other things, which you can then do easily using your ruleset.xml file or by writing more custom sniff classes.
I hope that helps a bit. If you do decide to write your own sniff and need help, just let me know.

Generating WSDL when using PHP's native SOAP class?

I'm using the native SOAP class in PHP 5, having changed from NuSOAP as the native class is faster (and NuSOAP development seems to have ceased). However the PHP 5 SOAP lacks the ability to generate WSDL.
Has anyone experience of generating WSDL in PHP? If so, please recommend your preferred method.
Thanks.
Stuart,
If you or anyone else is looking for a solution to this problem here's what I did.
First get this script: http://www.phpclasses.org/browse/download/zip/package/3509/name/php2wsdl-2009-05-15.zip
Then look at its example files. After that I just sliced it the way I needed because I'm using codeigniter:
function wsdl(){
error_reporting(0);
require_once(APPPATH."/libraries/WSDLCreator.php"); //Path to the library
$test = new WSDLCreator("Webservice", $this->site."/wsdl");
//$test->includeMethodsDocumentation(false);
$test->addFile(APPPATH."/controllers/gds.php");
$test->addURLToClass("GDS", $this->site);
$test->ignoreMethod(array("GDS"=>"GDS"));
$test->ignoreMethod(array("GDS"=>"accessCheck"));
$test->createWSDL();
$test->printWSDL(true); // print with headers
}
That it, your all done.
Btw, I'm using SoapServer and SoapClient in php5+
You can try these options:
- https://code.google.com/p/php-wsdl-creator/ (GPLv3)
- https://github.com/piotrooo/wsdl-creator/ (GPLv3)
- http://www.phpclasses.org/package/3509-PHP-Generate-WSDL-from-PHP-classes-code.html (BSD like)
The first one might be your best option if the licence fits your project.
Generating a WSDL on the fly is not something that happens very often - it would tend to raise a few questions about the stability of your service!
Zend Studio can generate a WSDL from a PHP class, and there are a few other similar tools.
If you do need to generate the WSDL dynamically, take a look at Zend Framework library: Zend_Soap_AutoDiscover
Zend_Soap_AutoDiscover is a good alternative to NuSOAP. But, you can also create the WSDL file from scratch which can be very complicated and error prone. To ease this process, you can use an IDE to generate the WSDL file for your PHP functions and pass it as a parameter to your PHP SoapServer class. Check out the complete tutorial on How to generate wsdl for php native soap class

Categories