Comments (17)
That sure is possible by creating your own custom assembler that contains the code-geberation for this specific type of setter. You might want to place it after the regular FluentSetterAssembler
and remove the set method if it already exist.
As a base, you could start by copying this class and alter it to your needs:
https://github.com/phpro/soap-client/blob/master/src/Phpro/SoapClient/CodeGenerator/Assembler/FluentSetterAssembler.php
You might also need to create a code generation rule that matches on both a TYPE name and a PROPERTY name. Unless you want to apply it on any "Description" property.
from ext-soap-engine.
That's also an option.
You could even add the <![CDATA[ ]]>
part and check to conditionally run htmlentities based on that as well.
At least now you have an idea on how to tackle the issue :)
from ext-soap-engine.
That´s exactly what makes this framework so powerful ❤️ 😊
from ext-soap-engine.
Hello,
The easiest way forward is to add a Type converter:
https://github.com/php-soap/ext-soap-engine#typeconverter
The problem here, is that the Description
element is a regular xsd:string
element. It would have been nicer if it were a separate XSD type that could be overwritten.
You can fiddle around with this version a bit in your codebase to see how it behaves.
I tested it from my side and should work OK on basic data - assuming all other HTML fields expect CDATA as well.
<?php
use Soap\ExtSoapEngine\Configuration\TypeConverter\TypeConverterInterface;
use VeeWee\Xml\Dom\Document;
class CDataHtmlStringConverter implements TypeConverterInterface {
public function getTypeNamespace(): string
{
return 'http://www.w3.org/2001/XMLSchema';
}
public function getTypeName(): string
{
return 'string';
}
public function convertXmlToPhp(string $xml)
{
$doc = Document::fromXmlString($xml);
return $doc->toUnsafeDocument()->textContent;
}
public function convertPhpToXml($value): string
{
if (\strip_tags((string) $value) !== $value) {
return '<value><![CDATA['.$value.']]></value>';
}
return '<value>'.htmlentities($value).'</value>';
}
}
This converter will:
- Check if the string contains HTML tags, if so - it will use CDATA.
- If not, it will use regular string encoding (with htmlentities)
The strings that are coming in, are currently just being passed as-is.
So if you get HTML back wrapped in CDATA, it will contain the data without any html entities.
Since you will be overwriting base xsd strings with this converter - it is a quite impacting change.
Make sure to test it inside your application broadly :)
An alternative approach, could be the usage of SoapVar instead of a plain string:
'Description' => new \SoapVar('<ns1:Description><![CDATA[<html><head><title>hello world</title></head></html>]]></ns1:Description>', XSD_ANYXML),
Do note that you need to pass the whole XML tag with a hardcoded namespace. Currently the WSDL only contains one namespace, so that is not a big issue. But if it changes at some point, it might break this logic.
from ext-soap-engine.
dear toon, thanks a lot for your quick reply !!
i agree, that the "TypeConverter" is dangerous in some way.
is there a way to use a "TypeConverter" only for specific XML elements ???
from ext-soap-engine.
No, the type-converter has no knowledge of the context it operates on.
It only operates on type:
https://www.php.net/manual/en/soapclient.construct.php#soapclient.construct.options.typemap
As long as your inputs don't (accidentally) contain any HTML tags, it should work just fine with the type converter. It could as well be that the WS accepts CDATA everywhere, making it a non-issue. However, I agree that it would be nicer if they created a custom xsd type for this explicitally in their WSDL.
Since it is something internally in ext-soap, there is nothing we can do about it from this package - until we build our own encoding/decoding system from scratch.
from ext-soap-engine.
what do you think about this idea:
i could implement a comment in my HTML that is only used in "Description", something like:
<!-- USE-CDATA-HERE -->
and instead of
if (\strip_tags((string) $value) !== $value) {
I could search for exactly that (USE-CDATA-HERE) string 🤔
from ext-soap-engine.
that sounds even better, I will run some tests on that 😊
from ext-soap-engine.
@veewee may i ask:
does this code (the typeconverter) has to be placed in the "config" or somewhere else, too ??
from ext-soap-engine.
The typemap must be configured on the ExtSoapOptions
in the generated factory:
https://github.com/phpro/soap-client/blob/master/docs/cli/generate-clientfactory.md
The config.php
in phpro/soap-client
is rather to tell code generation how to load the WSDL metadata.
(That logic will be simplified in v3 a bit by using a separate factory for code generation that doesnt take any ext-soap options anymore.)
from ext-soap-engine.
okay, got it. will try, thanks !!
from ext-soap-engine.
@veewee pardon, i have to ask. using "htmlentities" in the "convertPhpToXml" function gives me empty tags when using a string like Test 123 45°
- I guess because of the °
. so I have to ask: did you maybe mean htmlspecialchars
instead of htmlentities
🤔
from ext-soap-engine.
htmlentities
can take the ENT_QUOTES
flag. I've used that function because it handles other special characters besides the regular html once as well. But you can play around with that and see what works for you.
(you could also use DOMDocument to build valid xml - but it seems I haven't got any builder for cdata yet.)
I am a bit confused on why a quote will result in an empty tag though:
<hello>world"</hello>
This is perfectly valid - unless it gets injected in an attribute.
from ext-soap-engine.
The problem seems to be the the "degree" sign (in my example) , I am confused as well. So I switched to "htmlspecialchars" and that worked, because the ° sign doesn't need to be encoded...
I can create a demo repository in case you like to check that.....?
from ext-soap-engine.
i guess i will stick with the 2nd solution, because it´s too dangerous in my eyes to touch "everything", when there is only one specific tag, that needs to be changed.
@veewee is there any method available to change a specific variable inside a specific class while classes get generated ?
so that this:
public function setDescription(string $Description)
{
$this->Description = $Description;
return $this;
}
becomes this:
public function setDescription(string $Description)
{
if (!empty($Description)) {
$this->Description = new SoapVar('<ns1:Description><![CDATA['.$Description.']]></ns1:Description>', XSD_ANYXML);
}
return $this;
}
❓ ❓
from ext-soap-engine.
Related Issues (8)
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from ext-soap-engine.