Getting attributes into SOAP elements is a bit of a hassle. The way they implemented it is a bit confusing.
First thing to do is add the attributes to the wsdl file that SoapServer
uses to correctly read and respond to the SOAP requests.
<xs:complexType name="encryptionContext">
<xs:simpleContent>
<xs:extension base="xs:string">
**<xs:attribute name="type" type="tns:encryptionType" />**
</xs:extension>
</xs:simpleContent>
</xs:complexType>
We will have to tell SoapServer
to use a php helper class by passing it in the options as classmap
:
$soap_server = new \SoapServer($wsdl_file, array(
'cache_wsdl' => 1,
'trace' => true,
'classmap' => array('mediaCollection' => 'SoapMediaHelper')
));
What we are mapping here is the SOAP element name mediaCollection
to one of our classes, SoapMediaHelper
. Instead of returning arrays, we can now return a class
, in this case, it's named SoapMediaHelper
. The class can have soap-element=>value pairs as well as soap-attribute=>value pairs.
Assuming we already have made a class that handles mediaCollection
s, this tells SoapServer
to map a class called SoapMediaHelper
to it. The class is really simple:
class SoapMediaHelper
{
public function __construct(Array $properties = array())
{
foreach ($properties as $key => $value) {
$this->{$key} = $value;
}
}
}
The properties of this class have to be populated. These properties should be both the tagname=>value pairs as well as the attribute name and value pair(s) for the attributes we want to add to our mediaCollection
. SoapServer
will figure out which is which according to our wsdl file.
We will still have to populate this object, which we can do with yet another class.
class SoapVarHelper
{
public function get($the_playlist, $playlist_id, $owned_by_user){
/* The SoapMediaHelper class is mapped to the mediaCollection wsdl.
* This is only needed to be able to set attributes on the XML nodes while using php's SoapServer
* */
$media_helper = new SoapMediaHelper($the_playlist);
/* For this type, the following xml attributes have to be set. (Not in the wsdl example above.) */
if($playlist_id === 'playlists'){
$media_helper->readOnly = false;
$media_helper->userContent = true;
$media_helper->renameable = false;
$media_helper->canDeleteItems = true;
}
if($owned_by_user){
$media_helper->readOnly = false;
$media_helper->userContent = false;
$media_helper->renameable = true;
$media_helper->canDeleteItems = true;
$media_helper->canReorderItems = true;
}
return new \SoapVar($media_helper, SOAP_ENC_OBJECT);
}
}
This class should be called with the normal tagname=>value pairs. It then adds the attributes we want. In this case conditionally. We feed our SoapMediaHelper
object to SoapVar
. (We told SoapServer
earlier that this is fine.)
Now the last thing we need to do is, in our mediaCollection
class, to use the helper SoapVarHelper
to return a SoapMediaHelper
(the one we told SoapServer
about earlier).
In our mediaCollection
we have a function get_metadata_for_root
:
public function get_metadata_for_root($user_id, $index, $count){
$titles = array(
'slides' => 'Featured',
);
$media_metadata = array();
foreach($titles as $key => $title){
$playlist = array(
'id' => $key,
'title' => $title,
'img' => $this->_utils->get_url() . '/public/sonos/images/browse-icons/icon-default-legacy.png'
);
**$media_metadata[] = $this->_soap_var_helper->get($playlist, $key, false);**
}
$res = array(
'count' => count($media_metadata),
'index' => 0,
'total' => count($media_metadata),
'mediaCollection' => $media_metadata
);
}
For every mediaCollection
result we pass it through the soap_var_helper
to make sure not only the element=>value pairs are added, but also the attributes that we want on it.
TO SUMMARIZE:
Make sure you feed the SoapServer
with a wsdl file, so it know the elements and the attributes.
In the SoapServer
options add classmap
in order to tell SoapServer
that it is fine when we feed it a SoapMediaHelper
object instead of the regular input.
Before responding to a request for, in this case, mediaCollection
, pass this response through the SoapMediaHelper
. The SoapVarHelper
will map all the properties=>value pairs as class properties, then the SoapMediaHelper
will add attributes (also as name=>value pairs) to it.
SoapServer
will take care of the rest.